Formato legível humano para cabeçalhos http com tcpdump


69

Gostaria de visualizar os cabeçalhos HTTP enviados do Apache (escutando na porta 80) para o Tomcat (na porta 4080) em uma máquina Linux.

Segundo a Wikipedia ,

Os campos do cabeçalho são pares nome-valor separados por dois pontos no formato de sequência de texto não criptografado.

Eu tentei algumas variações do seguinte 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?

O resultado sempre foi o mesmo - uma mistura estranha de palavras sem sentido e inglesas (por exemplo HEAD).

Como posso visualizar os cabeçalhos em um formato legível por humanos?


Tcpdump mostra o pacote inteiro. Isso inclui os cabeçalhos IP e TCP. AFAIK, você não pode exibir apenas a carga útil do TCP.
Zoredache

Respostas:


93

Aqui está uma linha que eu criei para exibir cabeçalhos HTTP de solicitação e resposta usando tcpdump(o que também deve funcionar no seu 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 o corte de pacotes em 10 KB e apenas conhece os comandos GET, POST e HEAD, mas isso deve ser suficiente na maioria dos casos.

EDIT : modificado para se livrar dos buffers a cada passo para torná-lo mais responsivo. No entanto, agora é necessário o Perl e o stdbuf, portanto, use a versão original se você não os tiver: EDIT : Destinos de porta de script alterados de 80 a 4080, para realmente ouvir o tráfego que já passou pelo apache, em vez de o tráfego externo direto chegar à 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 }'

Algumas explicações:

  • sudo stdbuf -oL -eL faz o tcpdump rodar em buffer de linha
  • O filtro mágico tcpdump é explicado em detalhes aqui: https://stackoverflow.com/questions/11757477/understanding-tcpdump-filter-bit-masking
  • O grep está procurando por qualquer linha com GET, HTTP / ou POST; ou qualquer linha que pareça um cabeçalho (letras e números seguidos de dois pontos)
  • BEGIN {$ | = 1} faz com que o perl seja executado no buffer de linha
  • s /.*? (GET | HTTP / [0-9.] * | POST) / \ n $ 1 / g adiciona uma nova linha antes do início de cada nova solicitação ou resposta

11
Funciona bem. Você poderia adicionar mais detalhes sobre como essa expressão tcpdump funciona?
Vivek Thomas

11
a parte 'ip' em parens é explicada aqui, por exemplo: stackoverflow.com/questions/11757477/…
Kibber

Você acabou de me salvar muita dor de cabeça. Pena que eu posso apenas +1.
Aaron Dobbing 10/09/2015

19

Você pode obter algo próximo do que deseja usando -A, por exemplo,

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

Lembre-se de usar -s 0para garantir que você obtenha o pacote inteiro.

Como alternativa, você pode usar wiresharkpara visualizar os cabeçalhos interativamente.


11
Tentei -Ae -s 0, tenho a mesma saída.
Adam Matan

2
Tente sem -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

... que é algo parecido com o que você deseja. Leia a partir de 'HEAD' - essa é a carga útil do HTTP. Se você definitivamente usou -s 0e não há nada depois HTTP/1.0, não há cabeçalhos HTTP na solicitação.
Flup

obrigado. Existe uma maneira de imprimir apenas os cabeçalhos de texto, sem a carga binária?
Adam Matan

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.