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?


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

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.


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

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.