9

我正在尝试使用 tcpdump 来嗅探 http 标头。

这个过滤器效果很好,但我无法理解 -

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

我用谷歌搜索了它,但我找不到任何有用的信息

这是整个 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
4

1 回答 1

18

获取 http 标头的不是 BPF 过滤器,而是 tcpdump 命令上的“-A”开关。

您的 tcpdump 命令在 eth0 上查找到某个目的地或某个源的 tcp 流量,其中最终 BPF 过滤器涉及的计算结果为非零总数。使用“-A”选项,它以 ASCII 格式打印每个数据包减去其链接级别的标头。

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

  • ip[2:2]指 IP 标头中的两个字节(即第 3 和第 4 字节),从字节 2 开始(记住它从偏移量 0 开始)。这个总数表示 IP 数据包的总长度,最大可以是 65535 字节。

对于这里的位掩码,为清楚起见,我预先添加了一个“0”,因此掩码0xf变为0x0f. 根据下面 GuyHarris 的评论,面具上的前导“0”被删除。

  • ip[0]&0x0f指 IP 标头中字节 0(即第 1 个字节)的后半部分,这将为您提供 32 位字的 IP 标头长度,因此,通常将其乘以 4 进行此类计算。

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

您需要将最后 2 个长度乘以 4,因为它们是 32 位/4 字节字,因此需要转换为以字节为单位的总数,以便计算正确

您的过滤器应该计算:

  • IP 数据包长度(以字节为单位) - IP 标头长度 - TCP 标头长度

并寻找该值为零,即像这样

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 指南。

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

于 2012-08-02T15:36:05.097 回答