网络基本功(十八):细说tcpdump的妙用(下)

 

转载请在文首保留原文出处:EMC中文支持论坛https://community.emc.com/go/chinese p_w_picpath001.gif

 

 

更多信息

 

(承接上文)

 

过滤:

 

要有效地使用tcpdump,掌握过滤器非常必要的。过滤允许用户指定想要抓取的数据流,从而用户可以专注于感兴趣的数据。此外,ethereal这样的工具使用tcpdump过滤语法来抓取数据流。

如果用户很清楚对何种数据流不感兴趣,可以将这部分数据排除在外。如果用户不确定需要什么数据,可以将源数据收集到文件之后在读取时应用过滤器。实际应用中,需要经常在两种方式之间转换。

简单的过滤器是加在命令行之后的关键字。但是,复杂的命令是由逻辑和关系运算符构成的。对于这样的情况,通常最好用-F选项将过滤器存储在文件中。例如,假设testfilter 是一个包含过滤主机205.153.63.30的文本文件,之后输入tcpdump –Ftestfilter等效于输入命令tcpdump host 205.153.63.30。通常,这一功能只在复杂过滤器时使用。但是,同一命令中命令行过滤器和文件过滤器不能混用。

 

地址过滤:

 

过滤器可以按照地址选择数据流。例如,考虑如下命令:

bsd1# tcpdump host 205.153.63.30

该命令抓取所有来自以及发往IP地址205.153.63.30的主机。主机可以通过名称或IP地址来选定。虽然指定的是IP地址,但抓取数据流并不限于IP数据流,实际上,过滤器也会抓到ARP数据流。限定仅抓取特定协议的数据流要求更复杂的过滤器。

 

有若干种方式可以指定和限制地址,下例是通过机器的以太网地址来选择数据流:

bsd1# tcpdump ether host 0:10:5a:e3:37:c

 

数据流可进一步限制为单向,分别用src或dst指定数据流的来源或目的地。下例显示了发送到主机205.153.63.30的数据流:

bsd1# tcpdump dst 205.153.63.30

注意到本例中host被省略了。在某些例子中省略是没问题的,但添加这些关键字通常更安全些。


广播和多播数据相应可以使用broadcast和multicast。由于多播和广播数据流在链路层和网络层所指定的数据流是不同的,所以这两种过滤器各有两种形式。过滤器ether multicast抓取以太网多播地址的数据流,ip multicast抓取IP多播地址数据流。广播数据流也是类似的使用方法。注意多播过滤器也会抓到广播数据流。


除了抓取特定主机以外,还可以抓取特定网络。例如,以下命令限制抓取来自或发往205.153.60.0的报文:

bsd1# tcpdump net 205.153.60


以下命令也可以做同样的事情:

bsd1# tcpdump net 205.153.60.0 mask 255.255.255.0

而以下命令由于最后的.0就无法正常工作:

bsd1# tcpdump net 205.153.60.0

 

协议及端口过滤:

 

限制抓取指定协议如IP,Appletalk或TCP。还可以限制建立在这些协议之上的服务,如DNS或RIP。这类抓取可以通过三种方式进行:使用tcpdump关键字,通过协议关键字proto,或通过服务使用port关键字。

 

一些协议名能够被tcpdump识别到因此可通过关键字来指定。以下命令限制抓取IP数据流:

bsd1# tcpdump ip

当然,IP数据流包括TCP数据流,UDP数据流,等等。

 

如果仅抓取TCP数据流,可以使用:

bsd1# tcpdump tcp

tcpdump可识别的关键字包括ip, igmp, tcp, udp, and icmp。

 

有很多传输层服务没有可以识别的关键字。在这种情况下,可以使用关键字proto或ip proto加上/etc/protocols能够找到的协议名或相应的协议编号。例如,以下两种方式都会查找OSPF报文:

bsd1# tcpdump ip proto ospf

bsd1# tcpdump ip proto 89

 

内嵌的关键字可能会造成问题。下面的例子中,无法使用tcp关键字,或必须使用数字。例如,下面的例子是正常工作的:

bsd#1 tcpdump ip proto 6

另一方面,不能使用proto加上tcp:

bsd#1 tcpdump ip proto tcp

会产生问题。

 

对于更高层级的建立于底层协议之上的服务,必须使用关键字port。以下两者会采集DNS数据流:

bsd#1 tcpdump port domain

bds#1 tcpdump port 53

 

第一条命令中,关键字domain能够通过查找/etc/services来解析。在传输层协议有歧义的情况下,可以将端口限制为指定协议。考虑如下命令:

bsd#1 tcpdump udp port domain

这会抓取使用UDP的DNS名查找但不包括使用TCP的DNS zone传输数据。而之前的两条命令会同时抓取这两种数据。

 

报文特征:

 

过滤器也可以基于报文特征比如报文长度或特定字段的内容,过滤器必须包含关系运算符。要指定长度,使用关键字less或greater。如下例所示:

bsd1# tcpdump greater 200

该命令收集长度大于200字节的报文。

 

根据报文内容过滤更加复杂,因为用户必须理解报文头的结构。但是尽管如此,或者说正因如此,这一方式能够使用户最大限度的控制抓取的数据。

一般使用语法 proto [ expr : size ]。字段proto指定要查看的报文头——ip则查看IP头,tcp则查看TCP头,以此类推。expr字段给出从报文头索引0开始的位移。即:报文头的第一个字节为0,第二字节为1,以此类推。size字段是可选的,指定需要使用的字节数,1,2或4。

bsd1# tcpdump "ip[9] = 6"

查看第十字节的IP头,协议值为6。注意这里必须使用引号。撇号或引号都可以,但反引号将无法正常工作。


bsd1# tcpdump tcp

也是等效的,因为TCP协议编号为6。


这一方式常常作为掩码来选择特定比特位。值可以是十六进制。可通过语法&加上比特掩码来指定。下例提取从以太网头第一字节开始(即目的地址第一字节),提取低阶比特位,并确保该位不为0:

bsd1# tcpdump 'ether[0] & 1 != 0'

该条件会选取广播和多播报文。

 

以上两个例子都有更好的方法来匹配报文。作为一个更实际的例子,考虑以下命令:

bsd1# tcpdump "tcp[13] & 0x03 != 0"

该过滤器跳过TCP头的13个字节,提取flag字节。掩码0x03选择第一和第二比特位,即FIN和SYN位。如果其中一位不为0则报文被抓取。此命令会抓取TCP连接建立及关闭报文。

 

不要将逻辑运算符与关系运算符混淆。比如想tcp src port > 23这样的表达式就无法正常工作。因为tcp src port表达式返回值为true或false,而不是一个数值,所以无法与数值进行比较。如果需要查找端口号大于23的所有TCP数据流,必须从报文头提取端口字段,使用表达式“tcp[0:2] & 0xffff > 0x0017”。