某本指南里有个数字,通常在六十到八十字节之间,是某人从 1500 里减掉、用来得到接口 MTU 的。那个数字描述的只是某一条路径上的某一种封装。换掉模式、外部地址族、加密算法,或者改变有没有 NAT,这套算术就不再适用于你的隧道。

这个数字来自另一条隧道

开销不是 IPsec 在抽象意义上的属性。它是真正被构造出来的那个数据包的属性:协商好的模式、外层头部、保护头部、填充、完整性字段,可能还有一层额外的 UDP 封装。

针对 IPv4、没有 NAT 的传输模式给出的数字,描述的包比 NAT 穿越下的 IPv6 隧道模式更小。两者在各自的场景里都没错。把其中任何一个照搬到另一种部署,就是人们最后拿到一个会弄坏大流量传输的 MTU 的原因。故障是安静的,因为小请求一直能正常工作。

把真正存在的各层加起来

从外层 IP 头部开始,向内侧推进。隧道模式下原始数据包在里面,所以外层头部是追加,而不是替换。 RFC 4303 描述的是 ESP 头部、填充以及紧随其后的完整性数据。

LayerWhat it addsWhen it applies
Outer IP header20 bytes for IPv4, 40 for IPv6Always, and 40 rather than 20 if the outer path is v6
ESP header8 bytes of SPI and sequence numberAlways
Block cipher IV8 to 16 bytes depending on the transformWhen the negotiated cipher uses one
Padding and trailerPadding to the block size, plus two trailer bytesAlways, and the amount varies with payload length
Integrity data12 to 16 bytes for common authenticated ciphersWhen integrity protection is negotiated
UDP encapsulation8 bytesNAT traversal on port 4500, which is common for clients behind NAT

这些行没有一行在各部署之间是恒定的,填充那一行甚至在同一次部署里都不恒定。一个公开的开销数字之所以让人失望,原因全在这里。

两个站点可能对同一条隧道有分歧

受保护的数据包仍然要穿过外层路径,而外层路径并非处处相同。PPPoE 接入线路承载的比干净的 Ethernet 段更少。移动网络可能进一步收缩,而把自己流量再隧道化的运营商又会加上一层没人提过的封装。一条链路能通、另一条链路失败的隧道,描述的是第二条链路,而不是协议。

两个方向也可能不同。非对称路由可能给你一个能用的上传和一个卡住的下载,这看起来像应用问题,直到你去看数据包大小而不是可达性。小 ping 能通,对满尺寸的回应几乎没有证明力。

去测量,而不是去减

找出能穿过这条路径的最大数据报。然后把它和接口报告的值比较:

ip link show eth0 | grep -o 'mtu [0-9]*'
ip xfrm state list
ping -M do -s 1400 198.51.100.7
ping -M do -s 1372 198.51.100.7
tcpdump -ni any -c 20 'esp or udp port 4500'

把 ping 尺寸降下来,直到有回应,并把能用的最大值当作这条路径的预算。xfrm 的输出会告诉你协商了什么模式和什么算法,那才是任何诚实计算的输入。抓包能确认线上是 ESP 还是被 UDP 包住的 ESP,这就把 NAT 的问题定了下来,不用猜。

也给控制平面留一个值。IKE 握手包的结构和数据包不同,所以从握手抓包里推出来的尺寸不是数据平面的 MTU。

把数字放在它该在的地方

对于穿过隧道的 TCP,限制 MSS 往往是最小侵入的控制手段,因为它减少端点发送的量,而不改变隧道本身。对于基于路由的隧道,要有意设置隧道接口的 MTU,并记录原因。两件事一起做然后测量,你无法知道是哪一件起了作用。

把协商好的模式、外层地址族、NAT 情况和可复现的症状一起留在工单里。一组记录下来的四条事实胜过记住的一个常数,而且只有这种形式能扛过下一次客户端升级。

相关文章