tcpdump 是 Linux 下最经典、最轻量的网络抓包工具。它不需要图形界面,直接输出数据包的头部信息和简要内容到终端,适合快速排查网络问题、分析协议交互过程。掌握它,无论在笔记本、服务器还是嵌入式设备上都能第一时间诊断网络异常。
1. 基本用法
最简单的抓包命令是让 tcpdump 监听某个网络接口:
sudo tcpdump -i eth0
它会不断输出所有经过 eth0 的数据包摘要。以下是一些常用选项:
-i any:监听所有接口。-n:不将 IP 地址反向解析为主机名,不将端口号转为服务名,可以避免 DNS 查询带来的延迟和干扰。-nn:同时禁用主机名和服务名解析,输出纯数字地址和端口,最为常用。-c N:捕获 N 个包后自动退出。-v、-vv、-vvv:输出更详细的信息(协议字段、TTL 等)。-w file.pcap:将捕获的数据包存入文件,便于后续用 Wireshark 等工具分析。-r file.pcap:从文件中读取包,而不是实时抓取。-s snaplen:设置抓取的数据包快照长度,-s 0表示完整抓取整个包,默认通常只抓前 96 字节,建议在需要完整载荷时手动加上。
日常排错中,最常用的基础命令形式是:
sudo tcpdump -i eth0 -nn
2. 读取输出信息
tcpdump 的每一行输出代表一个数据包,格式大致如下:
时间戳 协议 源地址.端口 > 目的地址.端口: 标志位 序列号/确认号 窗口大小 其他选项
例如:
14:32:10.123456 IP 192.168.1.10.54321 > 93.184.216.34.80: Flags [S], seq 123456789, win 64240, options [mss 1460], length 0
14:32:10.123456是精确到微秒的时间戳。IP表示使用 IP 协议。192.168.1.10.54321 > 93.184.216.34.80表示从本地端口 54321 发往远程 80 端口。Flags [S]表示这是一个 SYN 包(TCP 连接请求)。seq、win、options等是 TCP 具体信息。
关注 Flag 字段:
[S]:SYN(发起连接)[S.]:SYN-ACK(响应连接请求)[.]:ACK(确认)[F]:FIN(结束连接)[R]:RST(重置连接)[P.]:PSH+ACK(数据推送)
通过这些标识可以快速判断 TCP 握手是否正常,连接是否被拒绝。
3. 过滤规则
在繁忙的网络接口上不加过滤地抓包会瞬间淹没终端,tcpdump 使用 BPF(Berkeley Packet Filter)语法 进行精准过滤。过滤器放在命令行的最后,支持多层条件组合。
3.1 按主机过滤
tcpdump host 192.168.1.100 # 所有收发到这个 IP 的包
tcpdump src host 192.168.1.100 # 源地址是该 IP
tcpdump dst host 192.168.1.100 # 目的地址是该 IP
3.2 按端口过滤
tcpdump port 80 # 源或目的端口是80
tcpdump src port 54321 # 源端口是54321
tcpdump dst port 443 # 目的端口是443
tcpdump portrange 8000-8100 # 端口范围
3.3 按协议过滤
tcpdump tcp # 只看TCP包
tcpdump udp # 只看UDP包
tcpdump icmp # 只看ICMP包(如 ping)
tcpdump arp # 只看ARP包
tcpdump ip6 # 只看IPv6包
3.4 组合过滤
使用 and、or、not 以及括号组合条件。括号在 Shell 中有特殊含义,需用引号保护或转义:
# 只看从192.168.1.10发往80端口的TCP包
tcpdump src host 192.168.1.10 and tcp dst port 80
# 只看来自192.168.1.20的非SSH(22端口)流量
tcpdump host 192.168.1.20 and not port 22
# 组合复杂条件:ICMP或目的端口为53的UDP(DNS)
tcpdump 'icmp or (udp and dst port 53)'
3.5 按特征过滤(高级)
# 看SYN包(TCP flags中SYN=1且ACK=0):tcp[tcpflags] & (tcp-syn) != 0
tcpdump 'tcp[tcpflags] & (tcp-syn) != 0 and tcp[tcpflags] & (tcp-ack) == 0'
# 抓取包含特定字节的数据包(偏移量 0 处为 GET )
tcpdump 'tcp and (tcp[((tcp[12:1] & 0xf0) >> 2):4] = 0x47455420)'
这类过滤已经深入到包载荷,实际工作中更推荐先用 -w 保存再用 Wireshark 分析,但当环境只有命令行时,它极为强大。
4. 实用场景示例
排障 TCP 握手
单独监听与某主机的 TCP 三次握手:
sudo tcpdump -i eth0 -nn 'host 10.10.10.1 and tcp[tcpflags] & (tcp-syn) != 0'
你能清楚看到哪个方向没有回应 SYN-ACK,立即判断是网络不通还是服务未监听。
抓取 DNS 查询
sudo tcpdump -i any -nn port 53
输出中能看到完整的 DNS 请求和响应,快速定位域名解析故障。
实时抓取 HTTP 请求头
sudo tcpdump -A -s 0 'tcp port 80 and (((ip[2:2] - ((ip[0]&0xf)<<2)) - ((tcp[12]&0xf0)>>2)) != 0)'
-A 以 ASCII 显示包内容,-s 0 抓获完整数据,通过复杂过滤器找有数据载荷的包。更简洁的做法是先用 -w 保存再用 strings 命令:
sudo tcpdump -i eth0 -w http.pcap tcp port 80
strings http.pcap | grep -E '^(GET|POST|Host:)'
5. 注意事项
- 抓包通常需要 root 权限(或
CAP_NET_RAW)。 - 在生产服务器上抓包要注意磁盘空间和 CPU 占用,务必配合过滤器和
-c限制数量,或使用-W(文件轮转)等选项。 - 明文抓取可能泄露敏感信息,连接加密协议(HTTPS、SSH)时只能看到密文,这是正常现象。
- 对 VLAN 或隧道环境,可能需要指定接口或使用
-e显示链路层头部。
tcpdump 的过滤语法初看起来有些晦涩,但掌握最常用的主机、端口、协议三件套,就已经能解决八成的网络诊断场景。它带来的价值在于:没有任何黑盒,任何一点网络异常都能被精确捕获并还原。