OpenVPN 上 SSH 卡住?先测路径 MTU
回声正常,一到列目录会话就永久卡死。改 mssfix、fragment 或接口 MTU 之前,先从两端测出上限。
SSH 能连上,提示符也出现了,可一旦命令返回稍大的结果,会话立刻死掉。回声还能撑一会儿,随后连接超时,而客户端仍显示隧道处于连接状态。这种「数据一来就坏」的会话通常撞上的是尺寸上限,而不是 SSH 本身的缺陷。下面的检查顺序,是为了先排除最省事的解释。
先看清故障形态,再动配置文件
小包过得去,满包过不去。提示符、横幅或一次按键轻松装下;目录列表、下载或粘贴的整块内容装不下。行为发生变化时的那个尺寸才是线索,而不是「出问题的是 SSH」这件事。
机制是这样的: 路径 MTU 发现机制,它依赖反馈. TCP 选好分段大小,沿途路由器若转不动这个包,本应发 ICMP 消息告知。封装让外层包大于内层包,所以隧道内可用的尺寸永远低于物理链路。只要在任何地方过滤掉这些 ICMP 消息,发送方就永远收不到修正,继续发满分段,外层包被静默丢弃。
从两端测出上限
先比较隧道 MTU 与物理链路,再决定改哪一个。如果隧道直接复制了物理链路的值,它已经告诉你错配在哪里。
从隧道内部用禁止分片的探测,逐步降低载荷,直到有回应。尺寸参数只计载荷,所以能通的值总在接口 MTU 之下。若需要接口数值,再把各层头部大小加回去。
ip link show tun0
ping -M do -s 1380 10.9.0.1再从隧道外部对服务器公网地址重复一次探测。如果大探测在外网也失败,瓶颈就在通往服务器的路径上,任何隧道选项都挪不动它。这一步比较能让你免于去调一个从来不是问题源的客户端。打开配置文件之前,把两个结果都记下来。
mssfix 与 fragment 各管一段
mssfix 限制隧道内 TCP 连接在握手时通告的分段大小。它对 SSH、HTTPS 和文件复制最有效,所以往往一设上去,卡顿就消失了。它完全不碰 UDP 载荷。
隧道里还跑着 UDP 服务时,修好 SSH 之后仍可能继续失败,而这个结果会困扰所有以为一个选项能包打天下的人。
fragment 是另一套机制,也是另一件工具。它在封装前拆分超大包,只适用于 UDP 传输,会带来每个数据报的额外开销,文档里写明它是发现机制损坏时的最后手段。两端参数必须一致。一端限流、另一端分片,只会在日志里留下警告,并产生光看文件无法预测的行为。
调低接口 MTU 是粗放选项
把两端接口 MTU 一起调低,是粗放做法。它让每个内层发送方都用更小的数字,确实管用,但代价由全部流量承担,而不是由真正需要的那些 TCP 流承担。
当隧道承载你无法限流的流量,或客户端是你管不到配置的设备时,再选它。要对称地应用,并把数值记在配置旁边。只改一半比不改更糟,因为它看上去像已经修好了。
用当初卡住的那次传输复测
重新连接让配置生效,开一条新连接,重跑那条冻住的命令。分段大小在握手时协商,所以熬过重连的会话仍带着旧值。这里 ping 不是好测试,因为故障本质就是小包能过。用那个坏掉的列目录、下载或粘贴来验。
若在更小的尺寸下仍然卡住,就往别处看:让流状态过期的有状态防火墙、重复地址,或重连时会切换的路由。把失败的探测尺寸和你改过的设置一起记下来,这一对信息才让下一份报告有用。