tcpdump
注:本文大部分转自细说tcpdump的妙用,有删改。
tcpdump命令:
tcpdump -en -i p3p2 -vv # show vlan
tcpdump选项可划分为四大类型:控制tcpdump程序行为,控制数据怎样显示,控制显示什么数据,以及过滤命令。
控制程序行为
这一类命令行选项影响程序行为,包括数据收集的方式。之前已介绍了两个例子:-r和-w。-w选项允许用户将输出重定向到一个文件,之后可通过-r选项将捕获数据显示出来。
如果用户知道需要捕获的报文数量或对于数量有一个上限,可使用-c选项。则当达到该数量时程序自动终止,而无需使用kill命令或Ctrl-C。下例中,收集到100个报文之后tcpdump终止:
bsd1# tcpdump -c100
如果用户在多余一个网络接口上运行tcpdump,用户可以通过-i选项指定接口。在不确定的情况下,可使用ifconfig –a来检查哪一个接口可用及对应哪一个网络。例如,一台机器有两个C级接口,xl0接口IP地址205.153.63.238,xl1接口IP地址205.153.61.178。要捕捉205.153.61.0网络的数据流,使用以下命令:
bsd1# tcpdump -i xl1
没有指定接口时,tcpdump默认为最低编号接口。
-p
选项将网卡接口设置为非混杂模式。这一选项理论上将限制为捕获接口上的正常数据流——来自或发往主机,多播数据,以及广播数据。
-s
选项控制数据的截取长度。通常,tcpdump默认为一最大字节数量并只会从单一报文中截取到该数量长度。实际字节数取决于操作系统的设备驱动。通过默认值来截取合适的报文头,而舍弃不必要的报文数据。
如果用户需截取更多数据,通过-s选项来指定字节数。也可以用-s来减少截取字节数。对于少于或等于200字节的报文,以下命令会截取完整报文:
bsd1# tcpdump -s200
更长的报文会被缩短为200字节。
控制信息如何显示
-a
,-n
,-N
和-f
选项决定了地址信息是如何显示的。-a选项强制将网络地址显示为名称,-n阻止将地址显示为名字,-N阻止将域名转换。-f选项阻止远端名称解析。下例中,从sloan.lander.edu (205.153.63.30) ing远程站点,分别不加选项,-a,-n,-N,-f。(选项-c1限制抓取1个报文)
bsd1# tcpdump -c1 host 192.31.7.130
tcpdump: listening on xl0
14:16:35.897342 sloan.lander.edu > cio-sys.cisco.com: icmp: echo request
bsd1# tcpdump -c1 -a host 192.31.7.130
tcpdump: listening on xl0
14:16:14.567917 sloan.lander.edu > cio-sys.cisco.com: icmp: echo request
bsd1# tcpdump -c1 -n host 192.31.7.130
tcpdump: listening on xl0
14:17:09.737597 205.153.63.30 > 192.31.7.130: icmp: echo request
bsd1# tcpdump -c1 -N host 192.31.7.130
tcpdump: listening on xl0
14:17:28.891045 sloan > cio-sys: icmp: echo request
bsd1# tcpdump -c1 -f host 192.31.7.130
tcpdump: listening on xl0
14:17:49.274907 sloan.lander.edu > 192.31.7.130: icmp: echo request
默认为-a选项。
-t
和-tt
选项控制时间戳的打印。-t选项不显示时间戳而-tt选项显示无格式的时间戳。以下命令显示了tcpdump命令无选项,-t选项,-tt选项的同一报文:
12:36:54.772066 sloan.lander.edu.1174 > 205.153.63.238.telnet: . ack 3259091394 win 8647 (DF)
sloan.lander.edu.1174 > 205.153.63.238.telnet: . ack 3259091394 win 8647 (DF)
934303014.772066 sloan.lander.edu.1174 > 205.153.63.238.telnet: . ack 3259091394 win 8647 (DF)
控制显示什么数据
可以通过-v和-vv选项来打印更多详细信息。例如,-v选项将会打印TTL字段。要显示较少信息,使用-q,或quiet选项。一下为同一报文分别使用-q选项,无选项,-v选项,和-vv选项的输出。
12:36:54.772066 sloan.lander.edu.1174 > 205.153.63.238.telnet: tcp 0 (DF)
12:36:54.772066 sloan.lander.edu.1174 > 205.153.63.238.telnet: . ack 3259091394 win 8647 (DF)
12:36:54.772066 sloan.lander.edu.1174 > 205.153.63.238.telnet: . ack 3259091394 win 8647 (DF) (ttl 128, id 45836)
12:36:54.772066 sloan.lander.edu.1174 > 205.153.63.238.telnet: . ack 3259091394 win 8647 (DF) (ttl 128, id 45836)
-e
选项用于显示链路层头信息。上例中-e选项的输出为:
12:36:54.772066 0:10:5a:a1:e9:8 0:10:5a:e3:37:c ip 60:
sloan.lander.edu.1174 > 205.153.63.238.telnet: . ack 3259091394 win 8647 (DF)
05ae9:8是sloan.lander.edu中3Com卡的以太网地址,05a37:c是205.153.63.238中3Com卡的以太网地址。
-x
选项将报文以十六进制形式dump出来,排除了链路层报文头。-x和-vv选项报文显示如下:
13:57:12.719718 bsd1.lander.edu.1657 > 205.153.60.5.domain: 11587+ A? www.microsoft.com. (35) (ttl 64, id 41353)
4500 003f a189 0000 4011 c43a cd99 3db2
cd99 3c05 0679 0035 002b 06d9 2d43 0100
0001 0000 0000 0000 0377 7777 096d 6963
726f 736f 6674 0363 6f6d 0000 0100 01
过滤
要有效地使用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
。