- httptap est un outil qui lance un programme Linux sous la forme
httptap -- <command>et affiche dans le terminal un résumé des requêtes et réponses HTTP/HTTPS produites par ce programme - Il fonctionne sans droits root, sans démon, sans modification globale du système, sans règles
iptablesni changement de table de routage ; l’exécutable est un binaire Go statique sans dépendances - Il est actuellement réservé à Linux et ses auteurs indiquent qu’il serait difficile à porter vers d’autres systèmes d’exploitation, car il utilise des appels système propres à Linux comme les network namespaces
- Le trafic HTTPS est déchiffré en injectant dans l’environnement du sous-processus une autorité de certification créée à la volée ; l’outil fonctionne comme un proxy TCP transparent qui traite les paquets IP/TCP/UDP bruts
- Sur Ubuntu 23.10 et versions ultérieures, ou sur les distributions qui désactivent par défaut les user namespaces non privilégiés, une configuration
sysctlpeut être nécessaire ; certaines limites existent, comme l’impossibilité d’accepter des connexions entrantes et la nécessité d’accéder à/dev/net/tun
Ce que fait httptap
- httptap enveloppe l’exécution de n’importe quelle commande Linux et affiche les requêtes HTTP/HTTPS qu’elle émet
- La forme d’utilisation de base est
httptap -- <command> - Par exemple, lors de l’exécution de
curl https://monasticacademy.org, il affiche la requêteGET https://monasticacademy.org/et la réponse308
- La forme d’utilisation de base est
- Dans l’exemple Python
requests.get('https://monasticacademy.org'), il suit les redirections et affiche deux requêtes- La première requête reçoit un
308pourhttps://monasticacademy.org/ - La suivante reçoit un
200pourhttps://www.monasticacademy.org/
- La première requête reçoit un
Installation et conditions d’exécution
- Les binaires précompilés peuvent être installés en récupérant la tarball de la dernière release
- Toutes les versions et architectures CPU sont disponibles dans les releases
- Une installation via Go est également proposée
go install github.com/monasticacademy/httptap@latest
- En général, l’exécution ne nécessite pas de droits root, de démon ni de configuration globale du système
- Ne crée pas de règles
iptables - Ne modifie pas la table de routage
- N’affecte généralement pas les autres processus du même système
- Ne crée pas de règles
- Sur Ubuntu 23.10 et versions ultérieures, les réglages suivants sont nécessaires
sudo sysctl -w kernel.apparmor_restrict_unprivileged_unconfined=0sudo sysctl -w kernel.apparmor_restrict_unprivileged_userns=0
- Ces réglages désactivent des fonctionnalités récentes du noyau qui restreignent les user namespaces non privilégiés
- Ils peuvent aussi être nécessaires sur d’autres distributions qui désactivent par défaut les user namespaces non privilégiés
- Une solution consistant à fournir un profil AppArmor avec httptap est à l’étude afin de supprimer ce besoin
Exemples d’utilisation
- L’exemple avec
curl -s https://buddhismforai.sutra.co -o /dev/nullmontre que le serveur renvoie une redirection302 - Si l’on suit les redirections, comme avec
curl -sL, les requêtes supplémentaires sont également affichées- La première requête renvoie
302 - La deuxième requête renvoie
200pour l’URL cible de la redirection
- La première requête renvoie
- Dans l’exemple
gcloud compute instances list, on peut voir les endpoints HTTP utilisés en interne par la CLI Google CloudPOST https://oauth2.googleapis.com/tokenGET https://compute.googleapis.com/compute/v1/.../aggregated/instances?...- La sortie habituelle de
gcloudet les logs de requêtes de httptap apparaissent ensemble
- Dans l’exemple
kubectl get all, les requêtes vers le serveur d’API Kubernetes sont affichées--https 443 6443fait traiter les connexions TCP sur les ports 443 et 6443 comme du HTTPS--insecure-skip-tls-verifyest nécessaire parce que kubectl n’utilise pas l’autorité de certification générée par httptap
- L’exemple
curl --doh-url https://cloudflare-dns.com/dns-querymontre un flux DNS-over-HTTP- Les deux premières requêtes correspondent aux résolutions DNS
- Les deux suivantes sont des requêtes HTTP classiques vers le site cible
- En utilisant les options
--headet--bodyensemble, les en-têtes HTTP et la charge utile brute sont affichés
Sortie HAR
- L’option
--dump-har out.harpermet de dumper les requêtes et réponses HTTP dans un fichier HAR - Le fichier HAR généré peut être visualisé avec divers visualiseurs HAR
- Google HAR Analyzer est donné comme exemple
- L’exemple de HAR contient une requête
308 Redirectvershttps://monasticacademy.orget une requête200 OKvershttps://www.monasticacademy.org
Accès à localhost
- Pour accéder à un port localhost de l’hôte depuis httptap, il faut utiliser
host.httptap.localou169.254.77.65au lieu delocalhost - Chaque network namespace Linux dispose de son propre périphérique loopback
127.0.0.1; ainsi,127.0.0.1:1234dans httptap n’est pas la même adresse et le même port que sur l’hôte - httptap contourne ce problème en codant en dur le routage de
169.254.77.65vers127.0.0.1
Sous-processus démonisés
- Sous Linux, il est possible de créer des sous-processus qui continuent d’exister après la fin du processus d’origine
- C’est un mode de fonctionnement courant pour les démons et les applications GUI lancées depuis la ligne de commande
- Lorsqu’un tel processus est exécuté sous httptap, le processus démonisé reste dans le network namespace de httptap
- L’option
--no-exitfait continuer le proxy et la journalisation de httptap même après la fin du sous-processus lancé immédiatement- Dans l’exemple avec Visual Studio Code, la forme utilisée est
httptap --no-exit -- code --ignore-certificate-errors . - Pour quitter, il faut fermer VS Code puis arrêter httptap avec
Ctrl+C
- Dans l’exemple avec Visual Studio Code, la forme utilisée est
- Si httptap s’arrête d’abord sans
--no-exit, le network namespace reste présent, mais plus aucun processus ne lit les paquets du périphérique TUN, ce qui coupe la connexion réseau de l’application - Avec
setsid setsid curl http://httpbin.org/getet dans l’exemple Python utilisantfork,setsid,fork, l’absence de--no-exitprovoque aussi une erreurCould not resolve host
Fonctionnement interne
httptap -- <command>exécute<command>dans un network namespace isolé et déchiffre le trafic HTTPS en injectant une autorité de certification créée à la volée- Il crée un périphérique TUN Linux et configure l’environnement du sous-processus pour que tout le trafic réseau passe par ce périphérique
- Le trafic écrit vers le périphérique TUN est transmis au descripteur de fichier détenu par le processus qui a créé ce périphérique
- Modifier le network namespace racine affecterait tout le trafic du système ; httptap crée donc un network namespace séparé
- Ce namespace ne contient qu’un périphérique loopback et un périphérique TUN
- Le sous-processus est exécuté dans ce namespace
- Le trafic reçu depuis le périphérique TUN est constitué de paquets IP bruts
- httptap analyse les paquets IP et les paquets TCP/UDP qu’ils contiennent
- Il doit réécrire des paquets IP bruts vers le sous-processus
- Son implémentation TCP/IP maison omet de nombreuses parties du protocole TCP complet, mais fonctionne raisonnablement bien pour cet usage
- Quand le sous-processus envoie une requête à
www.example.com, httptap reçoit un TCP SYN destiné à l’IP cible et répond par un SYN+ACK- Il établit séparément une vraie connexion TCP vers l’IP cible via l’API de sockets classique du noyau Linux
- Il relaie ensuite les données dans les deux sens
- Cette architecture est celle d’un proxy TCP transparent traditionnel
- Le déchiffrement HTTPS est assuré par l’injection d’une autorité de certification
- Au démarrage, httptap génère une autorité de certification correspondant à une private key et à un certificat x509
- Il écrit le certificat dans un système de fichiers visible uniquement par le sous-processus
- Il définit des variables d’environnement visibles uniquement par le sous-processus pour ajouter cette autorité de certification à la liste de confiance
- Comme httptap possède la private key de l’autorité de certification, il peut prouver son identité comme s’il était le serveur avec lequel le sous-processus veut communiquer et lire les requêtes HTTP en clair
Limites
- L’outil est actuellement réservé à Linux et dépend d’appels système propres à Linux, comme les network namespaces
- Le processus ne peut pas écouter de connexions réseau entrantes
- L’accès à
/dev/net/tunest nécessaire - Toutes les requêtes ICMP echo sont renvoyées telles quelles, sans envoyer de paquets ICMP sur le réseau réel
2 commentaires
it was developed at the Monastic Academy in Vermont in the US. We believe that a monastic schedule, and the practice of the Buddhist spiritual path more generally, provide ideal conditions for technological development.
Avis de Hacker News
La section « How it was made » du README était presque aussi intéressante que l’outil lui-même.
On y explique qu’ils vivent et pratiquent ensemble sur un peu plus de 100 acres de terrain, récitent des mantras et méditent ensemble matin et soir, et organisent et participent chaque mois à environ une semaine de retraite de méditation. Le reste du temps, ils s’occupent ensemble du terrain, de l’entretien des bâtiments, de la cuisine, du ménage, de la planification, de la collecte de fonds et, depuis quelques années, du développement logiciel.
À une époque où le microcode et la logique causaient des problèmes à l’échelle de la nanoseconde, un ingénieur surmené aurait quitté son poste en laissant sur son terminal cette note en guise de lettre de démission : « Je pars dans une commune du Vermont et je ne m’occuperai plus d’unités de temps plus courtes que les saisons. »
La question de savoir si c’est une bonne idée, ou si cela mènera au résultat qu’ils imaginent, est un autre sujet.
L’association entre technologie et méditation m’attire. L’idée en elle-même est séduisante, mais la mettre réellement en pratique doit sans doute être difficile. Cela ressemble à une sorte de Recurse bouddhiste.
httptap est un traceur HTTP au niveau du processus, exécutable sans droits root.
Si vous lancez un programme Linux avec
httptap <programme>, vous pouvez voir sur la sortie standard la trace des requêtes et réponses HTTP/HTTPS.httptap -- python -c "import requests; requests.get('https://monasticacademy.org')"---> GET https://monasticacademy.org/<--- 308 https://monasticacademy.org/ (15 bytes)---> GET https://www.monasticacademy.org/<--- 200 https://www.monasticacademy.org/ (5796 bytes)Il fonctionne en exécutant le programme dans un espace de noms réseau isolé, et utilise gVisor comme pile TCP/IP propre. Ce n’est pas un proxy HTTP, il ne dépend donc pas de la configuration de proxy. Le trafic TLS est déchiffré à la volée en générant une CA, sans installer de règles
iptablesni effectuer de changements globaux sur le système.netstackpour certaines fonctionnalités sur macOS.Ce serait particulièrement utile s’il n’est pas nécessaire de configurer un proxy.
https://blog.wireshark.org/2010/02/running-wireshark-as-you/
L’idée d’exécuter le processus dans un espace de noms réseau isolé est géniale.
La partie HTTPS est encore plus intéressante. Il semble que l’outil définisse pour le programme des variables d’environnement communes[1] afin qu’il utilise un bundle de CA placé dans un répertoire temporaire, mais, comme avec les variantes de
http_proxy, le problème est que le programme peut simplement les ignorer.On voit aussi qu’un système de fichiers overlay est monté sur
/etc/resolv.conf[2]. Je me demande s’il serait utile que httptap monte le répertoire/etc/ca-certificatesavec le bundle de CA temporaire.[1] https://github.com/monasticacademy/httptap/blob/cb92ee3acfb2...
[2] https://github.com/monasticacademy/httptap/blob/cb92ee3acfb2...
Si httptap monte un overlay sur
/etc/resolv.conf, c’est parce que, pour la résolution DNS aussi, il n’existe pas vraiment de moyen sûr de dire à un processus arbitraire quel serveur DNS utiliser, de la même façon que pour les racines CA. Cela dit,/etc/resolv.confreste une option assez fiable. Dès que le processus est placé dans un espace de noms réseau, il ne peut plus accéder au résolveur systemdlocalhost:53, la configuration la plus courante sur les Linux de bureau, il faut donc fournir une résolution DNS.Monter
/etc/ca-certificatesen overlay pourrait aussi aider. Cela dit, en regardant la structure de ce répertoire, j’ai été surpris de voir à quel point elle manque de cohérence d’une distribution à l’autre. Mais c’est faisable. En tout cas, si quelqu’un sait comment ajouter des certificats dans ce répertoire d’une façon reconnue par au moins certaines implémentations TLS, je suis preneur.Comme contre-exemple, on peut imaginer un malware qui communique en TLS et dont le code compilé est fortement obfusqué. Ce pourrait être un programme qui embarque dans le binaire un ensemble fixe de certificats CA et n’ouvre jamais le système de fichiers. Il pourrait malgré tout établir des connexions TLS sûres pendant environ dix ans, jusqu’à l’expiration de la plupart des certificats CA racines. TLS est entièrement géré en espace utilisateur, et rien ne garantit l’utilisation d’OpenSSL ou d’une autre bibliothèque commune ; on ne peut donc pas compter non plus sur un hook d’une fonction OpenSSL particulière. C’est encore pire si le serveur utilise un certificat auto-signé et que le client l’accepte pour une raison quelconque.
Cela dit, avec un peu de travail, il est certainement possible de gérer de façon fiable 99 % des cas. C’est toujours mieux que rien.
Utiliser ici un périphérique TUN est vraiment une excellente idée. La section « How it was made » du README est aussi parmi les meilleures que j’aie lues dans un README GitHub
Je travaille sur quelque chose appelé Subtrace[1], capable d’intercepter automatiquement à la fois les requêtes entrantes et sortantes. C’est amusant de voir que l’interface pour lancer un programme semble avoir convergé vers la même forme[2]. Cela dit, l’objectif de Subtrace est un peu différent de celui de httptap : il est plus proche de l’observabilité/monitoring des services backend cloud, d’où l’accent mis sur les requêtes dans les deux sens. L’approche est également différente. Avec Seccomp BPF, il intercepte une dizaine d’appels système comme
socket,connect,listen,accept, etc., et fait transiter toutes les connexions TCP via Subtrace. Ensuite, il parse les requêtes HTTP dans les flux TCP, puis réutilise l’onglet Network de Chrome DevTools en le faisant tourner dans le navigateur comme une webapp classique pour les présenter à l’utilisateurJe serais curieux de savoir s’il y a eu des anecdotes intéressantes en exécutant des programmes sous httptap. Je me demande aussi quel programme « téléphone à la maison » le plus souvent
[1] https://github.com/subtrace/subtrace
[2] https://docs.subtrace.dev/quickstart
https://github.com/M66B/NetGuard
C’est difficile à croire, mais il y a dans le répertoire
networktabdu dépôt une tentative à moitié aboutie de faire la même chose pour l’onglet réseau de Firefox. C’est un projet très chouette, j’aimerais en apprendre davantage et j’en discuterais volontiersUn autre outil permettant à un utilisateur sans privilèges d’analyser le trafic réseau consiste à utiliser rootless Podman avec Pasta
Il suffit d’ajouter ceci aux options de
podman run--network=pasta:--pcap,myfile.pcapPasta enregistrera alors le trafic réseau dans un fichier PCAP, qui pourra être analysé plus tard. J’ai aussi rédigé un exemple simple d’analyse du fichier PCAP enregistré avec
tsharkhttps://github.com/eriksjolund/podman-networking-docs?tab=re...
Plutôt intéressant. J’avais écrit une bibliothèque qui fournit une fonction similaire de « tap » pour les applications Go : https://github.com/henvic/httpretty
https://asciinema.org/a/297429
J’avais aussi envisagé de faire quelque chose dans ce style pour des programmes arbitraires, mais je n’ai jamais vraiment creusé la manière de l’implémenter. Ça fait plaisir de voir que quelqu’un l’a fait
Je me demande pourquoi ne pas utiliser eBPF. On pourrait alors voir d’un coup toutes les requêtes HTTP de tous les processus, y compris ceux déjà en cours d’exécution. Et en plus, sans avoir à se soucier de TLS : par exemple, il suffirait peut-être de se hooker sur
write(2)write(2)résout TLS. On pourrait lire et modifier le texte chiffré, mais comme le processus n’appelle paswrite(2)avec des octets en clair, on ne peut pas lire la requête HTTP réelle. Au final, on ne verrait que les octets chiffrés qui partent sur le réseau, ce que même la NSA peut voirIl faut une astuce de certificat CA comme celle utilisée par httptap. Bien sûr, il y a des réserves comme le certificate pinning, mais dans la plupart des scénarios pratiques, on peut rendre ça fiable
En créant Subtrace[1], j’ai réfléchi à ce problème précis jusqu’à l’absurde ; s’il existe une approche plus simple ou plus élégante, ça m’intéresse sincèrement
[1] https://github.com/subtrace/subtrace
writeavec eBPF n’aide pas au déchiffrement TLSDans tous les cas, plus il y a d’options, mieux c’est
Super. Je pense que je vais m’en servir tout de suite pour du débogage de configuration nginx
Pour l’instant, j’utilise
curl -vet je parcours manuellement la sortie pour repérer ce qui ne va pas ; avec cet outil, des choses comme les boucles de redirection devraient apparaître immédiatementÇa a l’air très bien pour jeter rapidement et grossièrement un œil à la pile d’appels HTTP/S d’une appli
Personnellement, je préfère eBPF pour tout voir, mais cet utilitaire peut aider à réduire le périmètre des parties importantes à examiner dans une trace eBPF
Ça a l’air bien
Le profil GitHub pointe vers https://www.monasticacademy.org/about ; je n’ai pas d’avis particulier là-dessus en soi, mais je me demandais quel était le lien entre leurs retraites de formation de type monastique et le projet GitHub
En regardant tout en bas du README, le lien était expliqué : https://github.com/monasticacademy/httptap?tab=readme-ov-fil...
Cela signifie que, sur un terrain de 123 acres dans le Vermont, des personnes vivent ensemble selon une structure monastique bouddhiste relativement traditionnelle, sans toutefois être des moines ordonnés. Pendant la journée, elles travaillent ensemble sur divers projets techniques et non techniques. Le lien vers le README ci-dessus en donne un bon aperçu
https://github.com/monasticacademy/httptap?tab=readme-ov-fil...