对于 tcpdump 的使用,大部分管理员会分成两类。有一类管理员,他们熟知 tcpdump 和其中的所有标记;另一类管理员,他们仅了解基本的使用方法,剩下事情都要借助参考手册才能完成。出现这种情况的原因在于, tcpdump 是一个相当高级的命令,使用的时候需要对网络的工作机制有相当深入的了解。在linux操作系统中, tcpdump 命令用来保存和记录网络流量。linux就该这么学,你可以用它来观察网络上发生了什么,并可用来解决各种各样的问题,包括和网络通信无关的问题。除了网络问题,我经常用 tcpdump 解决应用程序的问题。如果你发现两个应用程序之间无法很好工作,可以用 tcpdump 观察出了什么问题。 tcpdump 可以用来抓取和读取数据包,特别是当通信没有被加密的时候。
工具/原料
tcpdump命令工具
基础操作
1、不转换主机名、端口号# tcpdump -n通常情况下, tcpdump 会尝试查找和转换主机名和端口号。# tcpdump你可以通过 -n 标记关闭这个功能。我个人总是使用这个标记,因为我喜欢使用 IP 地址而不是主机名,主机名和端口号的转换经常会带来困扰。但是,知道利用 tcpdump 转换或者不转换的功能还是相当有用的,特别是有些时候,知道源流量(source traffic)来自哪个服务器是相当重要的。
2、增加详细信息# tcpdump -v增加一个简单 -v 标记,输出会包含更多信息,例如一个 IP 包的生存时间(ttl, time to live)、长度和其他的选项。tcpdump 的详细信息有三个等级,你可以通过在命令行增加 v 标记的个数来获取更多的信息。通常我在使用 tcpmdump 的时候,总是使用最高等级的详细信息,因为我希望看到所有信息,以免后面会用到。# tcpdump -vvv -c 1
3、指定网络接口# tcpdump -i eth0通常情况下,如果不指定网络接口, tcpdump 在运行时会选择编号最低的网络接口,一般情况下是 eth0,不过因系统不同可能会有所差异。你可以用 -i 标记来指定网络接口。在大多数 Linux 系统上,any 这一特定的网络接口名用来让 tcpdump 监听所有的接口。我发现这在排查服务器(拥有多个网络接口)的问题特别有用,尤其是牵扯到路由的时候。# tcpdump -i any
4、写入文件# tcpdump -w /path/to/filetcpdump 运行结果会输出在屏幕上。但很多时候,你希望把 tcpdump 的脶巴躔炒输出结果保存在文件中,最简单的方法就是利用 -w 标记。如果你后续还会检查这些网络数据,这样做就特别有用。将这些数据存成一个文件的好处,就是你可以多次读取这个保存下来的文件,并且可以在这个网络流量的快照上使用其它标记或者过滤器(我们后面会讨论到)。# tcpdump -w /var/tmp/tcpdata.pcap
5、读取文件# tcpdump -r /path/to/file一旦你将输出存成文件,就必然需要读取这个文件。要做到这点,你只需要在 -r 标记后指定这个文件的存放路径。一个小提醒,如果你熟悉 wireshark 这类网络诊断工具,也可以利用它们来读取 tcpdump 保存的文件。
6、指定抓包大小# tcpdump -s 100较新版本的 tcpdump 通常可以截获 65535 字节,但某些情况下你不需要截获默认大小的数据包。运行 tcpdump 时,你可以通过 -s 标记来指定快照长度。
7、指定抓包数量# tcpdump -c 10tcpdump 会一直运行,直至你用 CTRL+C 让它退出。你也可以通过 -c 标记后面加上抓包的数量,让 tcpdump 在抓到一定数量的数据包后停止操作。当你不希望看到 tcpdump 的输出大量出现在屏幕上,以至于你无法阅读的时候,就会希望使用这个标记。当然,通常更好的方法是借助过滤器来截获特定的流量。
8、基础知识汇总# tcpdump -nvvv -i any -c 100 -s 100你可以将以上这些基础的标记组合起来使用,来让 tcpdump 提供你所需要的信息。
高级应用
1、过滤器介绍完基础的标记后,我们该介绍过滤器了。 tcpdump 可以通过各式各样的表达式,来过滤所截取或者输出的数据。我在这篇文章里会给出一些简单的例子,以便让你们了解语法规则。你们可以查询 tcpdump 帮助中的 pcap-filter 章节,了解更为详细的信息
2、查找特定主机的流量# tcpdump -nvvv -i any -c 3 host 10.0.3.1运行上述命令, tcpdump 会像前面一样把结果输出到屏幕上,不过只会显示源 IP 或者目的 IP 地址是 10.0.3.1 的数据包。通过增加主机 10.0.3.1 参数,我们可以让 tcpdump 过滤掉源和目的地址不是 10.0.3.1 的数据包。
3、查找特定主机的流量# tcpdump -nvvv -i any -c 3 host 10.0.3.1运行上述命令, tcpdump 会像前面一样把结果输出到屏幕上,不过只会显示源 IP 或者目的 IP 地址是 10.0.3.1 的数据包。通过增加主机 10.0.3.1 参数,我们可以让 tcpdump 过滤掉源和目的地址不是 10.0.3.1 的数据包。
4、只显示源地址为特定主机的流量# tcpdump -nvvv -i any -c 3 src host 10.0.3.1前面的例子显示了源和目的地址是 10.0.3.1 的流量,而上面的命令只显示数据包源地址是 10.0.3.1 的流量。这是通过在 host 前面增加 src 参数来实现的。这个额外的过滤器告诉 tcpdump 查找特定的源地址。 反过来通过 dst 过滤器,可以指定目的地址。
5、过滤源和目的端口# tcpdump -nvvv -i any -c 3 port 22 and port 60738通过类似 and 操作符,你可以在 tcpdump 上使用更为复杂的过滤器描述。这个就类似 if 语句,你就这么想吧。这个例子中,我们使用 and 操作符告诉 tcpdump 只输出端口号是 22 和 60738 的数据包。这点在分析网络问题的时候很有用,因为可以通过这个方法来关注某一个特定会话(session)的数据包。
6、查找两个特定瞿搋村乇端口和来自特定主机的数据流# tcpdump -nvvv -i any -c 20 '(port 80 or port 443) and h泠贾高框ost 10.0.3.169'前面的例子用来排查多端口的协议问题,是非常有效的。如果 Web 服务器的数据流量相当大, tcpdump 的输出可能有点混乱。我们可以通过增加 host 参数进一步限定输出。在这种情况下,我们通过把 or 表达式放在括号中来保持 or 描述。
分析数据
1、理解输出结果打开 tcpdump 的所有选项去截获网络流量是相当困难的,但一旦你拿到这些数据你就要对它进行解读。我们将涉及如何判断源/目的 IP 地址,源/目的端口号,以及 TCP 协议类型的数据包。当然这些是相当基础的,你从 tcpdump 里面获取的信息也远不止这些。
2、判断源和目的地址判断源和目的地址和端口号相当简单。从上面的输出,我们可以看到源 IP 地址是 10.0.3.246,源端口号是 56894, 目的 IP 地址是 192.168.0.92,端口号是 22。一旦你理解 tcpdump 格式后,这些信息很容易判断。如果你还没有猜到格式,你可以按照 src-ip.src-port > dest-ip.dest-port: Flags[S] 格式来分析。源地址位于 > 前面,后面则是目的地址。你可以把 > 想象成一个指向目的地址的箭头符号。
3、判断数据包亿姣灵秀类型10.0.3.246.56894 > 192.168.0.92.22: Flags [S], cksum 0xcf28 (incorrect -> 0x0388), seq 682725222, win 29200, options [mss 1460,sackOK,TS val 619989005 ecr 0,nop,wscale 7], length 0从上面的例子,我们可以判断这个数据包是一个 SYN 数据包。我们是通过 tcpdump 输出中的 [S] 标记字段得出这个结论,不同类型的数据包有不同类型的标记。不需要深入了解 TCP 协议中的数据包类型,你就可以通过下面的速查表来加以判断。[S] – SYN (开始连接)[.] – 没有标记[P] – PSH (数据推送)[F] – FIN (结束连接)[R] – RST (重启连接)在这个版本的 tcpdump 输出中,[S.] 标记代表这个数据包是 SYN-ACK 数据包。
4、数据包检查用十六进制和 ASCII 码打印数据包# tcpdump -nvvv -i any -c 1 -XX 'port 80 and host 10.0.3.1'排查应用程序网络问题的通常做法,就是用 tcpdump 的 -XX 标记打印出 16 进制和 ASCII 码格式的数据包。这是一个相当有用的命令,它可以让你看到源地址,目的地址,数据包类型以及数据包本身。但我不是这个命令输出的粉丝,我认为它太难读了。
5、只打印 ASCII 码格式的数据包# tcpdump -nvvv -i any -c 1 -A 'port 80 and host 10.0.3.1'我倾向于只打印 ASCII 格式数据,这可以帮助我快速定位数据包中发送了什么,哪些是正确的,哪些是错误的。你可以通过 -A 标记来实现这一点。
6、非 TCP 数据流ICMP 数据包# tcpdump -nvvv -i any -c 2 icmpUDP 数据包# tcpdump -nvvv -i any -c 2 udp