[转载]tcpdump/libpcap过滤规则解析中的BUG
文章作者:scz信息来源:网络分析专家论坛([url]www.netexpert.cn[/url])
注意,事实上这篇文章重在强调动用-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 'ip and udp and src port 53 or 1233' 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 'udp src port 53 or 1233' 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的对话框中并不支持变异的单引号,如下规则将报错:
'udp src port 53 or 1233' 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 'ip and udp and src port 53 or 1233' 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
页:
[1]
