发新话题
打印

[转载]tcpdump/libpcap过滤规则解析中的BUG

[转载]tcpdump/libpcap过滤规则解析中的BUG

文章作者:scz
信息来源:网络分析专家论坛(www.netexpert.cn

注意,事实上这篇文章重在强调动用-d,而不是强调BUG,因为事实上不是
BUG,我在文章的后半段解释清楚了。但没有删除前面的备忘记录,只是想
完整介绍一下来龙去脉,有时候过程不比结果逊色。

标题: tcpdump/libpcap过滤规则解析中的BUG

2005-03-14 16:19

今天收到"quickmouse@华中"的一封信,他想捕捉源端口为53/UDP或1233/UDP的报文
以及ARP报文。当时我说可以这样:

tcpdump 'ip and udp and src port 53 or 1233' or arp

结果他回信说这个命令将捕捉部分TCP报文,我觉得很奇怪,感觉上不太可能,于是
执行了如下命令测试:

telnet <target> 53

这里<target>上并未侦听53/TCP,于是将回送一个RST报文。我在前述tcpdump命令的
输出中并未看到这个RST报文。可耗子这样说,肯定不会空穴来风,他让我用-d确认
一下,结果看到这个输出:

# tcpdump &#39;ip and udp and src port 53 or 1233&#39; or arp -d
(000) ldh    [12]
(001) jeq    #0x800        jt 2   jf 17
(002) ldb    [23]
(003) jeq    #0x11        jt 4   jf 10
(004) ldh    [20]
(005) jset    #0x1fff       jt 19  jf 6
(006) ldxb    4*([14]&0xf)
(007) ldh    [x + 14]
(008) jeq    #0x35        jt 18  jf 9
(009) jeq    #0x4d1        jt 18  jf 19
(010) jeq    #0x84        jt 12  jf 11  <== 0x84(132)不知从哪里来的
(011) jeq    #0x6         jt 12  jf 19
(012) ldh    [20]
(013) jset    #0x1fff       jt 19  jf 14
(014) ldxb    4*([14]&0xf)
(015) ldh    [x + 14]
(016) jeq    #0x4d1        jt 18  jf 19  <== 源端口为1233/TCP的报文
(017) jeq    #0x806        jt 18  jf 19
(018) ret    #68
(019) ret    #0

这个输出意味着上述命令将捕捉到源端口为1233/TCP的报文。用如下命令测试:

telnet <target> 1233

果然捕捉到一个RST报文。显然,耗子所说的解析BUG确实存在,最明显的是0x84不知
从哪里冒出来的。

现在检查如下过滤规则:

# tcpdump &#39;udp src port 53 or 1233&#39; or arp -d
(000) ldh    [12]
(001) jeq    #0x800        jt 2   jf 10  IP报文
(002) ldb    [23]
(003) jeq    #0x11        jt 4   jf 12  UDP报文
(004) ldh    [20]
(005) jset    #0x1fff       jt 12  jf 6   第一个IP碎片
(006) ldxb    4*([14]&0xf)
(007) ldh    [x + 14]
(008) jeq    #0x35        jt 11  jf 9   源端口为53/UDP
(009) jeq    #0x4d1        jt 11  jf 12  源端口为1233/UDP
(010) jeq    #0x806        jt 11  jf 12  ARP报文
(011) ret    #68
(012) ret    #0

这次才是如我们所愿的过滤规则。两个教训,一是过滤规则写得长了,一些看似冗余
而无害的条件可能因BUG而变得有害,二是安全起见务必动用-d先期检查过滤规则。

不过,这个BUG可能是某些版本的tcpdump/libpcap相配合时出现的BUG:

# tcpdump -V
tcpdump version 3.8.3
libpcap version 0.8.3

真正解析过滤规则的部件是libpcap,而不是tcpdump。libpcap采用pcap_compile()
和pcap_setfilter()结合的办法屏蔽了各种链路层支持的不同。

在bash命令行上还可以这样写:

# tcpdump \(udp src port 53 or 1233\) or arp

转义符\的出现是因为圆括号()对于bash本身有其它意义。

由于Ethereal/Winpcap使用类似的过滤规则,很可能存在类似的BUG,务必小心。在
Ethereal的对话框中并不支持变异的单引号,如下规则将报错:

&#39;udp src port 53 or 1233&#39; or arp

Ethereal的对话框中圆括号没有类似bash元字符那样的特殊意义,因此也不需要转义
符,如下规则将报错:

\(udp src port 53 or 1233\) or arp

在Ethereal中,只能按最原始的显示指定过滤规则:

(udp src port 53 or 1233) or arp

2005-03-15 08:24

晚上又想了想,算不上是软件BUG,是我的BUG,看下面的注释:

# tcpdump &#39;ip and udp and src port 53 or 1233&#39; or arp -d
(000) ldh    [12]
(001) jeq    #0x800        jt 2   jf 17  IP报文
(002) ldb    [23]
(003) jeq    #0x11        jt 4   jf 10  UDP报文
(004) ldh    [20]
(005) jset    #0x1fff       jt 19  jf 6   第一个IP碎片
(006) ldxb    4*([14]&0xf)
(007) ldh    [x + 14]
(008) jeq    #0x35        jt 18  jf 9   源端口为53/UDP
(009) jeq    #0x4d1        jt 18  jf 19  源端口为1233/UDP
(010) jeq    #0x84        jt 12  jf 11  0x84(132)与0x11(17)、0x06平行
(011) jeq    #0x6         jt 12  jf 19  TCP报文
(012) ldh    [20]
(013) jset    #0x1fff       jt 19  jf 14  第一个IP碎片
(014) ldxb    4*([14]&0xf)
(015) ldh    [x + 14]
(016) jeq    #0x4d1        jt 18  jf 19  源端口为1233/TCP
(017) jeq    #0x806        jt 18  jf 19  ARP报文
(018) ret    #68
(019) ret    #0

or的优先级低于and,导致1233是单独的一个规则,不受"ip and udp and"的约束。

检查如下过滤规则:

# tcpdump src port 1233 -d
(000) ldh    [12]
(001) jeq    #0x800        jt 2   jf 12  IP报文
(002) ldb    [23]
(003) jeq    #0x84        jt 6   jf 4   0x84(132)与0x11(17)、0x06平行
(004) jeq    #0x6         jt 6   jf 5   TCP报文
(005) jeq    #0x11        jt 6   jf 12  UDP报文
(006) ldh    [20]
(007) jset    #0x1fff       jt 12  jf 8   第一个IP碎片
(008) ldxb    4*([14]&0xf)
(009) ldh    [x + 14]
(010) jeq    #0x4d1        jt 11  jf 12  源端口为1233/UDP或1233/TCP
(011) ret    #68
(012) ret    #0
人情如冰六月寒,花做一份艳,为谁笑人间? 如果任何人发现我转载的有图像的文章中图像失效或者文章有问题,请及时短消息通知我。先谢谢。::)) coup de foudre

TOP

发新话题