原文地址:EMC中文支持论坛https://community.emc.com/go/chinese
介绍
tcpdump命令最初设计用于观察TCP/IP性能问题,它是一个用于截取网络分组,并输出分组内容的工具。tcpdump可以将网络中传送的数据包的报文头完全截获下来提供分析,它支持针对网络层、协议、主机、网络或端口的过滤,并提供and, or, not等逻辑语句来帮助用户去掉无用的信息。
更多信息
使用tcpdump
Unix命令tee通常用来允许用户查看并记录Unix会话的输出。使用tcpdump结合tee加上-l选项来实现,命令格式如下:
1 | bsd1# tcpdump -l | tee outfile |
另一种方式是通过-w选项直接将抓取数据写入文件中。之后通过tcpdump -r选项来读取。抓取数据可以输入:
1 | bsd1# tcpdump -w rawfile |
然后将raw文件转化成text文件:
1 | bsd1# tcpdump -r rawfile > textfile |
tcpdump选项
tcpdump选项可划分为四大类型:
- 控制tcpdump程序行为
- 控制数据怎样显示
- 控制显示什么数据
- 以及过滤命令
控制程序行为
这一类命令行选项影响程序行为,包括数据收集的方式。之前已介绍了两个例子:-r和-w。-w选项允许用户将输出重定向到一个文件,之后可通过-r选项将捕获数据显示出来。
如果用户知道需要捕获的报文数量或对于数量有一个上限,可使用-c选项。则当达到该数量时程序自动终止,而无需使用kill命令或Ctrl-C。下例中,收集到100个报文之后tcpdump终止:
1 | bsd1# tcpdump -c100 |
如果用户在多余一个网络接口上运行tcpdump,用户可以通过-i选项指定接口。在不确定的情况下,可使用ifconfig –a来检查哪一个接口可用及对应哪一个网络。例如,一台机器有两个C级接口,xl0接口IP地址 205.153.63.238,xl1接口IP地址205.153.61.178。要捕捉205.153.61.0网络的数据流,使用以下命令:
1 | 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个报文)
1 | bsd1# tcpdump -c1 host 192.31.7.130 |
默认为-a选项。
-t和-tt选项控制时间戳的打印。-t选项不显示时间戳而-tt选项显示无格式的时间戳。以下命令显示了tcpdump命令无选项,-t选项,-tt选项的同一报文:
1 | 12:36:54.772066 sloan.lander.edu.1174 > 205.153.63.238.telnet: . ack 3259091394 win 8647 (DF) |
控制显示什么数据
可以通过-v和-vv选项来打印更多详细信息。例如,-v选项将会打印TTL字段。要显示较少信息,使用-q,或quiet选项。一下为同一报文分别使用-q选项,无选项,-v选项,和-vv选项的输出。
1 | 12:36:54.772066 sloan.lander.edu.1174 > 205.153.63.238.telnet: tcp 0 (DF) |
-e选项用于显示链路层头信息。上例中-e选项的输出为:
1 | 12:36:54.772066 0:10:5a:a1:e9:8 0:10:5a:e3:37:c ip 60: |
-x选项将报文以十六进制形式dump出来,排除了链路层报文头。-x和-vv选项报文显示如下:
1 | 13:57:12.719718 bsd1.lander.edu.1657 > 205.153.60.5.domain: 11587+ A? www.microsoft.com. (35) (ttl 64, id 41353) |
过滤
要有效地使用tcpdump,掌握过滤器非常必要的。过滤允许用户指定想要抓取的数据流,从而用户可以专注于感兴趣的数据。此外,ethereal这样的工具使用tcpdump过滤语法来抓取数据流。
如果用户很清楚对何种数据流不感兴趣,可以将这部分数据排除在外。如果用户不确定需要什么数据,可以将源数据收集到文件之后在读取时应用过滤器。实际应用中,需要经常在两种方式之间转换。
简单的过滤器是加在命令行之后的关键字。但是,复杂的命令是由逻辑和关系运算符构成的。对于这样的情况,通常最好用-F选项将过滤器存储在文件中。例如,假设testfilter 是一个包含过滤主机205.153.63.30的文本文件,之后输入tcpdump –Ftestfilter等效于输入命令tcpdump host 205.153.63.30。通常,这一功能只在复杂过滤器时使用。但是,同一命令中命令行过滤器和文件过滤器不能混用。
地址过滤:
过滤器可以按照地址选择数据流。例如,考虑如下命令:
1 | bsd1# tcpdump host 205.153.63.30 |
该命令抓取所有来自以及发往IP地址205.153.63.30的主机。主机可以通过名称或IP地址来选定。虽然指定的是IP地址,但抓取数据流并不限于IP数据流,实际上,过滤器也会抓到ARP数据流。限定仅抓取特定协议的数据流要求更复杂的过滤器。
有若干种方式可以指定和限制地址,下例是通过机器的以太网地址来选择数据流:
1 | bsd1# tcpdump ether host 0:10:5a:e3:37:c |
数据流可进一步限制为单向,分别用src或dst指定数据流的来源或目的地。下例显示了发送到主机205.153.63.30 的数据流:
1 | bsd1# tcpdump dst 205.153.63.30 |
注意到本例中host被省略了。在某些例子中省略是没问题的,但添加这些关键字通常更安全些。
广播和多播数据相应可以使用broadcast和multicast。由于多播和广播数据流在链路层和网络层所指定的数据流是不同的,所以这两种过滤器各有两种形式。过滤器ether multicast抓取以太网多播地址的数据流,ip multicast抓取IP多播地址数据流。广播数据流也是类似的使用方法。注意多播过滤器也会抓到广播数据流。
除了抓取特定主机以外,还可以抓取特定网络。例如,以下命令限制抓取来自或发往205.153.60.0的报文:
1 | bsd1# tcpdump net 205.153.60 |
以下命令也可以做同样的事情:
1 | bsd1# tcpdump net 205.153.60.0 mask 255.255.255.0 |
而以下命令由于最后的.0就无法正常工作:
1 | bsd1# tcpdump net 205.153.60.0 |
协议及端口过滤:
限制抓取指定协议如IP,Appletalk或TCP。还可以限制建立在这些协议之上的服务,如DNS或RIP。这类抓取可以通过三种方式进行:使用tcpdump关键字,通过协议关键字proto,或通过服务使用port关键字。
一些协议名能够被tcpdump识别到因此可通过关键字来指定。以下命令限制抓取IP数据流:
1 | bsd1# tcpdump ip |
当然,IP数据流包括TCP数据流,UDP数据流,等等。
如果仅抓取TCP数据流,可以使用:
1 | bsd1# tcpdump tcp |
tcpdump可识别的关键字包括ip, igmp, tcp, udp, and icmp。
有很多传输层服务没有可以识别的关键字。在这种情况下,可以使用关键字proto或ip proto加上/etc/protocols能够找到的协议名或相应的协议编号。例如,以下两种方式都会查找OSPF报文:
1 | bsd1# tcpdump ip proto ospf |
内嵌的关键字可能会造成问题。下面的例子中,无法使用tcp关键字,或必须使用数字。例如,下面的例子是正常工作的:
1 | bsd#1 tcpdump ip proto 6 |
另一方面,不能使用proto加上tcp:
1 | bsd#1 tcpdump ip proto tcp |
会产生问题。
对于更高层级的建立于底层协议之上的服务,必须使用关键字port。以下两者会采集DNS数据流:
1 | bsd#1 tcpdump port domain |
第一条命令中,关键字domain能够通过查找/etc/services来解析。在传输层协议有歧义的情况下,可以将端口限制为指定协议。考虑如下命令:
1 | bsd#1 tcpdump udp port domain |
这会抓取使用UDP的DNS名查找但不包括使用TCP的DNS zone传输数据。而之前的两条命令会同时抓取这两种数据。
报文特征:
过滤器也可以基于报文特征比如报文长度或特定字段的内容,过滤器必须包含关系运算符。要指定长度,使用关键字less或greater。如下例所示:
1 | bsd1# tcpdump greater 200 |
该命令收集长度大于200字节的报文。
根据报文内容过滤更加复杂,因为用户必须理解报文头的结构。但是尽管如此,或者说正因如此,这一方式能够使用户最大限度的控制抓取的数据。
一般使用语法 proto [ expr : size ]。字段proto指定要查看的报文头——ip则查看IP头,tcp则查看TCP头,以此类推。expr字段给出从报文头索引0开始的位移。即:报文头的第一个字节为0,第二字节为1,以此类推。size字段是可选的,指定需要使用的字节数,1,2或4。
1 | bsd1# tcpdump "ip[9] = 6" |
查看第十字节的IP头,协议值为6。注意这里必须使用引号。撇号或引号都可以,但反引号将无法正常工作。
1 | bsd1# tcpdump tcp |
也是等效的,因为TCP协议编号为6。
这一方式常常作为掩码来选择特定比特位。值可以是十六进制。可通过语法&加上比特掩码来指定。下例提取从以太网头第一字节开始(即目的地址第一字节),提取低阶比特位,并确保该位不为0:
1 | bsd1# tcpdump 'ether[0] & 1 != 0' |
该条件会选取广播和多播报文。
以上两个例子都有更好的方法来匹配报文。作为一个更实际的例子,考虑以下命令:
1 | 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”。