Annonce

Réduire
Aucune annonce.

Voir ce que le navigateur envoie en temps réel

Réduire
X
  • Filtre
  • Heure
  • Afficher
Tout nettoyer
nouveaux messages

  • Voir ce que le navigateur envoie en temps réel

    Bonjour,

    Voici un petit programme pour système Linux et compatibles. Il permet de voir ce qui transite depuis et vers le navigateur et même d'altérer ces données.

    Pour l'installer, il faut installer le pakage contenant g++ (compilateur C++). Télécharger relais-sources.zip et le copier dans un dossier, ensuite :
    Code:
    tar -xf relais-sources.zip
    cd relais-sources
    make
    make clean
    Pour commencer, taper "./relais -e 2100" dans le terminal. Puis, dans le navigateur, aller dans la section proxy et mettre 127.0.0.1 comme ip et 2100 comme port TCP. Cela affiche ce qu'envoie le navigateur aux serveurs. Un bon moyen de se former au protocole HTTP. Attention, ce programme ne fonctionne que pour HTTP, pas HTTPS.

    Une fois qu'on a une idée un peu plus claire de la pratique de HTTP, on peut s'amuser à altérer les données envoyées afin de rajouter ou supprimer des entêtes (voir regles.txt). A titre d'anecdote, il y a eu certains logiciels web (en php notamment) qui se faisaient abuser en notant l'adresse ip indiquée par l'entête "X-Forwarded-For:" au lieu de la véritable ip se connectant au serveur. "X-Forwarded-For:" est utilisée par un proxy non-anonyme pour cafarder l'ip de celui qui l'utilise. De sorte que maquiller son adresse ip était un jeu d'enfant selon le logiciel. Mais cela est a priori du passé.

    Ce programme est très imparfait dans la mesure où j'ai dû le rafistoler à la dernière minute pour qu'il supporte le standard C++11. De plus, l'un des bugs les plus gênants que je pensais avoir traité semble avoir réapparu (le port d'écoute du programme est souvent occupé lorsqu'on le relance, il faut fermer le navigateur et attendre avant de le relancer ou bien changer de port). J'essaierai de m'y pencher (je subodore une évolution du comportement de certains appels systèmes).

    Enfin, il s'agit d'un exemple relativement simple d'utilisation de "sockets multithreaded" sous linux en C++ qui pourrait intéresser quelques programmeurs en herbe.
    Fichiers attachés
    Dernière modification par Icarus, 07 janvier 2018, 12h52.

  • #2
    Le programme est de toi ?
    Si oui, pourquoi ne pas avoir mis le code sur un GitHub ?
    Mieux, pourquoi ne le mettrais tu pas en publique sur le GitLab de HK si le code est de toi. Ça permettrait d'augmenter sa visibilité ainsi que de permettre une relecture simple avantage téléchargement et de possibles pull requests.

    Sinon le le tout me semble très intéressant ainsi à première vue (je n'aì pas encore lu le code).
    Un manuel plus complet serait intéressant pour savoir comment manipuler le trafic

    Commentaire


    • #3
      Oui, le programme est de moi. Si tel n'avait pas été le cas, j'aurais cité l'auteur.

      Je ne connais pas le fonctionnement de GitHub. Cela dit, si ce programme me fut utile autrefois, je pense qu'à présent, c'est plus un outil pédagogique qu'autre chose. J'ai en effet réalisé à quel point le protocole HTTPS avait pris de la place sur le web (si j'ai bien compris, Google y est pour beaucoup). Car en vérité, il faudrait qu'il supporte ce protocole même si la théorie voudrait que l'on ne puisse pas décrypter les paquets émis par le navigateur. La pratique le permet cependant mais j'ai peur que ce soit très long et très compliqué.

      Et puis, il reste ce problème de port occupé qui fait qu'on ne peut relancer le logiciel avant quelques minutes (le temps que les connexions en TIME_WAIT soient effacées). Il faudrait que je puisse passer outre cela (cela fonctionnait sur une vieille fedora et un non moins vieux PC-BSD). A présent, que ce soit sur GhostBSD, Ubuntu ou Fedora, le problème est là et bien là. C'est insupportable lorsqu'on tâtonne pour faire marcher un jeu de règles.

      Enfin, la terminaison du programme provoque des erreurs lorsque - semble-t-il - aucun bloqueur de pub n'est activé dans le navigateur. Ceci plus le problème de port occupé me dit qu'il faut revoir profondément le mécanisme de raccrochage unilatéral des connexions.

      Commentaire


      • #4
        Bon, j'avance. Il semble que j'ai réussi à trouver comment résoudre le problème de port occupé.

        Initialement, j'avais utilisé le réglage d'option suivant :
        Code:
        sock = socket(AF_INET, SOCK_STREAM, 0);
        if (sock == -1) { bRun = false; return; }
        
        // Permet d'éviter les erreurs de port déjà pris alors qu'il est en time wait
        setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, NULL, 0);
        Cela marchait très bien. Mais int setsockopt(int socket, int level, int option_name, const void *option_value, socklen_t option_len) a du évoluer d'une façon ou d'une autre. Tout se passe comme si le fait de ne pas spécifier option_value (et donc option_len) la fait échouer. Je n'ai pas eu le temps de me pencher sur le pourquoi et comment de la chose mais le code suivant marche :
        Code:
        // Permet d'éviter les erreurs de port déjà pris alors qu'il est en time wait
        int option = 1;
        setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &option, sizeof(option));
        A changer, ligne 390 de relais_coeur.cpp.

        Je fournirai l'ensemble corrigé dès que possible.
        Dernière modification par Icarus, 07 janvier 2018, 16h11.

        Commentaire


        • #5
          Bonsoir,

          Oui c'est pas évident à trouver une doc claire pour cette fonction, mais celle-ci retourne quelque chose, pourquoi ne pas avoir testé son retour ?

          Voici une doc claire pour t'aider à retenir la prochaine fois...

          optval is a pointer to a variable from which the new value of the option is fetched by setsockopt, or into which the current value of the option is stored by getsockopt. The size of this variable is specified by the final argument optlen, as a value for setsockopt and as a value-result for getsockopt
          Alors si je prends au mot ce qui est écrit ci-dessus, je dirais même sizeof(int *), mais je me trompe peut-être.

          Commentaire


          • #6
            Merci pour ta réponse.

            Alors effectivement, c'est une mauvaise pratique de ne pas examiner le retour d'une fonction. Mais c'est un raccourci que j'ai pris à l'époque car celle-ci n'est pas vitale pour le programme. J'avoue : ce n'est pas le code le plus propre que j'ai pondu. Cela m'aurait permis cependant de m'apercevoir qu'elle renvoyait à présent EINVAL soit invalid argument.

            J'ai lu et relu le man de la fonction setsockopt pour finalement comprendre (avec d'autres documents mais je n'avais pas trouvé celui que tu donnes qui est assez clair) que SO_REUSEADDR attend que option_value soit donnée comme un entier. De ce que j'ai vu, soit c'est 0 et SO_REUSEADDR est désactivé soit c'est > 0 et c'est activé. Le problème, c'est que ce n'est pas clair du tout dans la mesure où d'autres SO_xxx n'attendent rien de la part de option_value (qu'on peut donc mettre à NULL).

            Au final, je me demande comment ça a pu marcher en l'état mais ça a marché, c'est certain. Je n'ai eu alors aucune envie de tester le retour de cette fonction puisqu'elle fonctionnait à l'évidence. J'ai essayé de chercher de vieilles pages man pour avoir une explication mais je n'ai rien trouvé concernant Linux. A savoir que ce programme a été écrit il y a plus de 10 ans.

            S'agissant de sizeof(), c'est bien entendu la variable utilisée et non son pointeur car les pointeurs font toujours la même taille (selon le système d'adressage retenu 32 ou 64 bits).

            J'ai corrigé en conséquence le contenu téléchargeable de mon premier message.
            Dernière modification par Icarus, 07 janvier 2018, 22h20.

            Commentaire


            • #7
              Sur le conseil de Anonyme77, j'ai mis ce programme sur le GitLab, non sans mal d'ailleurs puisque j'ignore à peu près tout de son fonctionnement : http://git.hackademics.fr/Icarus/Relais_Linux.git

              A ce propos, GitLab n'affiche pas les caractères accentués (bon, jusque-là, je suis plutôt habitué à vivre avec ce genre de choses) mais que pour certains fichiers et je n'y ai pas trouvé de logique...
              Dernière modification par Icarus, 08 janvier 2018, 22h10.

              Commentaire


              • #8
                Pour moi l'équivalent de cette phrase que j'indique en rouge, est équivalent à:

                La taille de la variable optval qui est un pointeur est spécifié par l'argument optlen.

                Commentaire


                • #9
                  On ne va pas épiloguer sur ce point de détail mais cela n'a aucun sens de transmettre la taille d'un pointeur puisqu'elle ne change pas. Le code sous-jacent a besoin de la taille de la variable pour pouvoir l'adresser correctement de sorte qu'on puisse lui transmettre toutes sortes de types différents. C'est commun comme façon de faire.

                  Relis bien et considère
                  optval is a pointer to a variable
                  puis
                  The size of this variable is specified by the final argument optlen
                  Tu vois bien que c'est la taille de la variable dont il est question et non de optval qui n'est qu'un pointeur.

                  Commentaire


                  • #10
                    Bah si tu connais le level et l'optname, tu sais que c'est un type int concernant le Datatype, donc la taille est l'adresse d'un entier int.

                    Mais bon tant que ça fait le café, l'essentiel est là !

                    Commentaire


                    • #11
                      Bonjour,

                      Petite démo de relais utilisé conjointement à Tor :



                      L'un des terminaux affiche les paquets reçus, l'autre les paquets envoyés et le dernier est l'exécution de Tor.

                      On remarquera que l'entête User-Agent a été manipulée, passant de "Mozilla/5.0 (X11; FreeBSD amd64; rv:57.0) Gecko/20100101 Firefox/57.0" à "Rêve d'Icare", comme le montre le site http://www.procato.com/my+headers/. Une manipulation bien innocente et avec peu d'effets secondaires.

                      Comment en suis-je arrivé là ? Simple.

                      Dans le terminal "Paquets envoyés", il faut lancer la commande : ./relais -e -f regles 2100 127.0.0.1 2101

                      Un fichier de règles (dont le nom est "regles" ici) doit être rédigé comme suit :
                      Code:
                      Out DelUp(\r)             Mozilla/5.0 (X11
                      Out InsUp(User-Agent:,\s) Rêve d'icare\r
                      Attention, en lieu et place de "Mozilla/5.0 (X11", il faut mettre le début exact du User-Agent qu'envoie votre navigateur, sinon cela ne marchera pas.

                      Dans le terminal "Paquet reçus", il faut exécuter : ./relais -r 2101 127.0.0.1 9050

                      Dans un autre terminal, lancer Tor (il écoute par défaut sur TCP 9050).

                      Enfin, configurer correctement son navigateur pour qu'il utilise un proxy SOCK V5 sur le port 2100. On notera que le proxy DNS SOCK V5 est désactivé pour l'occasion (il faut normalement l'activer pour aller dans le Darknet).



                      Le principe n'est guère mystérieux : une instance de relais prend en charge les demandes du navigateur et au passage manipule les données envoyées puis, il transfère les paquets à une seconde instance de relais qui écoute sur le port TCP 2101 (celle-ci affiche les paquets reçus). Ensuite, cette seconde instance renvoie le trafic vers Tor sur le port TCP 9050.
                      Dernière modification par Icarus, 14 janvier 2018, 01h19.

                      Commentaire

                      Chargement...
                      X