Format lisible par l'homme pour les en-têtes http avec tcpdump

69

Je souhaite afficher les en-têtes HTTP envoyés par Apache (écoute sur le port 80) à Tomcat (sur le port 4080) sur une machine Linux.

Selon Wikipedia ,

Les champs d'en-tête sont des paires nom-valeur séparées par deux-points dans un format de chaîne en texte clair.

J'ai essayé quelques variantes de la tcpdumpcommande suivante :

$ sudo tcpdump -lnX dst port 4080 -c 10

11:29:28.605894 IP SOME_IP.33273 > SOME_IP.4080: P 0:49(49) ack 1 win 23 <nop,nop,timestamp 1191760962 509391143>
    0x0000:  4500 0065 3a9f 4000 3f06 0084 628a 9ec4  E..e:.@.?...b...
    0x0010:  628a 9c97 81f9 0ff0 9e87 eee0 144b 90e1  b............K..
    0x0020:  8018 0017 fb43 0000 0101 080a 4708 d442  .....C......G..B
    0x0030:  1e5c b127 4845 4144 202f 6461 7070 6572  .\.'HEAD./dapper
    0x0040:  5f73 6572 7669 6e67 2f41 644d 6f6e 6b65  _serving/AdMonke
    0x0050:  793f                                     y?

Le résultat était toujours le même - un étrange mélange de charabia et de mots anglais (par exemple HEAD).

Comment afficher les en-têtes dans un format lisible par l'homme?

Adam Matan
la source
Tcpdump montre le paquet entier. Cela inclut les en-têtes IP et TCP. Autant que je sache, vous ne pouvez pas afficher uniquement la charge TCP.
Zoredache

Réponses:

93

Voici un one-liner que j'ai créé pour afficher les en-têtes HTTP de requête et de réponse tcpdump(ce qui devrait également fonctionner pour votre cas):

sudo tcpdump -A -s 10240 'tcp port 4080 and (((ip[2:2] - ((ip[0]&0xf)<<2)) - ((tcp[12]&0xf0)>>2)) != 0)' | egrep --line-buffered "^........(GET |HTTP\/|POST |HEAD )|^[A-Za-z0-9-]+: " | sed -r 's/^........(GET |HTTP\/|POST |HEAD )/\n\1/g'

Il limite coupe le paquet à 10Kb et ne connaît que les commandes GET, POST et HEAD, mais cela devrait suffire dans la majorité des cas.

EDIT : modifié pour supprimer les tampons à chaque étape afin de le rendre plus réactif. A besoin de Perl et de stdbuf maintenant, utilisez donc la version originale si vous ne les avez pas: EDIT : modification des cibles de port de script de 80 à 4080, pour écouter le trafic déjà passé par apache au lieu du trafic extérieur direct arrivant au port. 80:

sudo stdbuf -oL -eL /usr/sbin/tcpdump -A -s 10240 "tcp port 4080 and (((ip[2:2] - ((ip[0]&0xf)<<2)) - ((tcp[12]&0xf0)>>2)) != 0)" | egrep -a --line-buffered ".+(GET |HTTP\/|POST )|^[A-Za-z0-9-]+: " | perl -nle 'BEGIN{$|=1} { s/.*?(GET |HTTP\/[0-9.]* |POST )/\n$1/g; print }'

Quelques explications:

  • sudo stdbuf -oL -eL rend l'exécution de tcpdump en mémoire tampon
  • le filtre magique tcpdump est expliqué en détail ici: https://stackoverflow.com/questions/11757477/understanding-tcpdump-filter-bit-masking
  • grep recherche des lignes avec GET, HTTP / ou POST; ou toutes les lignes qui ressemblent à un en-tête (lettres et chiffres suivis de deux points)
  • BEGIN {$ | = 1} provoque l'exécution de Perl en mémoire tampon de ligne
  • s /.*? (GET | HTTP / [0-9.] * | POST) / \ n $ 1 / g ajoute une nouvelle ligne avant le début de chaque nouvelle demande ou réponse
Kibber
la source
1
Fonctionne très bien. Pourriez-vous s'il vous plaît ajouter plus de détails sur le fonctionnement de cette expression tcpdump?
Vivek Thomas
1
la partie 'ip' en parens est expliquée ici, par exemple: stackoverflow.com/questions/11757477/…
Kibber
Tu viens de me sauver tellement mal à la tête. Dommage que je ne peux que +1.
Aaron Dobbing le
19

Vous pouvez obtenir quelque chose de proche de ce que vous voulez en utilisant -A, par exemple

E....c@.@...
.....Ng.d.P..Ch.).....s.......
.A...u.BHEAD / HTTP/1.1
User-Agent: curl/7.29.0
Host: www.google.com
Accept: */*

N'oubliez pas d'utiliser -s 0pour vous assurer que vous obtenez le paquet entier.

Vous pouvez également utiliser wiresharkpour afficher les en-têtes de manière interactive.

Flup
la source
1
Essayé -Aet -s 0obtenu le même résultat.
Adam Matan
2
Essayez sans -X.
Flup
tcpdump -s 0 -A dst port 4080donne E..e..@.?.$bb...b....:......w........Q.....G..1.b..HEAD /dapper_serving/AdMonkey?ping=1 HTTP/1.0.
Adam Matan
... ce qui est proche de ce que vous voulez. Lisez à partir de 'HEAD' - c'est la charge HTTP. Si vous avez définitivement utilisé -s 0et qu'il n'y a rien après HTTP/1.0, il n'y a pas d'en-tête HTTP dans la demande.
Flup
Merci. Est-il possible d'imprimer uniquement les en-têtes de texte, sans les données utiles binaires?
Adam Matan
-1

Essayez d'utiliser http://justniffer.sourceforge.net/ C'est un meilleur outil ou Wireshark avec l'option "Suivre le flux TCP", il y a juste beaucoup de meilleures options que tcpdump pour voir les en-têtes (requêtes / réponses)

Danila Ladner
la source
1
Peut-être ajouterons-nous un exemple sur la façon de faire fonctionner cela
vikas027
Peut-être pouvez-vous lire une page de manuel? justniffer.sourceforge.net/#!/man_page
Danila Ladner