使用tcpdump的http头的人类可读格式

我想在Linux机器上查看从Apache(侦听端口80)发送到Tomcat(在端口4080上)的HTTP头。

根据维基百科 ,

标题字段是以明文string格式由冒号分隔的名称 – 值对。

我已经尝试了以下tcpdump命令的一些变体:

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

结果总是相同的 – 一个奇怪的混合的胡言乱语和英文单词(如HEAD )。

我如何以可读的格式查看标题?

下面是我使用tcpdump显示请求和响应HTTP头文件的tcpdump (这也适用于你的情况):

 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' 

它限制在10Kbclosures数据包,只知道GET,POST和HEAD命令,但在大多数情况下应该足够了。

编辑 :修改它在每一步摆脱缓冲区,使其更响应。 现在需要Perl和stdbuf,所以使用原始版本,如果你没有这些: 编辑 :改变脚本端口目标从80到4080,实际上听stream量通过Apache已经,而不是直接外部stream量到达端口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 }' 

一些解释:

  • sudo stdbuf -oL -eL使tcpdump运行线路缓冲
  • tcpdump魔术filter在这里详细解释: https : //stackoverflow.com/questions/11757477/understanding-tcpdump-filter-bit-masking
  • grep正在寻找GET,HTTP /或POST的任何行; 或者看起来像一个头的任何行(字母和数字后跟冒号)
  • BEGIN {$ | = 1}将导致perl运行行缓冲
  • s /.*?(GET | HTTP / [0-9。] * | POST)/ \ n $ 1 / g在每个新请求或响应开始之前添加一个换行符

你可以通过使用-A得到你想要的东西,例如

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

请记住使用-s 0来确保您获得整个数据包。

或者,您可以使用wireshark以交互方式查看标题。