2012-08-01 85 views
7

我想通过使用tcpdump来嗅探http头。了解Tcpdump过滤器和位掩码

该过滤器效果很好,但我不明白 -

(((ip[2:2] - ((ip[0]&0xf)<<2)) - ((tcp[12]&0xf0)>>2)) != 0) 

我GOOGLE了,但我无法找到任何有用的信息

这里是整个tcpdump命令

sudo tcpdump -A 'dst [dest host] or src [src host] and tcp and 
(((ip[2:2] - ((ip[0]&0xf)<<2)) - ((tcp[12]&0xf0)>>2)) != 0)' -i eth0 

回答

15

这不是BPF过滤器,它可以获取http头文件,但tcpdump命令中的“-A”开关。

您的tcpdump命令查找tcp流量到某个目标或来自eth0上的某个源,其中最终的BPF过滤器涉及一个导致总数不为零的计算。使用“-A”选项,它会以ASCII格式打印每个数据包,然后打印其链接级别标题。

我已经解释了下面的计算,但我相信在实际的过滤器中可能存在一些问题,可能是通过复制和粘贴。当您使用tcpdump的这些过滤器,你使用TCP位掩码,检查不落在字节边界

  • ip[2:2]指的是两个字节(即第3 & 4字节)字段时,通常会使用在IP报头中,从字节2开始(记住它从偏移量0开始)。该总和表示可以是最大65535字节的IP分组的总长度。

对于这里的掩码,为清楚起见,我已经预先计划一个“0”,从而掩盖0xf变得0x0f。根据下面的GuyHarris的评论,掩码中的前导'0'被丢弃。

  • ip[0]&0x0f指字节0的在IP报头中的第二半(即第一字节),这将会给你在32个字,因此IP报头长度,这通常通过4乘以这样的计算。

  • tcp[12]&0xf0)指的是字节12的前半部分(即第11个字节),它是数据偏移字段,用32位字指定TCP头部的大小,因此通常乘以4进行这样的计算。

您需要通过4乘最后2米的长度,因为他们是32位/ 4字节字等都需要被翻译成一个总以字节为单位的计算是正确的

你的过滤器应该是计算:

  • 该IP包的长度(以字节为单位) - 该IP报头长度 - TCP报头长度

并寻找该值被泽RO,即像这样

sudo tcpdump -A -nnpi eth0 '(ip[2:2] - ((ip[0]&0x0f)*4) - ((tcp[12]&0xf0)*4) != 0)'

当您执行减法,你正在寻找一个非零总。这个非零总数意味着存在第4层以上的数据,即tcp有效载荷中的数据,通常是应用程序流量。

您可能还需要添加port 80假设大多数HTTP流量是通过端口80

这样的过滤器是常用的安全民俗来检测一个SYN,这是不正常的,但根据RFC的数据,这是允许的。所以整个事情看起来是这样的 -

'tcp[13]=0x02 and (ip[2:2] - ((ip[0]&0x0f)*4) - ((tcp[12]&0xf0)*4) != 0)'

TCPIPGuide是TCP/IP很好的,免费在线指导BTW。

更新:根据Guy Harris的更新修改位掩码中的“前导零”部分。

+1

'0x0f'和'0xf'是相同的东西;前导零可以在十六进制值中省略。但是,如果前导零存在,代码可能会读取更多*清楚*。 “<< 2”与“* 4”相同;然而'2'是'/ 2'(除以2),这是错误的 - 这可能是一个错字。 – 2012-08-02 17:38:59

+1

非常全面的答复! – kingasmk 2012-08-02 23:32:07

+1

@GuyHarris thx,我不确定前导零是否被删除,所以只是认为我为了清晰起见而提出了我的评论。关于''2'与'* 4'相同,为了清楚起见,我只是简单地将它从'>> 2'中改为'* 4',因为'* 4'非常清楚,并且感觉有必要解释这些值的差异(32位字与字节),并消除围绕“<< 2”错字的怀疑。 – 2012-08-03 09:08:24