同一台服务器上其他设备都正常,只有一台笔记本通过隧道上传时卡住。这个现象指向单条路径,而不是服务器配置,也是 mssfix 问题的常见入口。该选项可能有帮助,但只对它真正改写的 TCP 连接有效。了解它的作用范围,可以避免为了救一台客户端而去改动本来正常的服务器。

这个选项改写了什么

mssfix 会编辑经过隧道的 TCP 握手中通告的最大段大小,好让发送端选择能装进封装预算的分段。它作用于握手,也就是说,在改动之前已经建立的连接会保留其协商好的值。

它不会缩小 UDP 数据报,也不会设置隧道 MTU。两种不同的问题会产生同样的症状:一是无视路径上限的 TCP 发送端,二是无论多大都静默丢弃大包的路径。mssfix 只解决前者,对后者毫无作用。

这一区别解释了那些令人失望的实验。在黑洞路径上设置更小的值,只会改变分段大小,却改变不了随后的丢包,因此传输会在另一个位置失败。

作用范围是隧道内的 TCP

只有 TCP 流量会被改写。QUIC 会话、游戏或发送大 UDP 数据报的应用会保持自己的包大小;如果卡住的正是这些传输,修复就应落在隧道或路径 MTU 上。在选择 TCP 选项之前,先弄清楚失败的传输使用什么协议,因为错误的层次有它自己的修复方式。

方向同样重要。客户端设置影响的是该客户端发进隧道的流量,而服务器覆盖的是它转发给客户端的流。如果只有入站下载卡住,客户端一侧的值就不是全部原因。

数字和关键字并不通用

OpenVPN 2.6 的社区版接受值后面的可选关键字。带 mtu 时,数字描述的是包含 IP 和 UDP 头的隧道外层包大小;不带它时,参数遵循另一套计算约定。因此,在版本之间复制的同一行并不描述同样的包预算。请查阅你实际运行的构建自带的文档页,而不是另一版本的教程。

语法是这样的:

mssfix 1400 mtu

把 1400 当作占位符,而不是你这条路径的建议值。应根据实测路径和实际使用的封装推导该值,并记住:旧版本或其他实现上的客户端可能会拒绝或重新解释这个关键字。

先在这一台客户端上确认

在改动任何东西之前,先从出问题的机器上测量路径。路径在不分片的情况下能承载的负载,就是你要找的数字:

ping -M do -s 1472 10.8.0.1
ping -M do -s 1400 10.8.0.1

第一个探测在加上 28 字节包头后正好装进 1500 字节的包。如果它因分片错误失败,而更小的那个成功,可用的值就介于两者之间,隧道开销还要从顶部扣除。

然后在新的连接上重复那次卡住的传输并对比。如果只有这一台客户端改善,其他设备不受影响,你就找到了问题的范围。如果所有客户端都卡住,那该检查的就是服务器一侧的值。两种结果都不足以成为去改动从未处于故障路径上的硬件的理由。

相关文章