跳到内容

12.2 抓包与协议分析:选择观测点,再解释数据

抓包能回答“这个观测点实际看到了什么包”,但不能自动告诉你全链路发生了什么。选错接口、抓在 NAT 前后不同位置,或忽略网卡卸载,都可能得到看似矛盾却各自真实的结果。

本课目标

  • 选择与故障假设匹配的抓包位置;
  • 区分 capture filter 与 Wireshark display filter;
  • 从 TCP 建连、重传、关闭和 TLS 握手中提取证据;
  • 识别 offload、namespace、代理和加密带来的观测边界;
  • 安全保存和分享 pcap。

先画观测点

一次请求可能经过:

text
client process
  -> client namespace / host
  -> NAT or proxy
  -> load balancer
  -> server host / container namespace
  -> server process

在客户端抓到 SYN 发出,只证明包到达客户端抓包点;在服务端抓不到,问题可能位于中间,也可能是抓错了接口或 namespace。最强的对照通常是同一时间窗内的双端抓包,再用五元组、TCP 序号和时间关联。

开始前记录:

  • UTC 时间与时钟同步状态;
  • 客户端和服务端地址、端口;
  • 容器、Pod、network namespace 与代理边界;
  • NAT 或负载均衡前后的地址变化;
  • 复现请求的 trace ID 或唯一请求头。

用 tcpdump 做有界采集

只在你拥有或明确获准诊断的系统与流量上抓包。先收窄接口、主机、端口、时长与文件大小:

bash
sudo tcpdump -i eth0 -nn -s 0 \
  'host 203.0.113.10 and tcp port 443' \
  -c 500 -w incident-443.pcap

参数含义:

  • -i eth0:明确观测接口;Linux 的 any 方便初筛,但链路层信息和行为可能不同于具体接口;
  • -nn:不做主机名和服务名解析,减少额外流量与歧义;
  • -s 0:按当前 tcpdump 语义抓取完整包;若涉及敏感数据,应改用足够诊断的较小 snaplen;
  • -c 500:到包数即停止;
  • -w:保存原始捕获,而不是解析后的文本。

长时间采集应轮转文件并限制数量:

bash
sudo tcpdump -i eth0 -nn -s 256 \
  'host 203.0.113.10 and tcp port 443' \
  -G 60 -W 5 -w 'incident-%Y%m%dT%H%M%S.pcap'

不同 tcpdump 版本对 -G-W 与文件名轮转的组合细节可能不同,正式值守前要在目标版本上演练。

两种过滤器不是一种语法

tcpdump 的 capture filter 通常使用 BPF 语法,在采集时决定哪些包进入文件:

text
host 203.0.113.10 and tcp port 443
tcp[tcpflags] & (tcp-syn|tcp-ack) != 0

Wireshark display filter 在包已经捕获后筛选显示,语法不同:

text
ip.addr == 203.0.113.10 && tcp.port == 443
tcp.flags.syn == 1
tcp.analysis.retransmission
tls.handshake.type == 1

把 display filter 粘进 tcpdump,或把 BPF 粘进 Wireshark 显示过滤框,都会失败或产生错误预期。

建连阶段:按包而不是按报错字符串判断

典型 TCP 建连:

text
client -> server  SYN
server -> client  SYN, ACK
client -> server  ACK

几类证据模式:

客户端抓包服务端抓包更接近的解释
SYN 重复发出,无响应看不到 SYN请求未到服务端观测点,或服务端抓错位置
SYN 重复发出,无响应看得到 SYN,无 SYN-ACK服务端路径、策略、资源或内核处理需继续检查
收到 RST可能看到 RST 发出主机或中间设备主动拒绝
收到 SYN-ACK,但客户端继续发 SYN服务端反复发 SYN-ACK客户端未接受响应,或最终 ACK 在路径中丢失

不要仅凭一次客户端抓包确定丢包发生的精确设备。双端证据能把范围缩到两个观测点之间,但仍未指出中间哪台设备负责。

重传与乱序:分析器提示是推断

Wireshark 的 tcp.analysis.retransmissionfast_retransmissionout_of_order 是依据当前捕获和分析状态生成的提示,不是发送端内核日志。抓包丢包、snaplen、分流、时间戳精度和观测点都可能影响判断。

判断重传时至少核对:

  • 五元组和方向;
  • TCP 序号区间与 ACK;
  • SACK block;
  • 相同 payload 是否再次出现;
  • 捕获文件自身是否丢包;
  • 两端是否都看到同一段。

在发送端抓包时,TSO/GSO 可能让捕获看到比线上 MTU 大的“包”;在接收端,GRO/LRO 可能合并多个段。校验和也可能在抓包发生后才由网卡填写,于是本机捕获显示 checksum incorrect,而线上包实际正确。需要判断线上帧形态时,在对端或中间 TAP 抓包,或在可控实验中临时检查 offload 设置;不要在生产环境未经评估就修改网卡特性。

TLS:能看到什么,不能看到什么

没有会话密钥时,TLS 1.2/1.3 的应用数据是加密的。抓包通常仍能观察到:

  • IP、端口、包长、方向和时序;
  • TCP 或 QUIC 的部分传输行为;
  • TLS ClientHello 中未被 ECH 保护的 SNI、ALPN 和 supported versions;
  • 服务端证书是否可见取决于 TLS 版本和握手阶段;TLS 1.3 在 ServerHello 后加密大部分握手消息。

因此,“Follow TCP Stream” 对 HTTPS 默认只会得到 TLS records,不会凭空还原 HTTP。

在受控测试环境中,可让支持的客户端通过 SSLKEYLOGFILE 导出会话秘密,再配置 Wireshark 解密。密钥日志等同于该会话的敏感解密材料,必须受限保存并及时销毁;并非所有运行时或客户端都支持这个环境变量。

对于 QUIC/HTTP/3,常规 TCP 分析不适用。优先结合客户端 key log、实现提供的 qlog、连接 ID、服务端日志和应用 trace。

NAT、代理与负载均衡

地址在链路上改变是正常现象:

  • 客户端出口 SNAT 会让服务端看到公网出口地址;
  • DNAT/负载均衡会把虚拟地址映射到后端地址;
  • 反向代理会终止客户端连接,再建立独立的上游连接;
  • PROXY protocol 或可信的转发头可传递原始地址,但必须由两端共同配置和验证。

所以“服务端看到的源 IP 不是用户 IP”不能直接推出 NAT 配置错误。先画出每一段连接的终点,并明确你观察的是哪一段。

一套可复用的抓包流程

  1. 写下待验证假设,例如“客户端 SYN 到了负载均衡,但没有到后端”。
  2. 选择能区分两种结果的观测点,统一时间。
  3. 用最小过滤器和短采集窗口复现一次。
  4. 保存原始 pcap、命令、工具版本与主机位置。
  5. 先看包是否存在,再看时序、序号与协议字段。
  6. 将抓包与连接表、防火墙计数器、负载均衡日志和应用 trace 对齐。
  7. 得出范围有限的结论,并明确尚未观测的区间。

数据安全

pcap 可能包含 Cookie、Authorization、查询参数、内部地址、DNS 名称和未加密业务数据。分享前应:

  • 在源头限制捕获范围和 snaplen;
  • 使用受控存储与最小权限;
  • 不直接用文本替换二进制 pcap 做“脱敏”;
  • 必要时用专门工具生成删减后的副本并验证;
  • 记录保留期限并删除临时密钥日志。

本课小结

抓包不是全知视角,而是一处传感器。先选择观测点,再解释协议;先确认原始包,再参考分析器提示。下一课会把这些工具组织成三个安全、可重复的本地实验。

规范与手册入口

  • tcpdump manual page 与 pcap-filter manual page;
  • Wireshark User's Guide:capture filters、display filters、TCP analysis;
  • RFC 9293(TCP)、RFC 8446(TLS 1.3)、RFC 9000(QUIC)。

Built with VitePress | Software Systems Atlas