前言 tcpdump 是一个很常用的网络包分析工具,可以用来显示通过网络传输到本系统的 TCP/IP 以及其他网络的数据包。tcpdump 使用 libpcap 库来抓取网络报,这个库在几乎在所有的 Linux/Unix 中都有。在 Windows 中我们通常会使用 Wireshark 进行图形化操作相当便捷,然而在 Linux 环境中如何巧妙应用 tcpdump 的命令来操作提升效率就显得尤为重要。在本文中,我们将会通过一些实例来演示如何使用 tcpdump 命令。
tcpdump 是一款灵活、功能强大的抓包工具,能有效地帮助排查网络故障问题。
更新历史 2019年02月27日 - 更新tcpdump抓包规则常用命令 2018年12月11日 - 初稿
阅读原文 - https://wsgzao.github.io/post/tcpdump/
扩展阅读
Wireshark - https://www.wireshark.org/#download tcpdump - http://www.tcpdump.org/ 在 Linux 命令行中使用 tcpdump 抓包 - https://linux.cn/article-10191-1.html 抓包工具 tcpdump 用法说明 - https://www.cnblogs.com/f-ck-need-u/p/7064286.html
tcpdump简介
tcpdump, a powerful command-line packet analyzer; and libpcap, a portable C/C++ library for network traffic capture.
Tcpdump prints out a description of the contents of packets on a network interface that match the boolean expression; the description is preceded by a time stamp, printed, by default, as hours, minutes, seconds, and fractions of a second since midnight. It can also be run with the -w flag, which causes it to save the packet data to a file for later analysis, and/or with the -r flag, which causes it to read from a saved packet file rather than to read packets from a network interface. It can also be run with the -V flag, which causes it to read a list of saved packet files. In all cases, only packets that match expression will be processed by tcpdump.
tcpdump 是一款用于截取网络分组,并过滤输出分组内容的工具。tcpdump 凭借强大的功能和灵活的截取策略,使其成为类 UNIX 系统下用于网络分析和问题排查的首选工具。 tcpdump 提供了源代码,公开了接口,因此具备很强的可扩展性,对于网络维护和入侵者都是非常有用的工具。tcpdump 存在于基本的 Linux 系统中,由于它需要将网络界面设置为混杂模式,普通用户不能正常执行,但具备 root 权限的用户可以直接执行它来获取网络上的信息。因此系统中存在网络分析工具主要不是对本机安全的威胁,而是对网络上的其他计算机的安全存在威胁。tcpdump 可以将网络中传送的数据包的 “头” 完全截获下来提供分析。它支持针对网络层、协议、主机、网络或端口的过滤,并提供 and、or、not 等逻辑语句来帮助我们去掉无用的信息。
tcpdump安装
tcpdump 默认在几乎所有的 Linux 发行版中都可用,但若你的 Linux 上没有的话,使用下面方法进行安装。
CentOS/RHEL 使用下面命令在 CentOS 和 RHEL 上安装 tcpdump,
sudo yum install tcpdump*
Fedora 使用下面命令在 Fedora 上安装 tcpdump:
dnf install tcpdump
Ubuntu/Debian/Linux Mint 在 Ubuntu/Debain/Linux Mint 上使用下面命令安装 tcpdump:
apt-get install tcpdump
tcpdump常用命令解释
tcpdump [ 选项 ] [ -c 数量 ] [ -i 网络接口 ] [ -w 文件名 ] [ 表达式 ]
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 man tcpdump ... tcpdump [ -AbdDefhHIJKlLnNOpqStuUvxX [ -c count ] [ -C file_size ] [ -G rotate_seconds ] [ -F file ] [ -i interface ] [ -j tstamp_type ] [ -m module ] [ -M secret ] [ --number ] [ -Q in |out|inout ] [ -r file ] [ -V file ] [ -s snaplen ] [ -T type ] [ -w file ] [ -W filecount ] [ -E spi@ipaddr algo:secret,... ] [ -y datalinktype ] [ -z postrotate-command ] [ -Z user ] [ --time-stamp-precision=tstamp_precision ] [ --immediate-mode ] [ --version ] [ expression ] ... 选项翻译如下: -l:使标准输出变为缓冲行形式; -c:抓包次数; -nn:直接以 IP 及 Port Number 显示,而非主机名与服务名称; -s :<数据包大小> 设置每个数据包的大小; -i:指定监听的网络接口; -r:从指定的文件中读取包; -w:输出信息保存到指定文件; -a:将网络地址和广播地址转变成名字; -d:将匹配信息包的代码以人们能够理解的汇编格式给出; -e:在输出行打印出数据链路层的头部信息; -f:将外部的Internet地址以数字的形式打印出来; -t:在输出的每一行不打印时间戳; -v :输出稍微详细的报文信息;--vv则输出更详细信息。
表达式指正则表达式,tcpdump 利用它作为过滤报文的条件,如果一个报文满足表达式的条件,则会捕获该报文。如果没有给出任何条件,则会截获网络上所有的信息包。 在表达式中一般有如下几种类型的关键字:
关于类型的关键字: host(缺省类型): 指明一台主机,如:host 10.215.20.13 net: 指定网络地址,net 10.215.20.0 port: 指明端口号,port 3306
确定传输方向的关键字:
dst or src(缺省值) 指定源或者目标地址是 10.215.20.13的流量包 src: src 10.9.51.13, 指定源地址是10.9.51.13 dst: dst net 172.0.0.0, 指定目标网络地址是172.0.0.0 dst and src 比如: src host 10.9.51.13 and dst host 10.215.20.13
协议的关键字:
协议的关键字:缺省值是监听所有协议的信息包 ip arp tcp udp icmp
三种逻辑运算:
非 : ! , not 与 : && , and 或 : || , or
例子: 抓取所有经过 bond0,目的地址是 10.10.1.254 或 10.10.1.200 端口是 80 的 TCP 数据
tcpdump -i bond0 '((tcp) and (port 80) and ((dst host 10.10.1.254) or (dst host 10.10.1.200)))'
其他重要的关键字:
gateway, broadcast, less(小于), greater(大于)
tcpdump参数实例 tcpdump tcp -i bond0 -tttt -s 0 -c 100 and dst port ! 22 and src net 10.10.1.0/24 -w 20190131.tcpdump
(1) tcp: 协议类型,用来过滤数据报的协议类型。 (2) -i bond0 : 只抓取经过接口bond0的包 (3) -tttt : 使用格式 2019-02-02 10:37:37.120297,便于分析。 (4) -s 0: 抓取数据包时默认抓取长度为68字节。加上-s 0 后可以抓到完整的数据包 (5) -c 100: 只抓取100个数据包 (6) dst port ! 22: 不抓取目标端口是22的数据包 (7) src net 10.10.1.0/24:数据包的源网络地址为10.10.1.0/24 (8) -w 20190131.tcpdump:保存成tcpdump文件中,方便使用wireshark分析抓包结果。
还有其他常用的参数:
-D:列出所有可用的网络接口 -n:禁用域名解析,让tcpdump直接输出IP地址. -X:以16进制格式输出数据包的内容,不加该参数,会只输出iptcp/udp头部信息。 加上该选项会将整个数据包输出。 -vvvv 该参数其实是-v与-vvv的组合。 -v会输出稍微详细一点的信息包括校验和ttl之类的; -vvv会尝试解析应用层协议,输出详细信息。二者组合就能完整的详细信息。 -A:以ASCII值显示抓到的包,比如和MySQL的交互时,可以通过-A查看包的文本内容.
tcpdump命令演示 从所有网卡中捕获数据包 运行下面命令来从所有网卡中捕获数据包:
tcpdump -i any
从指定网卡中捕获数据包 要从指定网卡中捕获数据包,运行:
tcpdump -i eth0
将捕获的包写入文件 使用 -w 选项将所有捕获的包写入文件:
tcpdump -i eth1 -w packets_file
读取之前产生的 tcpdump 文件 使用下面命令从之前创建的 tcpdump 文件中读取内容:
tcpdump -r packets_file
获取更多的包信息,并且以可读的形式显示时间戳 要获取更多的包信息同时以可读的形式显示时间戳,使用:
tcpdump -ttttnnvvS
查看整个网络的数据包 要获取整个网络的数据包,在终端执行下面命令:
tcpdump net 192.168.1.0/24
根据 IP 地址查看报文 要获取指定 IP 的数据包,不管是作为源地址还是目的地址,使用下面命令:
tcpdump host 192.168.1.100
要指定 IP 地址是源地址或是目的地址则使用:
tcpdump src 192.168.1.100
tcpdump dst 192.168.1.100
查看某个协议或端口号的数据包 要查看某个协议的数据包,运行下面命令:
tcpdump ssh
要捕获某个端口或一个范围的数据包,使用:
tcpdump port 22
tcpdump portrange 22-125
我们也可以与 src 和 dst 选项连用来捕获指定源端口或指定目的端口的报文。
我们还可以使用 “与” (and,&&)、“或” (or,|| ) 和 “非”(not,!) 来将两个条件组合起来。当我们需要基于某些条件来分析网络报文是非常有用。
使用 “与” 可以使用 and 或者符号 && 来将两个或多个条件组合起来。比如:
tcpdump src 192.168.1.100 && port 22 -w ssh_packets
使用 “或” “或” 会检查是否匹配命令所列条件中的其中一条,像这样:
tcpdump src 192.168.1.100 or dst 192.168.1.50 && port 22 -w ssh_packets
tcpdump port 443 or 80 -w http_packets
使用 “非” 当我们想表达不匹配某项条件时可以使用 “非”,像这样:
tcpdump -i eth0 src port not 22
这会捕获 eth0 上除了 22 号端口的所有通讯。
tcpdump抓包规则常用命令
下面的例子全是以抓取 eth0 接口为例,如果不加”-i eth0” 是表示抓取所有的接口包括 lo
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 tcpdump -i eth0 -vnn host 172.16.1.122 tcpdump -i eth0 -vnn net 172.16.1.0/24 tcpdump -i eth0 -vnn port 22 tcpdump -i eth0 -vnn udp tcpdump -i eth0 -vnn icmp tcpdump -i eth0 -vnn arp tcpdump -i eth0 -vnn ip tcpdump -i eth0 -vnn src host 172.16.1.122 tcpdump -i eth0 -vnn dst host 172.16.1.122 tcpdump -i eth0 -vnn src port 22 tcpdump -i eth0 -vnn src host 172.16.1.253 and dst port 22 tcpdump -i eth0 -vnn src host 172.16.1.122 or port 22 tcpdump -i eth0 -vnn src host 172.16.1.122 and not port 22 tcpdump -i eth0 -vnn \( src host 172.16.1.2 and dst port 22 \) or \( src host 172.16.1.65 and dst port 80 \) tcpdump -i eth0 -vnn 'src host 172.16.1.59 and dst port 22' or ' src host 172.16.1.68 and dst port 80 ' tcpdump –i eth0 -vnn -w /tmp/fil1 -c 100 tcpdump –i eth0 -vnn -r /tmp/fil1 tcp tcpdump –i eth0 -vnn -r /tmp/fil1 host 172.16.1.58 tcpdump -i any -nn 'ip[16] == 10' tcpdump -i any -nn 'ip[16] == 192 and ip[17] == 168 and ip[18] == 1 and ip[19] > 9 and ip[19] < 101' tcpdump -i any -nn -c 10000 port 443 > tcpdump.log cat tcpdump.log | awk '{print $3}' | awk -F '.' '{print $1 "." $2 "." $3 "." $4}' | sort | uniq -c | sort -rncat tcpdump.log | awk '{print $1}' | awk -F '.' '{print $1"."$2"."$3"."$4}' | sort | uniq -c | sort -rn | grep -v ":"
tcpdump抓包实践 使用 tcpdump 抓包,需要管理员权限,因此下面的示例中绝大多数命令都是以 sudo 开头。
首先,先用 tcpdump -D 命令列出可以抓包的网络接口:
1 2 3 4 5 6 $ sudo tcpdump -D 1.eth0 2.virbr0 3.eth1 4.any (Pseudo-device that captures on all interfaces) 5.lo [Loopback]
如上所示,可以看到我的机器中所有可以抓包的网络接口。其中特殊接口 any 可用于抓取所有活动的网络接口的数据包。
我们就用如下命令先对 any 接口进行抓包:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 $ sudo tcpdump -i any tcpdump: verbose output suppressed, use -v or -vv for full protocol decode listening on any, link-type LINUX_SLL (Linux cooked), capture size 262144 bytes 09:56:18.293641 IP rhel75.localdomain.ssh > 192.168.64.1.56322: Flags [P.], seq 3770820720:3770820916, ack 3503648727, win 309, options [nop,nop,TS val 76577898 ecr 510770929], length 196 09:56:18.293794 IP 192.168.64.1.56322 > rhel75.localdomain.ssh: Flags [.], ack 196, win 391, options [nop,nop,TS val 510771017 ecr 76577898], length 0 09:56:18.295058 IP rhel75.59883 > gateway.domain: 2486+ PTR? 1.64.168.192.in-addr.arpa. (43) 09:56:18.310225 IP gateway.domain > rhel75.59883: 2486 NXDomain* 0/1/0 (102) 09:56:18.312482 IP rhel75.49685 > gateway.domain: 34242+ PTR? 28.64.168.192.in-addr.arpa. (44) 09:56:18.322425 IP gateway.domain > rhel75.49685: 34242 NXDomain* 0/1/0 (103) 09:56:18.323164 IP rhel75.56631 > gateway.domain: 29904+ PTR? 1.122.168.192.in-addr.arpa. (44) 09:56:18.323342 IP rhel75.localdomain.ssh > 192.168.64.1.56322: Flags [P.], seq 196:584, ack 1, win 309, options [nop,nop,TS val 76577928 ecr 510771017], length 388 09:56:18.323563 IP 192.168.64.1.56322 > rhel75.localdomain.ssh: Flags [.], ack 584, win 411, options [nop,nop,TS val 510771047 ecr 76577928], length 0 09:56:18.335569 IP gateway.domain > rhel75.56631: 29904 NXDomain* 0/1/0 (103) 09:56:18.336429 IP rhel75.44007 > gateway.domain: 61677+ PTR? 98.122.168.192.in-addr.arpa. (45) 09:56:18.336655 IP gateway.domain > rhel75.44007: 61677* 1/0/0 PTR rhel75. (65) 09:56:18.337177 IP rhel75.localdomain.ssh > 192.168.64.1.56322: Flags [P.], seq 584:1644, ack 1, win 309, options [nop,nop,TS val 76577942 ecr 510771047], length 1060 ---- SKIPPING LONG OUTPUT ----- 09:56:19.342939 IP 192.168.64.1.56322 > rhel75.localdomain.ssh: Flags [.], ack 1752016, win 1444, options [nop,nop,TS val 510772067 ecr 76578948], length 0 ^C 9003 packets captured 9010 packets received by filter 7 packets dropped by kernel $
tcpdump 会持续抓包直到收到中断信号。你可以按 Ctrl+C 来停止抓包。正如上面示例所示,tcpdump 抓取了超过 9000 个数据包。在这个示例中,由于我是通过 ssh 连接到服务器,所以 tcpdump 也捕获了所有这类数据包。-c 选项可以用于限制 tcpdump 抓包的数量:
1 2 3 4 5 6 7 8 9 10 11 12 13 $ sudo tcpdump -i any -c 5 tcpdump: verbose output suppressed, use -v or -vv for full protocol decode listening on any, link-type LINUX_SLL (Linux cooked), capture size 262144 bytes 11:21:30.242740 IP rhel75.localdomain.ssh > 192.168.64.1.56322: Flags [P.], seq 3772575680:3772575876, ack 3503651743, win 309, options [nop,nop,TS val 81689848 ecr 515883153], length 196 11:21:30.242906 IP 192.168.64.1.56322 > rhel75.localdomain.ssh: Flags [.], ack 196, win 1443, options [nop,nop,TS val 515883235 ecr 81689848], length 0 11:21:30.244442 IP rhel75.43634 > gateway.domain: 57680+ PTR? 1.64.168.192.in-addr.arpa. (43) 11:21:30.244829 IP gateway.domain > rhel75.43634: 57680 NXDomain 0/0/0 (43) 11:21:30.247048 IP rhel75.33696 > gateway.domain: 37429+ PTR? 28.64.168.192.in-addr.arpa. (44) 5 packets captured 12 packets received by filter 0 packets dropped by kernel $
如上所示,tcpdump 在抓取 5 个数据包后自动停止了抓包。这在有些场景中十分有用 —— 比如你只需要抓取少量的数据包用于分析。当我们需要使用过滤规则抓取特定的数据包(如下所示)时,-c 的作用就十分突出了。
在上面示例中,tcpdump 默认是将 IP 地址和端口号解析为对应的接口名以及服务协议名称。而通常在网络故障排查中,使用 IP 地址和端口号更便于分析问题;用 -n 选项显示 IP 地址,-nn 选项显示端口号:
1 2 3 4 5 6 7 8 9 10 11 $ sudo tcpdump -i any -c5 -nn tcpdump: verbose output suppressed, use -v or -vv for full protocol decode listening on any, link-type LINUX_SLL (Linux cooked), capture size 262144 bytes 23:56:24.292206 IP 192.168.64.28.22 > 192.168.64.1.35110: Flags [P.], seq 166198580:166198776, ack 2414541257, win 309, options [nop,nop,TS val 615664 ecr 540031155], length 196 23:56:24.292357 IP 192.168.64.1.35110 > 192.168.64.28.22: Flags [.], ack 196, win 1377, options [nop,nop,TS val 540031229 ecr 615664], length 0 23:56:24.292570 IP 192.168.64.28.22 > 192.168.64.1.35110: Flags [P.], seq 196:568, ack 1, win 309, options [nop,nop,TS val 615664 ecr 540031229], length 372 23:56:24.292655 IP 192.168.64.1.35110 > 192.168.64.28.22: Flags [.], ack 568, win 1400, options [nop,nop,TS val 540031229 ecr 615664], length 0 23:56:24.292752 IP 192.168.64.28.22 > 192.168.64.1.35110: Flags [P.], seq 568:908, ack 1, win 309, options [nop,nop,TS val 615664 ecr 540031229], length 340 5 packets captured 6 packets received by filter 0 packets dropped by kernel
如上所示,抓取的数据包中显示 IP 地址和端口号。这样还可以阻止 tcpdump 发出 DNS 查找,有助于在网络故障排查中减少数据流量。
现在你已经会抓包了,让我们来分析一下这些抓包输出的含义吧。
理解抓取的报文 tcpdump 能够抓取并解码多种协议类型的数据报文,如 TCP、UDP、ICMP 等等。虽然这里我们不可能介绍所有的数据报文类型,但可以分析下 TCP 类型的数据报文,来帮助你入门。更多有关 tcpdump 的详细介绍可以参考其 帮助手册。tcpdump 抓取的 TCP 报文看起来如下:
1 08:41:13.729687 IP 192.168.64.28.22 > 192.168.64.1.41916: Flags [P.], seq 196:568, ack 1, win 309, options [nop,nop,TS val 117964079 ecr 816509256], length 372
具体的字段根据不同的报文类型会有不同,但上面这个例子是一般的格式形式。
第一个字段 08:41:13.729687 是该数据报文被抓取的系统本地时间戳。
然后,IP 是网络层协议类型,这里是 IPv4,如果是 IPv6 协议,该字段值是 IP6。
192.168.64.28.22 是源 ip 地址和端口号,紧跟其后的是目的 ip 地址和其端口号,这里是 192.168.64.1.41916。
在源 IP 和目的 IP 之后,可以看到是 TCP 报文标记段 Flags [P.]。该字段通常取值如下:
值
标志类型
描述
S
SYN
Connection Start 发起连接标志
F
FIN
Connection Finish 关闭连接标志
P
PUSH
Data push 传送数据标志
R
RST
Connection reset 异常关闭连接
.
ACK
Acknowledgment 表示确认包
该字段也可以是这些值的组合,例如 [S.] 代表 SYN-ACK 数据包。
接下来是该数据包中数据的序列号。对于抓取的第一个数据包,该字段值是一个绝对数字,后续包使用相对数值,以便更容易查询跟踪。例如此处 seq 196:568 代表该数据包包含该数据流的第 196 到 568 字节。
接下来是 ack 值:ack 1。该数据包是数据发送方,ack 值为 1。在数据接收方,该字段代表数据流上的下一个预期字节数据,例如,该数据流中下一个数据包的 ack 值应该是 568。
接下来字段是接收窗口大小 win 309,它表示接收缓冲区中可用的字节数,后跟 TCP 选项如 MSS(最大段大小)或者窗口比例值。更详尽的 TCP 协议内容请参考 Transmission Control Protocol(TCP) Parameters。
最后,length 372 代表数据包有效载荷字节长度。这个长度和 seq 序列号中字节数值长度是不一样的。
现在让我们学习如何过滤数据报文以便更容易的分析定位问题。
过滤数据包 正如上面所提,tcpdump 可以抓取很多种类型的数据报文,其中很多可能和我们需要查找的问题并没有关系。举个例子,假设你正在定位一个与 web 服务器连接的网络问题,就不必关系 SSH 数据报文,因此在抓包结果中过滤掉 SSH 报文可能更便于你分析问题。
tcpdump 有很多参数选项可以设置数据包过滤规则,例如根据源 IP 以及目的 IP 地址,端口号,协议等等规则来过滤数据包。下面就介绍一些最常用的过滤方法。
协议 在命令中指定协议便可以按照协议类型来筛选数据包。比方说用如下命令只要抓取 ICMP 报文:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 $ sudo tcpdump -i any -c5 icmp tcpdump: verbose output suppressed, use -v or -vv for full protocol decode listening on any, link-type LINUX_SLL (Linux cooked), capture size 262144 bytes 然后再打开一个终端,去 ping 另一台机器: $ ping opensource.com PING opensource.com (54.204.39.132) 56(84) bytes of data. 64 bytes from ec2-54-204-39-132.compute-1.amazonaws.com (54.204.39.132): icmp_seq=1 ttl=47 time=39.6 ms 回到运行 tcpdump 命令的终端中,可以看到它筛选出了 ICMP 报文。这里 tcpdump 并没有显示有关 opensource.com 的域名解析数据包: 09:34:20.136766 IP rhel75 > ec2-54-204-39-132.compute-1.amazonaws.com: ICMP echo request, id 20361, seq 1, length 64 09:34:20.176402 IP ec2-54-204-39-132.compute-1.amazonaws.com > rhel75: ICMP echo reply, id 20361, seq 1, length 64 09:34:21.140230 IP rhel75 > ec2-54-204-39-132.compute-1.amazonaws.com: ICMP echo request, id 20361, seq 2, length 64 09:34:21.180020 IP ec2-54-204-39-132.compute-1.amazonaws.com > rhel75: ICMP echo reply, id 20361, seq 2, length 64 09:34:22.141777 IP rhel75 > ec2-54-204-39-132.compute-1.amazonaws.com: ICMP echo request, id 20361, seq 3, length 64 5 packets captured 5 packets received by filter 0 packets dropped by kernel
主机 用 host 参数只抓取和特定主机相关的数据包:
1 2 3 4 5 6 7 8 9 10 11 12 13 $ sudo tcpdump -i any -c5 -nn host 54.204.39.132 tcpdump: verbose output suppressed, use -v or -vv for full protocol decode listening on any, link-type LINUX_SLL (Linux cooked), capture size 262144 bytes 09:54:20.042023 IP 192.168.122.98.39326 > 54.204.39.132.80: Flags [S], seq 1375157070, win 29200, options [mss 1460,sackOK,TS val 122350391 ecr 0,nop,wscale 7], length 0 09:54:20.088127 IP 54.204.39.132.80 > 192.168.122.98.39326: Flags [S.], seq 1935542841, ack 1375157071, win 28960, options [mss 1460,sackOK,TS val 522713542 ecr 122350391,nop,wscale 9], length 0 09:54:20.088204 IP 192.168.122.98.39326 > 54.204.39.132.80: Flags [.], ack 1, win 229, options [nop,nop,TS val 122350437 ecr 522713542], length 0 09:54:20.088734 IP 192.168.122.98.39326 > 54.204.39.132.80: Flags [P.], seq 1:113, ack 1, win 229, options [nop,nop,TS val 122350438 ecr 522713542], length 112: HTTP: GET / HTTP/1.1 09:54:20.129733 IP 54.204.39.132.80 > 192.168.122.98.39326: Flags [.], ack 113, win 57, options [nop,nop,TS val 522713552 ecr 122350438], length 0 5 packets captured 5 packets received by filter 0 packets dropped by kernel 如上所示,只抓取和显示与 54.204.39.132 有关的数据包。
端口号 tcpdump 可以根据服务类型或者端口号来筛选数据包。例如,抓取和 HTTP 服务相关的数据包:
1 2 3 4 5 6 7 8 9 10 11 12 $ sudo tcpdump -i any -c5 -nn port 80 tcpdump: verbose output suppressed, use -v or -vv for full protocol decode listening on any, link-type LINUX_SLL (Linux cooked), capture size 262144 bytes 09:58:28.790548 IP 192.168.122.98.39330 > 54.204.39.132.80: Flags [S], seq 1745665159, win 29200, options [mss 1460,sackOK,TS val 122599140 ecr 0,nop,wscale 7], length 0 09:58:28.834026 IP 54.204.39.132.80 > 192.168.122.98.39330: Flags [S.], seq 4063583040, ack 1745665160, win 28960, options [mss 1460,sackOK,TS val 522775728 ecr 122599140,nop,wscale 9], length 0 09:58:28.834093 IP 192.168.122.98.39330 > 54.204.39.132.80: Flags [.], ack 1, win 229, options [nop,nop,TS val 122599183 ecr 522775728], length 0 09:58:28.834588 IP 192.168.122.98.39330 > 54.204.39.132.80: Flags [P.], seq 1:113, ack 1, win 229, options [nop,nop,TS val 122599184 ecr 522775728], length 112: HTTP: GET / HTTP/1.1 09:58:28.878445 IP 54.204.39.132.80 > 192.168.122.98.39330: Flags [.], ack 113, win 57, options [nop,nop,TS val 522775739 ecr 122599184], length 0 5 packets captured 5 packets received by filter 0 packets dropped by kernel
IP 地址 / 主机名 同样,你也可以根据源 IP 地址或者目的 IP 地址或者主机名来筛选数据包。例如抓取源 IP 地址为 192.168.122.98 的数据包:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 $ sudo tcpdump -i any -c5 -nn src 192.168.122.98 tcpdump: verbose output suppressed, use -v or -vv for full protocol decode listening on any, link-type LINUX_SLL (Linux cooked), capture size 262144 bytes 10:02:15.220824 IP 192.168.122.98.39436 > 192.168.122.1.53: 59332+ A? opensource.com. (32) 10:02:15.220862 IP 192.168.122.98.39436 > 192.168.122.1.53: 20749+ AAAA? opensource.com. (32) 10:02:15.364062 IP 192.168.122.98.39334 > 54.204.39.132.80: Flags [S], seq 1108640533, win 29200, options [mss 1460,sackOK,TS val 122825713 ecr 0,nop,wscale 7], length 0 10:02:15.409229 IP 192.168.122.98.39334 > 54.204.39.132.80: Flags [.], ack 669337581, win 229, options [nop,nop,TS val 122825758 ecr 522832372], length 0 10:02:15.409667 IP 192.168.122.98.39334 > 54.204.39.132.80: Flags [P.], seq 0:112, ack 1, win 229, options [nop,nop,TS val 122825759 ecr 522832372], length 112: HTTP: GET / HTTP/1.1 5 packets captured 5 packets received by filter 0 packets dropped by kernel 注意此处示例中抓取了来自源 IP 地址 192.168.122.98 的 53 端口以及 80 端口的数据包,它们的应答包没有显示出来因为那些包的源 IP 地址已经变了。 相对的,使用 dst 就是按目的 IP / 主机名来筛选数据包。 $ sudo tcpdump -i any -c5 -nn dst 192.168.122.98 tcpdump: verbose output suppressed, use -v or -vv for full protocol decode listening on any, link-type LINUX_SLL (Linux cooked), capture size 262144 bytes 10:05:03.572931 IP 192.168.122.1.53 > 192.168.122.98.47049: 2248 1/0/0 A 54.204.39.132 (48) 10:05:03.572944 IP 192.168.122.1.53 > 192.168.122.98.47049: 33770 0/0/0 (32) 10:05:03.621833 IP 54.204.39.132.80 > 192.168.122.98.39338: Flags [S.], seq 3474204576, ack 3256851264, win 28960, options [mss 1460,sackOK,TS val 522874425 ecr 122993922,nop,wscale 9], length 0 10:05:03.667767 IP 54.204.39.132.80 > 192.168.122.98.39338: Flags [.], ack 113, win 57, options [nop,nop,TS val 522874436 ecr 122993972], length 0 10:05:03.672221 IP 54.204.39.132.80 > 192.168.122.98.39338: Flags [P.], seq 1:643, ack 113, win 57, options [nop,nop,TS val 522874437 ecr 122993972], length 642: HTTP: HTTP/1.1 302 Found 5 packets captured 5 packets received by filter 0 packets dropped by kernel
多条件筛选 当然,可以使用多条件组合来筛选数据包,使用 and 以及 or 逻辑操作符来创建过滤规则。例如,筛选来自源 IP 地址 192.168.122.98 的 HTTP 数据包:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 $ sudo tcpdump -i any -c5 -nn src 192.168.122.98 and port 80 tcpdump: verbose output suppressed, use -v or -vv for full protocol decode listening on any, link-type LINUX_SLL (Linux cooked), capture size 262144 bytes 10:08:00.472696 IP 192.168.122.98.39342 > 54.204.39.132.80: Flags [S], seq 2712685325, win 29200, options [mss 1460,sackOK,TS val 123170822 ecr 0,nop,wscale 7], length 0 10:08:00.516118 IP 192.168.122.98.39342 > 54.204.39.132.80: Flags [.], ack 268723504, win 229, options [nop,nop,TS val 123170865 ecr 522918648], length 0 10:08:00.516583 IP 192.168.122.98.39342 > 54.204.39.132.80: Flags [P.], seq 0:112, ack 1, win 229, options [nop,nop,TS val 123170866 ecr 522918648], length 112: HTTP: GET / HTTP/1.1 10:08:00.567044 IP 192.168.122.98.39342 > 54.204.39.132.80: Flags [.], ack 643, win 239, options [nop,nop,TS val 123170916 ecr 522918661], length 0 10:08:00.788153 IP 192.168.122.98.39342 > 54.204.39.132.80: Flags [F.], seq 112, ack 643, win 239, options [nop,nop,TS val 123171137 ecr 522918661], length 0 5 packets captured 5 packets received by filter 0 packets dropped by kernel 你也可以使用括号来创建更为复杂的过滤规则,但在 shell 中请用引号包含你的过滤规则以防止被识别为 shell 表达式: $ sudo tcpdump -i any -c5 -nn "port 80 and (src 192.168.122.98 or src 54.204.39.132)" tcpdump: verbose output suppressed, use -v or -vv for full protocol decode listening on any, link-type LINUX_SLL (Linux cooked), capture size 262144 bytes 10:10:37.602214 IP 192.168.122.98.39346 > 54.204.39.132.80: Flags [S], seq 871108679, win 29200, options [mss 1460,sackOK,TS val 123327951 ecr 0,nop,wscale 7], length 0 10:10:37.650651 IP 54.204.39.132.80 > 192.168.122.98.39346: Flags [S.], seq 854753193, ack 871108680, win 28960, options [mss 1460,sackOK,TS val 522957932 ecr 123327951,nop,wscale 9], length 0 10:10:37.650708 IP 192.168.122.98.39346 > 54.204.39.132.80: Flags [.], ack 1, win 229, options [nop,nop,TS val 123328000 ecr 522957932], length 0 10:10:37.651097 IP 192.168.122.98.39346 > 54.204.39.132.80: Flags [P.], seq 1:113, ack 1, win 229, options [nop,nop,TS val 123328000 ecr 522957932], length 112: HTTP: GET / HTTP/1.1 10:10:37.692900 IP 54.204.39.132.80 > 192.168.122.98.39346: Flags [.], ack 113, win 57, options [nop,nop,TS val 522957942 ecr 123328000], length 0 5 packets captured 5 packets received by filter 0 packets dropped by kernel 该例子中我们只抓取了来自源 IP 为 192.168.122.98 或者 54.204.39.132 的 HTTP (端口号 80)的数据包。使用该方法就很容易抓取到数据流中交互双方的数据包了。
检查数据包内容 在以上的示例中,我们只按数据包头部的信息来建立规则筛选数据包,例如源地址、目的地址、端口号等等。有时我们需要分析网络连接问题,可能需要分析数据包中的内容来判断什么内容需要被发送、什么内容需要被接收等。tcpdump 提供了两个选项可以查看数据包内容,-X 以十六进制打印出数据报文内容,-A 打印数据报文的 ASCII 值。
例如,HTTP 请求报文内容如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 $ sudo tcpdump -i any -c10 -nn -A port 80 tcpdump: verbose output suppressed, use -v or -vv for full protocol decode listening on any, link-type LINUX_SLL (Linux cooked), capture size 262144 bytes 13:02:14.871803 IP 192.168.122.98.39366 > 54.204.39.132.80: Flags [S], seq 2546602048, win 29200, options [mss 1460,sackOK,TS val 133625221 ecr 0,nop,wscale 7], length 0 E..<..@.@.....zb6.'....P...@......r............ ............................ 13:02:14.910734 IP 54.204.39.132.80 > 192.168.122.98.39366: Flags [S.], seq 1877348646, ack 2546602049, win 28960, options [mss 1460,sackOK,TS val 525532247 ecr 133625221,nop,wscale 9], length 0 E..<..@./..a6.' ...zb.P..o..&...A..q a...........R.W....... ................ 13:02:14.910832 IP 192.168.122.98.39366 > 54.204.39.132.80: Flags [.], ack 1, win 229, options [nop,nop,TS val 133625260 ecr 525532247], length 0 E..4..@.@.....zb6.'....P...Ao..' ........... .....R.W................ 13:02:14.911808 IP 192.168.122.98.39366 > 54.204.39.132.80: Flags [P.], seq 1:113, ack 1, win 229, options [nop,nop,TS val 133625261 ecr 525532247], length 112: HTTP: GET / HTTP/1.1 E.....@.@..1..zb6.'....P...Ao..' ........... .....R.WGET / HTTP/1.1 User-Agent: Wget/1.14 (linux-gnu) Accept: */* Host: opensource.com Connection: Keep-Alive ................ 13:02:14.951199 IP 54.204.39.132.80 > 192.168.122.98.39366: Flags [.], ack 113, win 57, options [nop,nop,TS val 525532257 ecr 133625261], length 0 E..4.F@./.."6.'...zb.P..o..'.......9.2..... .R.a.................... 13:02:14.955030 IP 54.204.39.132.80 > 192.168.122.98.39366: Flags [P.], seq 1:643, ack 113, win 57, options [nop,nop,TS val 525532258 ecr 133625261], length 642: HTTP: HTTP/1.1 302 Found E....G@./...6.'...zb.P..o..'.......9....... .R.b....HTTP/1.1 302 Found Server: nginx Date: Sun, 23 Sep 2018 17:02:14 GMT Content-Type: text/html; charset=iso-8859-1 Content-Length: 207 X-Content-Type-Options: nosniff Location: https://opensource.com/ Cache-Control: max-age=1209600 Expires: Sun, 07 Oct 2018 17:02:14 GMT X-Request-ID: v-6baa3acc-bf52-11e8-9195-22000ab8cf2d X-Varnish: 632951979 Age: 0 Via: 1.1 varnish (Varnish/5.2) X-Cache: MISS Connection: keep-alive <!DOCTYPE HTML PUBLIC " -//IETF//DTD HTML 2.0//EN"> <html><head> <title>302 Found</title> </head><body> <h1>Found</h1> <p>The document has moved <a href=" https://opensource.com/">here</a>.</p> </body></html> ................ 13:02:14.955083 IP 192.168.122.98.39366 > 54.204.39.132.80: Flags [.], ack 643, win 239, options [nop,nop,TS val 133625304 ecr 525532258], length 0 E..4..@.@.....zb6.'....P....o.............. .....R.b................ 13:02:15.195524 IP 192.168.122.98.39366 > 54.204.39.132.80: Flags [F.], seq 113, ack 643, win 239, options [nop,nop,TS val 133625545 ecr 525532258], length 0 E..4..@.@.....zb6.'....P....o.............. .....R.b................ 13:02:15.236592 IP 54.204.39.132.80 > 192.168.122.98.39366: Flags [F.], seq 643, ack 114, win 57, options [nop,nop,TS val 525532329 ecr 133625545], length 0 E..4.H@./.. 6.'...zb.P..o..........9.I..... .R...................... 13:02:15.236656 IP 192.168.122.98.39366 > 54.204.39.132.80: Flags [.], ack 644, win 239, options [nop,nop,TS val 133625586 ecr 525532329], length 0 E..4..@.@.....zb6.'....P....o.............. .....R.................. 10 packets captured 10 packets received by filter 0 packets dropped by kernel
这对定位一些普通 HTTP 调用 API 接口的问题很有用。当然如果是加密报文,这个输出也就没多大用了。
保存抓包数据 tcpdump 提供了保存抓包数据的功能以便后续分析数据包。例如,你可以夜里让它在那里抓包,然后早上起来再去分析它。同样当有很多数据包时,显示过快也不利于分析,将数据包保存下来,更有利于分析问题。
使用 -w 选项来保存数据包而不是在屏幕上显示出抓取的数据包:
1 2 3 4 5 6 $ sudo tcpdump -i any -c10 -nn -w webserver.pcap port 80 [sudo] password for ricardo: tcpdump: listening on any, link-type LINUX_SLL (Linux cooked), capture size 262144 bytes 10 packets captured 10 packets received by filter 0 packets dropped by kernel
该命令将抓取的数据包保存到文件 webserver.pcap。后缀名 pcap 表示文件是抓取的数据包格式。
正如示例中所示,保存数据包到文件中时屏幕上就没有任何有关数据报文的输出,其中 -c10 表示抓取到 10 个数据包后就停止抓包。如果想有一些反馈来提示确实抓取到了数据包,可以使用 -v 选项。
tcpdump 将数据包保存在二进制文件中,所以不能简单的用文本编辑器去打开它。使用 -r 选项参数来阅读该文件中的报文内容:
1 2 3 4 5 6 7 8 9 10 11 12 13 $ tcpdump -nn -r webserver.pcap reading from file webserver.pcap, link-type LINUX_SLL (Linux cooked) 13:36:57.679494 IP 192.168.122.98.39378 > 54.204.39.132.80: Flags [S], seq 3709732619, win 29200, options [mss 1460,sackOK,TS val 135708029 ecr 0,nop,wscale 7], length 0 13:36:57.718932 IP 54.204.39.132.80 > 192.168.122.98.39378: Flags [S.], seq 1999298316, ack 3709732620, win 28960, options [mss 1460,sackOK,TS val 526052949 ecr 135708029,nop,wscale 9], length 0 13:36:57.719005 IP 192.168.122.98.39378 > 54.204.39.132.80: Flags [.], ack 1, win 229, options [nop,nop,TS val 135708068 ecr 526052949], length 0 13:36:57.719186 IP 192.168.122.98.39378 > 54.204.39.132.80: Flags [P.], seq 1:113, ack 1, win 229, options [nop,nop,TS val 135708068 ecr 526052949], length 112: HTTP: GET / HTTP/1.1 13:36:57.756979 IP 54.204.39.132.80 > 192.168.122.98.39378: Flags [.], ack 113, win 57, options [nop,nop,TS val 526052959 ecr 135708068], length 0 13:36:57.760122 IP 54.204.39.132.80 > 192.168.122.98.39378: Flags [P.], seq 1:643, ack 113, win 57, options [nop,nop,TS val 526052959 ecr 135708068], length 642: HTTP: HTTP/1.1 302 Found 13:36:57.760182 IP 192.168.122.98.39378 > 54.204.39.132.80: Flags [.], ack 643, win 239, options [nop,nop,TS val 135708109 ecr 526052959], length 0 13:36:57.977602 IP 192.168.122.98.39378 > 54.204.39.132.80: Flags [F.], seq 113, ack 643, win 239, options [nop,nop,TS val 135708327 ecr 526052959], length 0 13:36:58.022089 IP 54.204.39.132.80 > 192.168.122.98.39378: Flags [F.], seq 643, ack 114, win 57, options [nop,nop,TS val 526053025 ecr 135708327], length 0 13:36:58.022132 IP 192.168.122.98.39378 > 54.204.39.132.80: Flags [.], ack 644, win 239, options [nop,nop,TS val 135708371 ecr 526053025], length 0 $
这里不需要管理员权限 sudo 了,因为此刻并不是在网络接口处抓包。
你还可以使用我们讨论过的任何过滤规则来过滤文件中的内容,就像使用实时数据一样。 例如,通过执行以下命令从源 IP 地址 54.204.39.132 检查文件中的数据包:
1 2 3 4 5 6 $ tcpdump -nn -r webserver.pcap src 54.204.39.132 reading from file webserver.pcap, link-type LINUX_SLL (Linux cooked) 13:36:57.718932 IP 54.204.39.132.80 > 192.168.122.98.39378: Flags [S.], seq 1999298316, ack 3709732620, win 28960, options [mss 1460,sackOK,TS val 526052949 ecr 135708029,nop,wscale 9], length 0 13:36:57.756979 IP 54.204.39.132.80 > 192.168.122.98.39378: Flags [.], ack 113, win 57, options [nop,nop,TS val 526052959 ecr 135708068], length 0 13:36:57.760122 IP 54.204.39.132.80 > 192.168.122.98.39378: Flags [P.], seq 1:643, ack 113, win 57, options [nop,nop,TS val 526052959 ecr 135708068], length 642: HTTP: HTTP/1.1 302 Found 13:36:58.022089 IP 54.204.39.132.80 > 192.168.122.98.39378: Flags [F.], seq 643, ack 114, win 57, options [nop,nop,TS val 526053025 ecr 135708327], length 0
下一步做什么? 以上的基本功能已经可以帮助你使用强大的 tcpdump 抓包工具了。更多的内容请参考 tcpdump 网站以及它的帮助文件。
https://hackertarget.com/tcpdump-examples/
tcpdump 命令行工具为分析网络流量数据包提供了强大的灵活性。如果需要使用图形工具来抓包请参考 Wireshark。
Wireshark 还可以用来读取 tcpdump 保存的 pcap 文件。你可以使用 tcpdump 命令行在没有 GUI 界面的远程机器上抓包然后在 Wireshark 中分析数据包。
一站式学习 Wiresharkhttps://community.emc.com/thread/194901 https://www.w3cschool.cn/wireshark/