只要 WireGuard 表现异常就下调 MTU,这个习惯会掩盖另一种故障。不转发报文的网关和承载不了大包的通路,会给出可以区分的形态:前者两个方向、任何大小都失败,后者小请求能过、大请求必死。在改动任何数字之前,先确认你面对的是哪一种。测试很便宜,却能排除一半可能的原因。

两种故障,两种形态

转发问题会在服务器之后立刻显现。握手成功,隧道地址有响应,而网关之后即使发一个小请求也完全不通。包到了服务器却没被转出去,或者回程根本没有路由。

大小问题只在超过某个阈值后出现。DNS、TCP 握手和很小的 API 调用都正常,而文件下载或大响应会挂住。能放下的包端到端走通了,放不下的包在某处被丢弃,却没有任何可用的报告。

这些描述指向不同的人、不同的配置文件,所以先测量形态比猜测更有价值。只 ping 一下网关无法把两者分开。

在缩小任何数值之前,先排除转发

要测试网关之外的目的地,而不是网关本身。ping 服务器的隧道地址只能证明接口是通的、能到达终结隧道的那台机器。更广网络的流量,取决于那台机器是否开启 IP 转发,以及防火墙是否放行被转发的流。两者都必须成立,任何一项不成立,结果都是同样的沉默。

回程路由同样重要。如果目的网络不知道如何到达客户端的隧道地址,请求会到达而响应会消失,客户端报告的超时看起来和转发被丢弃一模一样。

在设计使用地址转换的地方,转换规则就是那条回程的一部分。追查 MTU 问题时把规则删掉,会把本来能用的设计变成坏掉的设计,所以改动之前先读现有规则。

测量断裂从哪里开始

先读取转发状态和过滤规则。这些都是只读检查,回答的是那个便宜的问题:

sysctl net.ipv4.ip_forward
sudo iptables -S FORWARD
ip route get 10.30.0.9

然后用不分片位,从客户端向网关之外的主机探测大小:

ping -M do -s 1200 10.30.0.9
ping -M do -s 1400 10.30.0.9

如果第一个探测通过、第二个因分片错误失败,通路就是在告诉你它可用的大小。如果两个都不通,你面对的是转发或路由,而 MTU 并不是该改的变量。

ObservationPoints towardWhere to look
Nothing beyond the gateway worksForwarding or return routeForwarding flag, filter rules, routing table
Small works, large stallsPacket size on the pathTunnel MTU and the link underneath
Only names failDNS resolutionThe resolver configured for the tunnel
Works sometimesMultiple paths or state expiryFlow selection and NAT state

修复你已证明的那一层

当故障在转发时,修正就是一条转发规则或一条路由,并且按设计允许的范围写得尽量窄。当故障在大小上时,修正是一个把这条通路上的封装算进去的 MTU,而且只用在需要它的接口上,不是用在 fleet 里的每个网卡。

无论哪种情况,之后都用同一个目的地重做同一件事。原来的大传输现在能完成,说明改动打中了出问题的那一层。如果只有小探测变好,你只是处理了症状,真正的限制还在原处。

把改动之前观察到的形态写下来。这一行记在修复方案旁边,正是它让下一个人不会去下调一个从来不是问题的 MTU。

相关文章