tcpdump是一个命令行实用程序,可用于捕获和检查进出系统的网络流量。 它是网络管理员中用于排除网络问题和安全测试的最常用工具。
尽管名称如此,使用tcpdump,您也可以捕获非TCP流量,例如UDP,ARP或ICMP。 捕获的数据包可以写入文件或标准输出。 tcpdump命令最强大的功能之一是它能够使用过滤器并仅捕获要分析的数据。
在本文中,我们将介绍如何在Linux中使用tcpdump命令的基础知识。
安装tcpdump
在大多数Linux发行版和macOS上默认安装了tcpdump。 要检查tcpdump命令在您的系统上是否可用:
[linuxidc@linux:~/www.linuxidc.com]$ tcpdump –version
输出应如下所示:
tcpdump version 4.9.2
libpcap version 1.8.1
OpenSSL 1.1.1 11 Sep 2018
如果您的系统上没有tcpdump,则上面的命令将显示“ 没有那个文件或目录”。 您可以使用发行版的软件包管理器轻松安装tcpdump。
[linuxidc@linux:~/www.linuxidc.com]$ tcpdump –version
bash: /usr/sbin/tcpdump: 没有那个文件或目录
在Ubuntu和Debian上安装tcpdump
$sudo apt update && sudo apt install tcpdump
在CentOS和Fedora上安装tcpdump
$sudo yum install tcpdump
在Arch Linux上安装tcpdump
$sudo pacman -S tcpdump
使用tcpdump捕获数据包
tcpdump命令的常规语法如下:
tcpdump [选项] [过滤器表达式]
- 命令选项使您可以控制命令的行为。
- 过滤器表达式定义将捕获哪些数据包。
只有root或具有sudo特权的用户才能运行tcpdump。 如果您尝试以非特权用户身份运行该命令,则会收到一条错误消息:“您无权在该设备上进行捕获”。
tcpdump: ens33: You don’t have permission to capture on that device
(socket: Operation not permitted)
最简单的用例是不带任何选项和过滤器的情况下调用tcpdump:
[linuxidc@linux:~/www.linuxidc.com]$ sudo tcpdump
输出如下:
[sudo] linuxidc 的密码:
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on ens33, link-type EN10MB (Ethernet), capture size 262144 bytes
tcpdump将继续捕获数据包并写入标准输出,直到接收到中断信号为止。 使用Ctrl + C组合键发送中断信号并停止命令。
要获得更详细的输出,请传递-v选项,或传递-vv以获得更详细的输出:
[linuxidc@linux:~/www.linuxidc.com]$ sudo tcpdump -vv
您可以使用-c选项指定要捕获的数据包数量。 例如,要仅捕获5个数据包,请输入:
[linuxidc@linux:~/www.linuxidc.com]$ sudo tcpdump -c 5
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on ens33, link-type EN10MB (Ethernet), capture size 262144 bytes
21:08:14.575216 IP linux.42082 > 180.101.49.12.https: Flags [.], ack 470550152, win 30016, length 0
21:08:14.577139 IP 180.101.49.12.https > linux.42082: Flags [.], ack 1, win 64240, length 0
21:08:14.578127 IP linux.37565 > _gateway.domain: 52885+ [1au] PTR? 12.49.101.180.in-addr.arpa. (55)
21:08:14.583548 IP _gateway.domain > linux.37565: 52885 NXDomain 0/1/1 (114)
21:08:14.585411 IP linux.37565 > _gateway.domain: 52885+ PTR? 12.49.101.180.in-addr.arpa. (44)
5 packets captured
14 packets received by filter
5 packets dropped by kernel
捕获数据包后,tcpdump将停止。
如果未指定任何接口,则tcpdump使用它找到的第一个接口并转储通过该接口的所有数据包。
使用-D选项可以打印tcpdump可以从中收集数据包的所有可用网络接口的列表:
[linuxidc@linux:~/www.linuxidc.com]$ sudo tcpdump -D
对于每个接口,该命令将打印接口名称,简短描述以及关联的索引(数字):
输出:
1.ens33 [Up, Running]
2.any (Pseudo-device that captures on all interfaces) [Up, Running]
3.lo [Up, Running, Loopback]
4.bluetooth0 (Bluetooth adapter number 0)
5.nflog (Linux netfilter log (NFLOG) interface)
6.nfqueue (Linux netfilter queue (NFQUEUE) interface)
7.usbmon1 (USB bus number 1)
8.usbmon2 (USB bus number 2)
上面的输出显示ens3是tcpdump找到的第一个接口,并且在没有为该命令提供接口时使用。 第二个接口any是一种特殊的设备,可让您捕获所有活动的接口。
要指定要在其上捕获流量的接口,请使用-i选项调用命令,后跟接口名称或关联的索引。 例如,要捕获来自所有接口的所有数据包,可以指定any接口:
[linuxidc@linux:~/www.linuxidc.com]$ sudo tcpdump -i any
默认情况下,tcpdump对IP地址执行反向DNS解析,并将端口号转换为名称。 使用-n选项禁用转换:
[linuxidc@linux:~/www.linuxidc.com]$ sudo tcpdump -n
跳过DNS查询可以避免生成DNS流量并使输出更具可读性。建议在调用tcpdump时使用此选项。
与在屏幕上显示输出不同,您可以使用重定向操作符>和>>将其重定向到一个文件:
[linuxidc@linux:~/www.linuxidc.com]$ sudo tcpdump -n -i any > linuxidc.txt
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
^C3470 packets captured
3616 packets received by filter
0 packets dropped by kernel
您还可以使用tee命令在保存到文件的同时查看数据:
[linuxidc@linux:~/www.linuxidc.com]$ sudo tcpdump -n -l | tee linuxidc.txt
上面命令中的-l选项告诉tcpdump缓冲输出行。 不使用此选项时,生成新行时,输出不会写在屏幕上。
了解tcpdump输出
tcpdump在新行上输出每个捕获的数据包的信息。 每行包括一个时间戳和有关该数据包的信息,具体取决于协议。
TCP协议行的典型格式如下:
1611760288 [Protocol] [Src IP].[Src Port] > [Dst IP].[Dst Port]: [Flags], [Seq], [Ack], [Win Size], [Options], [Data Length]
让我们逐个字段进行说明,并解释以下内容:
21:53:20.460144 IP 192.168.182.166.57494 > 35.222.85.5.80: Flags [P.], seq 1:88, ack 1, win 29200, options [nop,nop,TS val 1067794587 ecr 2600218930], length 87
- 21:53:20.460144 – 捕获的数据包的时间戳为本地时间,并使用以下格式:hours:minutes:seconds.frac,其中frac是自午夜以来的几分之一秒。
- IP – 分组协议。 在这种情况下,IP表示Internet协议版本4(IPv4)。
- 192.168.182.166.57494 – 源IP地址和端口,以点(.)分隔。
- 35.222.85.5.80 – 目的IP地址和端口,以点号(.)分隔。
TCP标志字段。 在此示例中,[P.]表示推送确认数据包,用于确认前一个数据包并发送数据。 其他典型标志字段值如下:
- [.] – ACK (Acknowledgment)
- [S] – SYN (Start Connection)
- [P] – PSH (Push Data)
- [F] – FIN (Finish Connection)
- [R] – RST (Reset Connection)
- [S.] – SYN-ACK (SynAcK Packet)
- seq 1:88 – 序列号在first:last表示法中。 它显示了数据包中包含的数据数量。 除了数据流中的第一个数据包(其中这些数字是绝对的)以外,所有后续数据包均用作相对字节位置。 在此示例中,数字为1:88,表示此数据包包含数据流的字节1至88。 使用-S选项可打印绝对序列号。
- ack 1 – 确认号(acknowledgment number)是此连接另一端所期望的下一个数据的序列号。
- win 29200 – 窗口号是接收缓冲区中可用字节的数目。
- options [nop,nop,TS val 1067794587 ecr 2600218930] – TCP选项。 使用nop或“ no operation”填充使TCP报头为4字节的倍数。 TS val是TCP时间戳,而ecr表示回显应答。 请访问IANA文档以获取有关TCP选项的更多信息。
- length 87 – 有效载荷数据的长度
tcpdump过滤器
在不使用过滤器的情况下调用tcpdump时,它将捕获所有流量并产生大量输出,这使得查找和分析目标数据包变得非常困难。
过滤器是tcpdump命令最强大的功能之一。 因为它们允许您仅捕获与表达式匹配的那些数据包。 例如,在对与Web服务器有关的问题进行故障排除时,可以使用过滤器仅获取HTTP通信。
tcpdump使用Berkeley数据包筛选器(BPF)语法使用各种加工参数(例如协议,源IP地址和目标IP地址以及端口等)过滤捕获的数据包。
在本文中,我们将介绍一些最常见的过滤器。 有关所有可用过滤器的列表,请查看pcap-filter联机帮助页。
按协议过滤
要将捕获限制为特定协议,请将该协议指定为过滤器。 例如,要仅捕获UDP流量,可以使用:
$sudo tcpdump -n udp
定义协议的另一种方法是使用原型限定符,后跟协议编号。 以下命令将过滤协议编号17,并产生与上述相同的结果:
$sudo tcpdump -n proto 17
有关编号的更多信息,请检查IP协议编号列表。
主机过滤
要仅捕获与特定主机有关的数据包,请使用主机限定符:
$sudo tcpdump -n host 192.168.1.185
主机可以是IP地址或名称。
您还可以使用网络限定符将输出过滤到给定的IP范围。 例如,要仅转储与10.10.0.0/16相关的数据包,可以使用:
$sudo tcpdump -n net 10.10
按端口过滤
若要仅将捕获限制为来自特定端口或特定端口的数据包��请使用端口限定符。 以下命令使用以下命令捕获与SSH(端口22)服务相关的数据包:
$sudo tcpdump -n port 23
portrange限定符使您能够捕获一系列端口中的流量:
$sudo tcpdump -n portrange 110-150
按来源和目的地过滤
您还可以使用are src,dst,src和dst以及src或dst限定符基于源或目标端口或主机筛选数据包。
以下命令捕获来自IP为192.168.1.185的主机的传入数据包:
$sudo tcpdump -n src host 192.168.1.185
要查找从任何来源到端口80的流量,请使用:
$sudo tcpdump -n dst port 80
复合过滤器
可以使用和(&&) 或者 (||), 而不是(!)运算符组合过滤器。
例如,要捕获来自源IP地址192.168.1.185的所有HTTP通信,可以使用以下命令:
$sudo tcpdump -n src 192.168.1.185 and tcp port 80
您还可以使用括号来分组和创建更复杂的过滤器:
$sudo tcpdump -n ‘host 192.168.1.185 and (tcp port 80 or tcp port 443)’
为避免在使用特殊字符时解析错误,请将过滤器括在单引号内。
这是另一个示例命令,用于从源IP地址192.168.1.185捕获除SSH以外的所有流量:
$sudo tcpdump -n src 192.168.1.185 and not dst port 22
检查数据包
默认情况下,tcpdump仅捕获数据包头。 但是,有时您可能需要检查数据包的内容。
tcpdump允许您以ASCII和十六进制格式打印数据包的内容。
-A选项告诉tcpdump以ASCII格式输出每个数据包,以十六进制格式-x输出每个数据包:
$sudo tcpdump -n -A
要以十六进制和ASCII码显示数据包的内容,请使用-X选项:
$sudo tcpdump -n -X
读取和写入捕获到文件
tcpdump的另一个有用功能是将数据包写入文件。 当您捕获大量数据包或要捕获数据包以供以后分析时,这非常方便。
要开始写入文件,请使用-w选项,后跟输出捕获文件:
$sudo tcpdump -n -w data.pcap
上面的命令将捕获的内容保存到名为data.pcap的文件中。 您可以根据需要命名文件,但是使用.pcap扩展名(数据包捕获)是一种常见的约定。
使用-w选项时,输出不会显示在屏幕上。 tcpdump写入原始数据包并创建一个二进制文件,而常规文本编辑器无法读取该文件。
要检查文件的内容,请使用-r选项调用tcpdump:
$sudo tcpdump -r data.pcap
如果要在后台运行tcpdump,请在命令末尾添加与号 (&)。
也可以使用其他数据包分析器工具(例如Wireshark)检查捕获文件。
长时间捕获数据包时,可以启用文件轮换。 tcpdump允许您创建的新文件或以指定的时间间隔或固定大小旋转转储文件。 以下命令将创建多达十个200MB文件,分别名为file.pcap0,file.pcap1,依此类推:在覆盖旧文件之前。
$sudo tcpdump -n -W 5 -C 200 -w /tmp/file.pcap
生成5个文件后,较旧的文件将被覆盖。
请注意,您仅应在排除故障期间运行tcpdump。
如果要在特定时间启动tcpdump,则可以使用cronjob。 tcpdump没有在指定时间后退出的选项。 您可以在一段时间后使用timeout命令停止tcpdump。 例如,要在1分钟后退出,您可以使用:
$sudo timeout 60 tcpdump -n -w data.pcap
总结
tcpdump是用于分析和解决网络相关问题的命令行工具。
本文向您介绍了tcpdump用法和语法的基础。 有关更深入的文档,请访问tcpdump网站。
如果您有任何疑问或反馈,请随时发表评论。
更多Linux命令相关信息见Linux命令大全 专题页面 https://www.linuxidc.com/topicnews.aspx?tid=16
本文永久更新链接地址:https://www.linuxidc.com/Linux/2020-02/162226.htm