Tcpdump 抓包与网络排查指南
在日常的系统运维、容器排查和微服务调试中,网络问题(如连接超时、丢包、重传、协议错误)是最棘手的问题之一。tcpdump 是一款强大且经典的命令行网络抓包工具,它能够截获流经网卡的网络数据包,并支持极其丰富的过滤规则。
本文整理了 tcpdump 的核心参数、高频实战过滤表达式、容器环境下的抓包技巧,以及如何配合 Wireshark 进行深度分析。
1. 核心常用参数速查
在执行 tcpdump 命令时,合理搭配参数可以帮助我们快速、清晰地观察数据流,或者将数据保存到文件中。
| 参数 | 说明 | 建议与备注 |
|---|---|---|
-i <interface> | 指定监听的网卡接口(如 eth0, any) | any 表示监听所有网卡,但在某些系统上可能不支持混杂模式 |
-n | 不把 IP 地址解析为主机名 | 必带参数,避免 DNS 解析带来延迟和干扰 |
-nn | 不把端口号解析为服务名(如 80 不解析为 http) | 必带参数,直接显示数字端口 |
-c <count> | 抓取指定数量的数据包后自动退出 | 生产环境抓包时建议带上,防止刷屏或撑爆磁盘 |
-s <snaplen> | 设置抓取每个数据包的字节数 | -s 0 表示抓取完整的数据包(默认),排查应用层协议(如 HTTP/gRPC)时必须完整抓取 |
-v, -vv, -vvv | 输出更详细的报文协议信息 | 级别越高,输出的信息越详细(如 TTL、TOS、TCP 选项等) |
-X | 以 Hex(十六进制)和 ASCII 格式打印数据包内容 | 适合排查明文协议(如 HTTP, Redis, Memcached)的内容 |
-A | 仅以 ASCII 码格式打印数据包内容 | 适合快速查看 HTTP 请求体或响应体中的文本 |
-w <file.pcap> | 将抓取到的原始数据包写入 .pcap 文件 | 生产标准做法,保存后可下载到本地用 Wireshark 深度分析 |
-r <file.pcap> | 从保存的 .pcap 文件中读取并分析数据包 | 离线分析时使用 |
2. 高频实战过滤表达式
tcpdump 强大的核心在于其过滤表达式(Filter Expression)。通过合理组合限定词,我们可以从海量流量中精确筛选出目标报文。
基础过滤(按 IP、端口、协议)
# 1. 监听指定网卡上所有经过特定 IP 的流量(源或目的)
tcpdump -i eth0 -nn host 192.168.1.100
# 2. 监听特定源 IP 或目的 IP 的流量
tcpdump -i eth0 -nn src 192.168.1.100
tcpdump -i eth0 -nn dst 192.168.1.200
# 3. 监听特定端口的流量(TCP 或 UDP)
tcpdump -i eth0 -nn port 80
tcpdump -i eth0 -nn src port 8080
# 4. 监听特定网段的流量
tcpdump -i eth0 -nn net 10.244.0.0/16
# 5. 监听特定协议(tcp, udp, icmp, arp 等)
tcpdump -i eth0 -nn icmp
逻辑组合过滤(and, or, not)
通过逻辑运算符,可以构建非常复杂的过滤场景:
# 1. 抓取来自 192.168.1.100 且目的端口是 80 或 443 的 TCP 报文
tcpdump -i eth0 -nn 'tcp and src host 192.168.1.100 and (dst port 80 or dst port 443)'
# 2. 抓取网卡上除了 SSH (22) 之外的所有流量,防止抓包数据刷屏
tcpdump -i eth0 -nn 'not port 22'
# 3. 抓取主机 A 与主机 B 之间通信的所有非 ICMP 报文
tcpdump -i eth0 -nn 'host 192.168.1.10 and host 192.168.1.20 and not icmp'
3. 生产运维高频实战场景
场景一:排查 HTTP 明文请求与响应体
当怀疑微服务之间的 HTTP 调用参数有问题时,可以直接在终端打印 ASCII 内容:
# 抓取 8080 端口的 HTTP 流量,并以 ASCII 打印,限制抓取 100 个包
tcpdump -i eth0 -nn -A -s 0 port 8080 -c 100
场景二:排查 TCP 三次握手与连接重置(RST)
当客户端报 Connection reset by peer 或 Connection refused 时,我们需要观察 TCP 标志位(Flags):
# 抓取所有带有 RST 标志位的 TCP 报文(常用于排查连接被异常中断)
tcpdump -i any -nn 'tcp[tcpflags] & tcp-rst != 0'
# 抓取所有带有 SYN 或 FIN 标志位的报文(排查连接建立与释放)
tcpdump -i any -nn 'tcp[tcpflags] & (tcp-syn|tcp-fin) != 0'
场景三:排查 DNS 解析异常
当系统报错 Temporary failure in name resolution,怀疑 DNS 慢或解析失败:
# 监听 53 端口(DNS 默认端口)的 UDP 报文,查看解析请求与回复
tcpdump -i any -nn udp port 53
4. 容器与 Kubernetes 环境下的抓包技巧
在 Kubernetes (K8s) 或 Docker 容器环境中,由于容器内通常没有安装 tcpdump,且容器网络通过 Network Namespace 进行了隔离,直接在宿主机上执行 tcpdump -i eth0 往往抓不到容器内部的局部流量。
方法一:定位容器网卡,在宿主机抓包(Docker)
-
获取容器的 PID:
docker inspect --format '{{.State.Pid}}' <container_id_or_name># 假设输出为 12345 -
利用
nsenter进入容器的网络命名空间(推荐,最硬核且绿色的方式,无需在容器内安装任何工具):# 进入 PID 为 12345 的容器网络命名空间,并在其中执行宿主机的 tcpdumpnsenter -t 12345 -n tcpdump -i any -nn -w /tmp/container_traffic.pcap提示关于
nsenter的详细高级用法,请参考知识库中的 Nsenter 命名空间穿梭指南 文档。
方法二:使用 K8s 临时容器(Ephemeral Containers)抓包
在 Kubernetes 1.23+ 中,可以使用 kubectl debug 启动一个带有 tcpdump 的临时工具容器,并共享目标 Pod 的网络命名空间:
# 往目标 Pod 中注入一个包含 tcpdump 的 netshoot 镜像容器,并直接开始抓包
kubectl debug -it <pod_name> -n <namespace> --image=nicolaka/netshoot -- tcpdump -i any -nn -c 50
5. 配合 Wireshark 进行深度分析
虽然 tcpdump 可以在终端输出报文,但对于复杂的 TCP 粘包、乱序重传、SSL/TLS 握手排查,图形化工具 Wireshark 才是终极利器。
生产标准抓包与分析工作流
-
在服务器上抓包并保存为 pcap 文件(限制大小或数量,防止撑爆磁盘):
# 抓取 eth0 上 10000 个包,保存到 /tmp/target.pcaptcpdump -i eth0 -nn -s 0 -c 10000 -w /tmp/target.pcap -
将 pcap 文件下载到本地:
# 在本地终端执行 scp 下载scp user@server_ip:/tmp/target.pcap ./ -
使用 Wireshark 打开分析:
- Follow TCP Stream:在任意 TCP 包上右键,选择
Follow->TCP Stream,可以完整还原应用层的明文会话(如 Redis 命令、HTTP 报文)。 - 查看重传与丢包:在上方过滤器输入
tcp.analysis.flags,Wireshark 会自动高亮标出所有的重传包(Retransmission)、乱序包(Out-of-Order)和 ACK 丢失,帮您快速定位网络链路质量问题。
- Follow TCP Stream:在任意 TCP 包上右键,选择