【问题标题】:Understanding Tcpdump filter & bit-masking了解 Tcpdump 过滤器和位掩码
【发布时间】:2012-08-01 10:40:13
【问题描述】:

我正在尝试使用 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

【问题讨论】:

    标签: linux networking packet-sniffers tcpdump sniffing


    【解决方案1】:

    获取 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]&amp;0x0f 指 IP 标头中字节 0 的后半部分(即第一个字节),这将为您提供 32 位字的 IP 标头长度,因此,通常乘以 4进行这样的计算。

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

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

    您的过滤器应该正在计算:

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

    并寻找该值为零,即类似这样的东西

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

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

    您可能还想添加port 80,假设大多数 http 流量都在端口 80 上。

    安全人员通常使用这种过滤器来检测 SYN 上的数据,这是不正常的,但根据 RFC,这是允许的。所以整个事情看起来像 -

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

    TCPIPGuide 是一个非常好的免费在线 TCP/IP 指南。

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

    【讨论】:

    • 0x0f0xf 是同一个东西;在十六进制值中可以省略前导零。但是,如果存在前导零,则代码可能会更清楚阅读。 &lt;&lt;2*4 相同;但是,&gt;&gt;2/2(除以 2),这是错误的 - 这可能是一个错字。
    • 非常感谢非常全面的回答!
    • @GuyHarris thx,我不确定前导零是否被删除,所以我想我会为了清楚起见而发表评论。关于&gt;&gt;2*4 相同,为了清楚起见,我只是将其从&gt;&gt;2 更改为*4 非常清楚并且觉得有必要解释值的差异(32 位字与字节) ,并消除对&lt;&lt;2 错字的疑虑。
    • 大概您的意思是“&lt;&lt;2*4 相同” - 左移 n 相当于乘以 2^n,右移 n 相当于除以 2^n,所以是&gt;&gt;2,而不是&lt;&lt;2,是那里的错字。
    • @GuyHarris,我认为声明除以 4 的原始过滤器实际上是正确的,因为 TCP 标头长度字段位于字节的高半字节。因此,在没有适当移位的情况下提取存储在那里的数字实际上将字段的原始值乘以 16,需要除以 4 才能转换为字节。
    猜你喜欢
    • 2018-04-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-02-20
    • 2022-11-11
    • 2013-02-14
    • 2015-07-10
    • 2014-07-10
    相关资源
    最近更新 更多