你在隧道接口上抓到 1400 字节的报文,再到物理接口抓一次,数字却怎么也对不上。地址不同,长度不同,第二个文件看起来像另一段会话。其实并没有哪里坏掉。两个不同的报文恰好处在两个不同的层上,而它们之间的差距正是隧道对你的流量所做的事。先读完这两个视角,再去责怪 MTU。

两个观察点,以及各自呈现的报文

在隧道接口上抓到的包呈现的是内层报文:应用负载带着它原始的源和目的,尚未套上任何保护。在物理接口上抓到的包呈现的是外层报文:一个 IP 首部、一个传输层首部、封装本身,然后是被加密的内层报文充当负载。同一段会话,不同的对象。一旦你说清文件里装的是哪一个,这种错位就不再神秘。

长度的差异来自开销,地址的差异来自设计。反过来看,混乱就变得可以预料:人们把 1400 字节的内层报文和 1450 字节的外层报文放在一起比较,断定出了问题,然后开始去改那些从头到尾都没出错的 MTU 设置。给文件标上接口和层次,因为那正是读者最先需要、也是人们最常漏掉的一条信息。

抓包之前先确定层次

在写下第一个报文之前,先决定哪个层能回答你的问题。关于 MTU 的问题通常需要外层视角,因为首部在那里累积,链路的限制也在那里显现。关于应用的问题通常需要内层视角,因为你在意的负载在那里仍然存在。没有计划地两头都抓,只会得到两个文件和一个结论都没有。

用一个无害且获准的测试,并按你在意的源、目的和时间过滤。抓包前先读工具的接口与过滤选项,因为元数据通常已经够用,而且比负载好分享得多。默认把内层抓包当作敏感材料,因为它包含尚未加密的应用数据,只有在路径更远处才会受到保护。

长度差异里究竟装了什么

外层报文携带额外的首部和保护材料,携带多少取决于协议及其选项。路径上的分片、聚合或重排会破坏内层报文与承载它的外层报文之间表面的一一对应,所以逐包比长度并非总能做到。若怀疑是 MTU 故障,去找长度反馈和流量停住的位置,再与应用报告的情况对照。没有回应的重传模式,与携带下一跳长度的 ICMP 差错,是两种不同的信号。

一个报文离开了主机,并不能证明对端收到了它。如果你的抓包止于自己的接口,你只证明了内核发出了东西,这是关于这条路径最弱的证据。把抓包与可复现的症状组合起来:同一目的、同一操作、同一长度,跑两次,只改一个变量。

把 offload 读进这些数字里

主机侧的分段与其他 offload 会带来第二种失真,正是它让本地抓包与线上实况不一致。本地抓包可能显示适配器随后才拆分的缓冲区,所以链路上的帧比文件所显示的更小、更多。这就是为什么抓包文件里出现一个大缓冲区,并不能证明一个超大帧穿过了每一段链路。如果长度对你的结论很重要,就记录抓包点在哪里,以及那个接口上 offload 是否开启。

否则你测的是主机的便利,而不是路径的行为。两个分别标明接口与 offload 状态的文件,能在一分钟内了结这类争论中的大部分。

抓包在哪里不再是证据

看到加密的外层报文,说明在这些测试条件下存在一道保护边界,它对于设备上的其他应用、运营商的处理方式或端点自身的状态都什么也没说。在隧道内部看到明文,也不意味着隧道坏了;它意味着你是在加密点之上抓的包,而那是一个合理的观察位置。抓包是关于某个位置的证据,不是关于某个系统的判决,工单应当照这个口径写。把范围那句话留在报告里,因为正是它阻止一次观察变成一句审计断言。

给每个文件标上接口、过滤条件和时间戳,并在调查结束后删除它。tcpdump 手册记录了这里用到的接口与过滤参数,包括那些能让抓包保持小巧的参数。

如果必须共享证据,就共享长度、时间戳和参数,而不是负载。问题本来就是报文长度,答案很少需要任何人的数据。

相关文章