Formato leggibile dall'uomo per le intestazioni http con tcpdump


69

Vorrei visualizzare le intestazioni HTTP inviate da Apache (in ascolto sulla porta 80) a Tomcat (sulla porta 4080) in una macchina Linux.

Secondo Wikipedia ,

I campi di intestazione sono coppie nome-valore separate da due punti in formato stringa in chiaro.

Ho provato alcune varianti del seguente tcpdumpcomando:

$ 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?

Il risultato è sempre stato lo stesso: uno strano mix di parole incomprensibili e inglesi (ad es HEAD.).

Come posso visualizzare le intestazioni in un formato leggibile dall'uomo?


Tcpdump mostra l'intero pacchetto. Ciò include le intestazioni IP e TCP. AFAIK, non puoi visualizzare solo il payload TCP.
Zoredache,

Risposte:


93

Ecco un esempio che ho ideato per visualizzare le intestazioni HTTP di richiesta e risposta tcpdump(che dovrebbe funzionare anche nel tuo caso):

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'

Limita taglia il pacchetto a 10Kb e conosce solo i comandi GET, POST e HEAD, ma dovrebbe essere sufficiente nella maggior parte dei casi.

EDIT : modificato per eliminare i buffer in ogni fase per renderlo più reattivo. Ora ha bisogno di Perl e stdbuf, quindi usa la versione originale se non li possiedi: EDIT : destinazioni della porta dello script modificate da 80 a 4080, per ascoltare effettivamente il traffico che ha già attraversato apache, anziché il traffico esterno diretto che arriva alla porta 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 }'

Alcune spiegazioni:

  • sudo stdbuf -oL -eL fa funzionare tcpdump con buffer di linea
  • il filtro magico tcpdump è spiegato in dettaglio qui: https://stackoverflow.com/questions/11757477/understanding-tcpdump-filter-bit-masking
  • grep sta cercando qualsiasi linea con GET, HTTP / o POST; o qualsiasi riga che assomigli a un'intestazione (lettere e numeri seguiti da due punti)
  • BEGIN {$ | = 1} fa eseguire perl al buffer di linea
  • s /.*? (GET | HTTP / [0-9.] * | POST) / \ n $ 1 / g aggiunge una nuova riga prima dell'inizio di ogni nuova richiesta o risposta

1
Funziona alla grande. Potresti aggiungere ulteriori dettagli su come funziona l'espressione tcpdump?
Vivek Thomas,

1
la parte 'ip' in parentesi è spiegato qui, per esempio: stackoverflow.com/questions/11757477/...
Kibber

Mi hai appena salvato così tanto mal di testa. Peccato che posso solo +1.
Aaron Dobbing,

19

Puoi ottenere qualcosa di simile a ciò che desideri utilizzando -A, ad es

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

Ricordati di usare -s 0per assicurarti di ottenere l'intero pacchetto.

In alternativa, è possibile utilizzare wiresharkper visualizzare le intestazioni in modo interattivo.


1
Ho provato -Ae -s 0ottenuto lo stesso risultato.
Adam Matan,

2
Prova senza -X.
Flup,

tcpdump -s 0 -A dst port 4080E..e..@.?.$bb...b....:......w........Q.....G..1.b..HEAD /dapper_serving/AdMonkey?ping=1 HTTP/1.0.
Adam Matan,

... che è qualcosa di simile a quello che vuoi. Leggi da 'HEAD' - questo è il payload HTTP. Se hai sicuramente usato -s 0e non c'è niente dopo HTTP/1.0, non ci sono intestazioni HTTP nella richiesta.
Flup,

Grazie. C'è un modo per stampare solo le intestazioni di testo, senza il payload binario?
Adam Matan,

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.