Computer NetworkNotes

第 25 章:抓包分析

zjc 于 2026-01-25 发布

这是《计算机网络 零基础实战指南》的独立章节版。本章从概念、实操和生产排查三个视角展开,代码块保留了原书可直接运行的版本。 当日志、监控和链路追踪都无法解释“包到底有没有到、协议说了什么”时,抓包是最接近事实的证据。抓包能回答连接是否发起、握手卡在哪一步、谁发送了 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

含义:

  1. -s 128:每个包最多抓 128 字节;
  2. -c 10000:最多抓 10000 个包;
  3. -C 100:单文件约 100MB;
  4. -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

如果只看到 SS.,没有最后一个 ACK,客户端侧可能异常;如果只有 S 没有响应,则包未到达或被丢弃。

25.5 Wireshark 分析

常用功能:

  1. Statistics -> Summary;
  2. Statistics -> Conversations;
  3. Statistics -> IO Graph;
  4. Follow TCP Stream;
  5. Follow TLS Stream;
  6. Expert Information;
  7. Display Filter;
  8. 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

判断:

  1. 少量重传:偶发丢包,不一定影响业务;
  2. 集中重传:链路质量、拥塞、队列丢包;
  3. 一侧发送但无 ACK:回程路径或接收方异常;
  4. 握手阶段重传:建连被丢弃;
  5. TLS 后重传:网络质量或中间设备干扰;
  6. 同一连接大量重传:单路径问题。

进一步看:

mtr -rw -c 100 <target>
ss -i dst <target>
ethtool -S eth0

25.7 RST 分析

过滤:

tcp.flags.reset == 1

常见来源:

  1. 端口未监听;
  2. 服务崩溃;
  3. 应用主动 reset;
  4. 防火墙拒绝;
  5. LB 摘除后端;
  6. 连接队列溢出;
  7. 空闲超时;
  8. 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

关注:

  1. 查询是否发出;
  2. resolver 是否响应;
  3. 返回 A 还是 AAAA;
  4. TTL 是多少;
  5. 是否 CNAME 链;
  6. rcode 是否 NXDOMAIN / SERVFAIL;
  7. 响应耗时。

25.9 TLS 抓包

TLS 内容加密,但仍能看到:

  1. ClientHello;
  2. SNI;
  3. ALPN;
  4. TLS 版本和 Cipher Suites;
  5. 证书链长度;
  6. Alert 消息;
  7. 握手耗时。

过滤:

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 抓包注意事项

  1. 生产抓包先评估流量和磁盘;
  2. 只抓必要过滤条件;
  3. 使用滚动文件;
  4. 包文件可能包含敏感数据;
  5. 传输前脱敏或加密;
  6. 高流量机器优先在边缘或目标连接抓;
  7. 双端抓包更容易判断丢包方向;
  8. -i any 在不同系统上链路层表现不同;
  9. 容器网络要进入正确 namespace 或抓 veth;
  10. 记录抓包时间、机器、接口和过滤条件。

本章小结

tcpdump 用 BPF 精确采集包,Wireshark 用统计、专家信息、显示过滤和 Follow Stream 还原交互过程。抓包能定位握手卡点、RST 来源、重传、零窗口、DNS 响应、TLS Alert 和延迟层次。生产抓包必须控制范围、大小、留存和隐私。

思考题

  1. 为什么抓包时推荐 -nn
  2. SYN 只发不回说明什么?
  3. 如何用 Wireshark 找重传和零窗口?
  4. TLS 加密后还能看到哪些信息?
  5. 写一份生产授权抓包操作流程。