这是《计算机网络 零基础实战指南》的独立章节版。本章从概念、实操和生产排查三个视角展开,代码块保留了原书可直接运行的版本。 当日志、监控和链路追踪都无法解释“包到底有没有到、协议说了什么”时,抓包是最接近事实的证据。抓包能回答连接是否发起、握手卡在哪一步、谁发送了 RST、是否存在重传、窗口是否为零、DNS 返回了什么、TLS 证书是否匹配。
25.1 抓包准备
先明确四件事:
1. 在哪一端抓:客户端、服务端、LB、中间节点
2. 抓哪个接口:eth0、any、VPN、容器 veth
3. 过滤什么:IP、端口、协议、方向
4. 输出到哪里:文件、滚动文件、实时管道
基础命令:
tcpdump -D
ip link
tcpdump -i eth0 -nn host 10.20.1.10
tcpdump -i any -nn port 443
建议始终使用 -nn,避免 IP 和端口反向解析拖慢抓包。
25.2 常用 BPF 过滤
# IP
tcpdump -i eth0 -nn host 10.20.1.10
tcpdump -i eth0 -nn src 10.20.1.10
tcpdump -i eth0 -nn dst 10.20.1.10
tcpdump -i eth0 -nn net 10.20.0.0/16
# 端口
tcpdump -i eth0 -nn port 8080
tcpdump -i eth0 -nn src port 443
tcpdump -i eth0 -nn dst port 53
# 协议
tcpdump -i eth0 -nn icmp
tcpdump -i eth0 -nn udp port 53
tcpdump -i eth0 -nn arp
# TCP 标志
tcpdump -i eth0 -nn 'tcp[tcpflags] & tcp-syn != 0'
tcpdump -i eth0 -nn 'tcp[tcpflags] & tcp-rst != 0'
tcpdump -i eth0 -nn 'tcp[tcpflags] & tcp-fin != 0'
组合:
tcpdump -i eth0 -nn host 10.20.1.10 and port 443
tcpdump -i eth0 -nn host 10.20.1.10 and not port 22
25.3 输出文件
tcpdump -i eth0 -nn port 443 -w /tmp/debug.pcap
tcpdump -r /tmp/debug.pcap -nn
限制包大小和数量:
tcpdump -i eth0 -nn port 443 -s 128 -c 10000 -w debug.pcap
滚动抓包:
mkdir -p /var/log/tcpdump
tcpdump -i eth0 -nn port 443 \
-C 100 -W 10 -w /var/log/tcpdump/debug.pcap
含义:
-s 128:每个包最多抓 128 字节;-c 10000:最多抓 10000 个包;-C 100:单文件约 100MB;-W 10:最多保留 10 个滚动文件。
25.4 tcpdump 输出解读
TCP 握手:
10.0.1.10.50000 > 10.20.1.10.443: Flags [S]
10.20.1.10.443 > 10.0.1.10.50000: Flags [S.]
10.0.1.10.50000 > 10.20.1.10.443: Flags [.]
含义:
| 标志 | 含义 |
|---|---|
| S | SYN |
| S. | SYN + ACK |
| . | ACK |
| P | PSH |
| F | FIN |
| R | RST |
如果只看到 S 和 S.,没有最后一个 ACK,客户端侧可能异常;如果只有 S 没有响应,则包未到达或被丢弃。
25.5 Wireshark 分析
常用功能:
- Statistics -> Summary;
- Statistics -> Conversations;
- Statistics -> IO Graph;
- Follow TCP Stream;
- Follow TLS Stream;
- Expert Information;
- Display Filter;
- Protocol Hierarchy。
常用显示过滤:
ip.addr == 10.20.1.10
tcp.port == 443
tcp.flags.reset == 1
tcp.analysis.retransmission
tcp.analysis.zero_window
tcp.analysis.duplicate_ack
dns.qry.name == "www.example.com"
tls.handshake.type == 1
http.response.code >= 500
推荐排障顺序:
1. Summary 看时间范围、包数、丢包
2. Conversations 找异常地址和流量
3. IO Graph 看时间和速率
4. Expert Information 看重传、零窗口、异常
5. Follow Stream 看完整交互
25.6 重传分析
过滤:
tcp.analysis.retransmission
tcp.analysis.fast_retransmission
tcp.analysis.duplicate_ack
判断:
- 少量重传:偶发丢包,不一定影响业务;
- 集中重传:链路质量、拥塞、队列丢包;
- 一侧发送但无 ACK:回程路径或接收方异常;
- 握手阶段重传:建连被丢弃;
- TLS 后重传:网络质量或中间设备干扰;
- 同一连接大量重传:单路径问题。
进一步看:
mtr -rw -c 100 <target>
ss -i dst <target>
ethtool -S eth0
25.7 RST 分析
过滤:
tcp.flags.reset == 1
常见来源:
- 端口未监听;
- 服务崩溃;
- 应用主动 reset;
- 防火墙拒绝;
- LB 摘除后端;
- 连接队列溢出;
- 空闲超时;
- keepalive 失败。
抓包特征:
客户端发 SYN
服务端直接回 RST
通常优先查端口监听和安全策略。
连接正常建立
一段时间后服务端回 RST
优先查服务异常、超时策略和连接关闭逻辑。
25.8 DNS 抓包
tcpdump -i eth0 -nn udp port 53 -w dns.pcap
Wireshark 过滤:
dns.qry.name contains "example"
dns.flags.response == 1
dns.flags.rcode != 0
关注:
- 查询是否发出;
- resolver 是否响应;
- 返回 A 还是 AAAA;
- TTL 是多少;
- 是否 CNAME 链;
- rcode 是否 NXDOMAIN / SERVFAIL;
- 响应耗时。
25.9 TLS 抓包
TLS 内容加密,但仍能看到:
- ClientHello;
- SNI;
- ALPN;
- TLS 版本和 Cipher Suites;
- 证书链长度;
- Alert 消息;
- 握手耗时。
过滤:
tls.handshake.type == 1
tls.record.content_type == 21
常见 Alert:
| Alert | 含义 |
|---|---|
| certificate_expired | 证书过期 |
| bad_certificate | 证书无效 |
| unknown_ca | CA 不受信任 |
| handshake_failure | 算法或 SNI 不匹配 |
| protocol_version | 版本不兼容 |
如需解密应用数据,客户端可导出 TLS Key Log,但必须在授权和隐私允许时操作。
25.10 抓包注意事项
- 生产抓包先评估流量和磁盘;
- 只抓必要过滤条件;
- 使用滚动文件;
- 包文件可能包含敏感数据;
- 传输前脱敏或加密;
- 高流量机器优先在边缘或目标连接抓;
- 双端抓包更容易判断丢包方向;
-i any在不同系统上链路层表现不同;- 容器网络要进入正确 namespace 或抓 veth;
- 记录抓包时间、机器、接口和过滤条件。
本章小结
tcpdump 用 BPF 精确采集包,Wireshark 用统计、专家信息、显示过滤和 Follow Stream 还原交互过程。抓包能定位握手卡点、RST 来源、重传、零窗口、DNS 响应、TLS Alert 和延迟层次。生产抓包必须控制范围、大小、留存和隐私。
思考题
- 为什么抓包时推荐
-nn? - SYN 只发不回说明什么?
- 如何用 Wireshark 找重传和零窗口?
- TLS 加密后还能看到哪些信息?
- 写一份生产授权抓包操作流程。