笔记本能连上,内网能打开,但有几个公网站点卡住。认证和路由显然正常,于是解释只剩包大小。在 L2TP/IPsec 隧道中,可用 MTU 小于适配器仍在通告的值,客户端持续发送设置了“不分片”位的全尺寸数据包。可以命令 pfSense 网关清除该位,这是在彻底修复前确认诊断的最快办法。

从失败的那些页面入手

在动任何设置之前,先记下哪些目标失败、哪些成功。低于隧道上限的握手能正常完成,而需要全尺寸分段的传输会中途停住。这种分化是尺寸问题而非过滤器问题的特征,因为被屏蔽的目标是在建立连接时失败,而不是在页面中途失败。这两项观察不花任何代价,并且立刻缩小排查范围。

用一个设置该位并控制负载大小的 ping 去试探。能通过的最大负载告诉你真实的路径 MTU,而适配器通告的值则显示两者相差多远。

把两个数字都记下来。修复取决于哪一个不对,而这对数字正是之后抓包要确认的。

DF 位在出方向上做了什么

封装是数字不同的原因。IPsec 增加 ESP,L2TP 再增加一层报头,因此隧道承载的负载少于物理链路。Windows 仍在适配器上报告 1500 字节,并对发出的内容设置“不分片”。当这样的数据包放不下时,网关的正确回应是 ICMP 报文,要求发送方缩小。这就是为什么一条能通过小 ping 的隧道仍可能让文件下载失败。

这条报文往往根本不会到达。某一跳可能过滤了 ICMP,或者没有任何设备生成它,发送方就会重复同样的大小,直到传输放弃。

在这里,沉默就是常态表现,所以症状被读成选择性封锁。客户端日志里没有任何记录会记下缺失的 ICMP 报文。

pfSense 的这个选项,以及它做不到的事

该选项位于“系统、高级、防火墙与 NAT”页面,标签为“清除无效 DF 位而不是丢弃数据包”。过滤器不是丢弃带有该标志的超大包,而是去掉标志、让数据包在下游被分片。当数据包无法整块通过出接口时,就算作无效。

该选项在不碰客户端的情况下恢复连通性,所以很受欢迎。它也是一种绕行:分片消耗 CPU,并让每个丢失的分片更昂贵。

它只适用于被转发的流量,不适用于防火墙自身发出的流量。同一页面上还有“禁用防火墙清理”,那会完全关闭规范化,比这个问题所需的改动大得多。

一种更窄的修复:让 TCP 保持不分片

几乎所有卡住的流都是 TCP,而 TCP 可以协商更小的分段,不必依赖分片。在隧道接口上限制 MSS 会在握手期间改写通告值,于是每一侧都发送真正放得下的量。路径随后表现可预期,也没有数据包需要被拆分。

这就把 UDP 留给路径发现或 DF 选项。当失败的站点是普通网页时,限制才是应当优先采用的改动。

客户端可以通过 netsh interface ipv4 show subinterfaces 报告自己的适配器 MTU。把这个数字与服务器认为协商出的值作比较,因为两者并不总是一致。无论协商报告了什么,操作系统真正使用的都是那个值。

用抓包确认,然后重置状态

决定之前两侧都要抓:一份在隧道经过的地方,另一份在 WAN 接口经过的地方。以全尺寸发出却没有 ICMP 返回的数据包,指向限制这一层才是对的。到达之后又在回程中死掉的应答,则指向隧道的 MTU。

重试之前清空状态表,因为已有流会保留旧的段大小。然后加载失败的那个页面,读状态视图看双向流量,而不是只看单侧计数。如果仍然卡住,就再抓一次,而不是去试另一个复选框。

相关文章