网络问题排查到最后,十有八九要落到「抓个包看看」。tcpdump 是Linux 上抓包的第一工具,参数和表达式看着多,常用的就那一小撮。这篇是我的随手笔记,按「参数 → 表达式 → 菜谱」组织,用的时候直接抄。
前置
大多数发行版自带,没有就 apt install tcpdump / yum install tcpdump。抓包需要 root 或 CAP_NET_RAW 能力。
常用参数速查
| 参数 | 作用 |
|---|---|
-i eth0 / -i any | 指定网卡,any 抓所有(含 lo) |
-n | 不做 DNS 反解(快很多,基本必加) |
-nn | 连端口也不反解成服务名(显示 80 而不是 http) |
-c 100 | 抓够 100 个包就停,防止刷屏/打满磁盘 |
-w file.pcap | 写进文件,给 Wireshark 分析 |
-r file.pcap | 从文件读包(可再叠加过滤表达式) |
-A | 以 ASCII 打印包内容(看 HTTP 明文请求很直观) |
-X | 同时打印十六进制和 ASCII |
-s 0 | 抓完整包(默认有截断长度,看内容必加) |
-q | 精简输出,一行一个包 |
-G 60 -W 10 | 每 60 秒滚动写一个文件,最多保留 10 个(长期抓包用) |
过滤表达式
组合规则:and、or、not,加括号分组。
host 10.0.0.5 # 和这台机器有关的流量
src host 10.0.0.5 # 只看它发出的
port 80 # 端口
src port 53 and udp # 它发出的 DNS 查询
net 10.244.0.0/16 # 整个网段
portrange 8000-9000 # 端口范围
icmp # 只看 ICMP(ping)
tcp[tcpflags] & tcp-syn != 0 # 只看 SYN(新建连接)
tcp[tcpflags] & tcp-rst != 0 # 只看 RST(被拒/异常断开)
less 1500 and greater 1400 # 按包长过滤(排查 MTU 问题)
拿来即用的排查菜谱
「服务通不通」先看握手——只有 SYN 没有 ACK,多半是对面没监听或中间被丢:
tcpdump -i any -nn 'tcp[tcpflags] & (tcp-syn|tcp-ack) != 0 and port 8080'
抓 HTTP 请求明文看内容:
tcpdump -i any -nn -A -s 0 port 80
看 DNS 解析走向(K8s 里排查 CoreDNS 特别好用):
tcpdump -i any -nn port 53
「小包通、大包卡死」——MTU 黑洞排查:症状很典型——能 ping 通、能建连、小响应正常,一传大文件就卡死,跨隧道(WireGuard / IPsec / VXLAN)链路最常见。隧道把 MTU 吃小了,而路径上的 ICMP「需要分片」通知又被防火墙吞了,大包发出去就石沉大海。
先在发大文件的一侧看大包是不是在反复重传:
tcpdump -i eth0 -nn 'tcp and greater 1400' host <对端IP>
# 同样的序列号一遍遍出现 = 大包根本没被对面收到
再到隧道接口上看有没有人提醒我们降包长:
tcpdump -i tun0 -nn icmp
# 能看到 "ICMP unreachable - need to frag" = 通知在路上,只是被中间吞了
# 完全看不到 = 黑洞实锤
确认后给 TCP 连接钳制 MSS,让包长不越线即可解决:
iptables -t mangle -A POSTROUTING -p tcp --tcp-flags SYN,RST SYN -j TCPMSS --clamp-mss-to-pmtu
写文件回去用 Wireshark 细读:
tcpdump -i any -nn -s 0 -w /tmp/api.pcap host 10.0.0.5 and port 443 -c 1000
抓容器网卡的包:容器里没 tcpdump,从宿主机借——先 docker inspect 拿 PID 再 nsenter 进网络空间:
PID=$(docker inspect -f '{{.State.Pid}}' myapp)
nsenter -t $PID -n tcpdump -i eth0 -nn port 80
长期值守抓偶发问题(滚动文件 + 限量):
tcpdump -i eth0 -nn -s 0 -G 300 -W 20 -w /tmp/capture-%Y%m%d%H%M%S.pcap port 6379
几个坑
- 先看 dropped 计数:结束时 tcpdump 会打印
dropped by kernel数量,不为 0 说明抓的速率赶不上流量,加过滤表达式收窄或换-s减小快照长度 - 抓的位置决定看到什么:容器场景在宿主机
cni0、veth对、物理网卡上抓到的视角都不一样;跨节点流量在物理网卡上是封装后的包(flannel 是 UDP 4789),想看成色要选对位置 -A对 TLS 没用:443 上的内容全是密文,别浪费时间,最多看看 ClientHello 里的 SNI- 生产环境先估量:高流量网卡上裸跑
tcpdump -i any等于自杀,永远先加过滤条件和-c限量
小结
tcpdump 的心法就两条:一是用表达式把范围缩到最小,问题流量的特征越具体越好;二是拿不准就 -w 落盘,丢给 Wireshark 慢慢看比盯着滚屏强。再配合 nsenter 进容器网络空间,容器网络问题也基本通吃。