tcpdump —— 网络问题的最终证据
tcpdump —— 网络问题的最终证据
分类:02 进程与网络诊断 适用:Linux(libpcap),2.4/4.99 之后语法基本稳定 一句话:应用说没收到、网络说发了,只有抓包能判案。
1. 它解决什么问题
- 请求到底有没有到达这台机器?
- TCP 三次握手有没有完成?谁先 RST?
- 是不是真的丢包、重传、乱序?
- HTTP 请求/响应内容对不对(明文协议)。
2. 安装与权限
apt install -y tcpdump
dnf install -y tcpdump
# 普通用户抓包(避免全程 root)
setcap cap_net_raw,cap_net_admin=eip /usr/sbin/tcpdump
# 或
groupadd pcap && usermod -aG pcap $USER
容器内抓包需要 NET_RAW + NET_ADMIN,或直接在宿主机抓 veth。
3. 最常用的六条命令
tcpdump -i any -nn -c 100 # 任意网卡,100 个包,不解析
tcpdump -i eth0 -nn port 80 # 80 端口
tcpdump -i eth0 -nn host 10.0.0.5 # 某 IP 的所有流量
tcpdump -i eth0 -nn -w /tmp/cap.pcap # 写文件,后续用 Wireshark 分析
tcpdump -r /tmp/cap.pcap -nn -A # 读文件,按 ASCII 显示
tcpdump -i eth0 -nn -s0 -A port 80 # 抓完整包并直接看内容
4. 参数详解
| 参数 | 作用 | 说明 |
|---|---|---|
-i <if> |
指定网卡 | any 抓所有(但链路层信息缺失) |
-nn |
不解析主机名和端口名 | 必加,否则 DNS 反查拖慢 |
-c <n> |
抓 n 个包后退出 | 控制量 |
-s <n> |
抓取长度(snaplen) | -s0 抓完整包,旧默认 96 字节会截断 |
-w <file> |
写 pcap | 排障首选,先存后析 |
-r <file> |
读 pcap | |
-A |
以 ASCII 显示载荷 | 看 HTTP 明文 |
-X |
十六进制 + ASCII | 看二进制协议 |
-e |
显示链路层头(MAC) | 排查 ARP/二层问题 |
-v/-vv/-vvv |
详细程度 | -vv 看 TTL、窗口、校验和 |
-l |
行缓冲 | 配合管道 ` |
-Q in/out |
只抓进/出方向 | 区分请求与响应 |
-Z <user> |
抓完降权到指定用户 | 安全加固 |
-B <kb> |
内核缓冲大小 | 高流量防丢包 |
-G <s> -C <MB> -W <n> |
按时间/大小轮转 | 长时间抓包 |
-D |
列出可用网卡 | |
-p |
非混杂模式 | 只抓本机流量 |
5. 过滤器语法(BPF)
这是 tcpdump 的核心。表达式写在最后,建议用单引号包住。
基础
host 10.0.0.5 # 源或目的
src host 10.0.0.5 # 仅源
dst host 10.0.0.5 # 仅目的
net 10.0.0.0/24 # 网段
port 80 # 源或目的端口
src port 8080
dst port 443
portrange 8000-9000
组合
# 与、或、非
host 10.0.0.5 and port 3306
host 10.0.0.5 and not port 22
'( port 80 or port 443 ) and host 10.0.0.5'
括号必须转义或用引号包住,否则被 shell 解释。
协议与标志位
tcp # 所有 TCP
udp
icmp
arp
ip proto 6 # 协议号
tcp[tcpflags] & tcp-syn != 0 # 只看 SYN
tcp[tcpflags] & (tcp-syn|tcp-ack) == (tcp-syn|tcp-ack) # SYN+ACK
tcp[tcpflags] & tcp-rst != 0 # 只看 RST
tcp[13] & 2 != 0 # 等价写法(13 是 flags 偏移)
ip[8] < 64 # TTL < 64(判断是否经过路由)
按包长过滤
greater 1000 # 大于 1000 字节
less 100 # 小于 100 字节
6. 输出怎么读
14:32:01.123456 IP 10.0.0.5.51234 > 10.0.0.9.80: Flags [S], seq 123456789, win 29200, options [mss 1460,sackOK,TS val 123 ecr 0,nop,wscale 7], length 0
14:32:01.123987 IP 10.0.0.9.80 > 10.0.0.5.51234: Flags [S.], seq 987654321, ack 123456790, win 28960, options [mss 1460,sackOK,TS val 456 ecr 123,nop,wscale 7], length 0
14:32:01.124123 IP 10.0.0.5.51234 > 10.0.0.9.80: Flags [.], ack 1, win 229, length 0
| 标志 | 含义 |
|---|---|
[S] |
SYN |
[S.] |
SYN+ACK |
[.] |
ACK |
[P.] |
PSH+ACK(有数据) |
[F.] |
FIN+ACK |
[R] |
RST |
[R.] |
RST+ACK |
length 0表示无载荷(握手包)。- 只看握手三条就能判断连接是否建立:有
S无S.→ 服务端没回(防火墙 drop 或没监听)。
7. 实战场景
7.1 判断请求是否到达本机
# 本机(服务端)抓
tcpdump -i any -nn -c 20 'tcp port 8080 and host 10.0.0.5'
- 完全无包 → 没到这台机器:查 DNS、路由、安全组、SLB。
- 有 SYN 无 SYN+ACK → 本机没监听或被本机防火墙 drop。
- 有 SYN 立即 RST → 端口未监听(RST 是内核回的)。
- 三次握手完成但无后续 → 应用层没处理。
7.2 抓 RST 是谁发的
tcpdump -i any -nn 'tcp[tcpflags] & tcp-rst != 0' -c 20
看 RST 的方向:从服务端发出 → 服务端主动拒绝(连接队列满、keepalive 超时、应用崩溃);从客户端发出 → 客户端放弃。
7.3 看 HTTP 请求内容
tcpdump -i eth0 -nn -s0 -A 'tcp port 80 and host 10.0.0.5' | grep -E '^(GET|POST|HTTP|Host:|Cookie:)'
HTTPS 只能看到 SNI 和证书(除非有私钥解密):
tcpdump -i eth0 -nn -s0 -A 'tcp port 443' | grep -i 'host:'
7.4 长时间抓包(轮转,防爆盘)
tcpdump -i eth0 -nn -s0 -w /data/cap/$(hostname)-%Y%m%d-%H%M.pcap \
-G 600 -Z root 'port 8080' &
# 每 600 秒切一个新文件,%Y%m%d 由 -G 触发时按 strftime 展开
配合清理:
find /data/cap -name '*.pcap' -mtime +2 -delete
7.5 定位丢包与重传
tcpdump -i eth0 -nn -vv 'host 10.0.0.5 and tcp' -c 200 > /tmp/tcp.txt
grep -c 'retrans' /tmp/tcp.txt # 粗略看重传提示(需 -vv 且较新版本)
精确分析建议存 pcap 后用 Wireshark 的 tcp.analysis.retransmission 过滤。
7.6 抓特定网段排除干扰
tcpdump -i eth0 -nn 'net 10.0.0.0/24 and not port 22 and not port 53' -c 500
8. 常见坑
packets dropped by kernel:抓包速率超过内核缓冲,加大-B 40960或缩小过滤范围。丢包时结论就不可信了。-i any抓不到链路层:any是伪设备,-e的 MAC 信息缺失,二层问题必须指定真实网卡。- 默认 snaplen 会截断:老版本默认 96 字节,看 HTTP body 必须
-s0。 - 不加
-nn极慢:每个包都做反向 DNS,高流量时直接卡死。 - 只抓到一个方向:交换机/网卡 offload 导致,或路由不对称。需要双向时在两台机器分别抓。
- 容器内
-i any只看到容器网卡:要抓宿主机侧 veth,或nsenter -t <pid> -n。 - 生产抓包有性能和安全风险:限制
-c、过滤条件、时长;pcap 里可能含明文密码,注意脱敏与留存合规。 tcp port 80不含 HTTP/2、gRPC over 其他端口,按实际端口抓。- TLS 1.3 抓不到证书明文(除 SNI),别指望从包里看域名以外的东西。
-w时不要再加-A/-X:会污染 pcap 文件,读不出来。
9. 配套:tshark
# 统计 HTTP 状态码
tshark -r cap.pcap -Y 'http.response' -T fields -e http.response.code | sort | uniq -c
# 找重传
tshark -r cap.pcap -Y 'tcp.analysis.retransmission' | head
# 提取 SNI
tshark -r cap.pcap -Y 'tls.handshake.extensions_server_name' \
-T fields -e tls.handshake.extensions_server_name | sort -u
10. 速查表
tcpdump -i any -nn -c 100
tcpdump -i eth0 -nn port 80
tcpdump -i eth0 -nn host 10.0.0.5 and port 3306
tcpdump -i eth0 -nn -s0 -w /tmp/cap.pcap
tcpdump -r /tmp/cap.pcap -nn -A
tcpdump -i eth0 -nn 'tcp[tcpflags] & tcp-rst != 0'
tcpdump -i eth0 -nn 'tcp[tcpflags] & tcp-syn != 0 and host 10.0.0.5'
tcpdump -i eth0 -nn -Q in port 8080
tcpdump -i eth0 -nn -B 40960 -s0 -w /data/cap.pcap 'port 8080'
tcpdump -D # 列出网卡