一条能完成认证、能传一个 ping,却在第一次大流量传输时卡住的隧道,是缺少 ICMP 消息的典型特征,而不是 VPN 坏了。发送方永远不知道包太大,只会不断重试同一尺寸,应用则一直等待。修复它属于防火墙策略决策,而不是重装客户端。顺序很重要:先测出尺寸边界在哪里,再收窄那条吞掉报告的策略。

在这条链路上,ICMP 究竟承载什么

IPv4 路径 MTU 发现 依赖路由器报告:设置了 don't-fragment 位的包无法转发。这份报告就是 ICMP Fragmentation Needed 消息,没有它,发送方就没有理由缩小分段尺寸。IPv6 更严格:路由器在传输途中不做分片,因此 ICMPv6 Packet Too Big 消息是唯一能让发送方缩小的信号。

这两类消息都是控制平面的反馈,都不是诊断用的回显。封锁 ping 的策略与封锁全部 ICMP 的策略在规则表里看起来很相似,在网络上的表现却截然不同。后者会把尺寸正确的隧道,变成一条对任何大于链路最小环节的流量都单向不通的路径。

有些传输层用探测包自行实现发现,正如 RFC 4821 所述,它们对这类反馈的依赖更小。这是检查自己跑的是哪种传输层的理由,而不是假定每条隧道都免疫。

消息在链路上的作用若被封锁
ICMPv4 类型 3 代码 4包对下一跳来说太大发送方不断重试并卡住
ICMPv6 类型 2Packet Too Big,IPv6 中的对应消息同样卡住,且没有分片作为退路
ICMP 类型 11超时,traceroute 会用到诊断会丢失跳数,流量仍然通行
ICMP 回显请求与应答可达性测试ping 失败,链路可能完好

故障与尺寸相关

先问故障是否与包尺寸相关。登录页、DNS 查询和短小的 API 调用都能通过,而文件上传、大响应或图片下载却会卡住。这种模式指向两端之间某处的尺寸上限,而不是认证或路由问题。小 ping 成功,几乎说明不了边界在哪里。

隧道内部要考虑两层:载荷包和外层封装包。内部发送方可能行为正确,而外层路径比隧道假设的更小,所以隧道自身的 MTU 设置与下面的物理链路都很重要。

改规则之前先测量

用 don't-fragment 位和自选的载荷尺寸去探测,从出问题的客户端指向受保护的地址:

ping -M do -s 1472 10.20.5.7
ping -M do -s 1300 10.20.5.7

1472 字节载荷加上 28 字节报头,正好是 1500 字节的包。如果大探测因分片错误失败、小探测通过,就找到了边界;再按隧道开销修正,重复到可用尺寸稳定为止。

接着确认缺口来自报告本身。如果探测静默失败,既无错误也无应答,说明消息大概率被丢弃而非送达,可疑的就是那条规则。

收窄规则,然后重新测试任务

修正应当放行特定的控制消息,而不是整个协议。在 iptables 主机上,形态是按类型放行;请按你平台上管理防火墙的方式调整语法:

iptables -I INPUT -p icmp --icmp-type fragmentation-needed -j ACCEPT
ip6tables -I INPUT -p icmpv6 --icmpv6-type packet-too-big -j ACCEPT

如果本地策略如此,回显应答可以继续封锁,因为链路并不需要它们。然后从新连接重测原先失败的那次传输,并确认规则计数器显示消息正在到达。

如果放行消息后大传输仍然卡住,剩余的限制在别处:隧道 MTU 设得太高、会改写包的代理,或者丢弃而不报告的中间盒。ICMP 规则是必要条件,而不是充分条件。

相关文章