隧道已经建立,横幅也到达了,客户端却打印出正在等待密钥交换回复的消息。搜索结果直指 MTU,有时确实如此。但常常并非如此:回复可能从未发出,因为客户端读不到某个密钥文件,或者两端从未就算法达成一致。这一行只说明客户端在等什么,并不说明等待因何开始。请把它当作症状,在改动任何大小之前先分开这三种原因。

查看跟踪输出,判断是否本来就该有回复

详细输出显示沉默之前最后一个成功的步骤。如果服务器的协议横幅已经到达,说明 TCP 正常、远端仍活着;真正的问题是一个特定数据包发生了什么。横幅之后沉默一分钟,看起来像路径问题。提示没有匹配的密钥交换方法,是策略问题。长时间等待以服务器关闭会话告终,说明服务器放弃了,服务器日志会解释原因。

最后一种情况,先读服务器的认证日志,再去动客户端。服务器从未发出的决定,客户端看不到。

为什么很小的回复仍可能过大

密钥交换的回复通常很小,所以怪罪大小听起来不对。带主机证书时回复并不小,因为它携带服务器的证书链。这使它成为会话中第一个可能超出隧道可用载荷的数据包。当路径 MTU 探测的反馈在半路丢失时,发送方会反复重发一个装不下的包,客户端就永远停在同一行上。

去确定大小,而不是假设。用 ip link show tun0 读取隧道 MTU,然后发送不应分片的探测:ping -4 -M do -s 1352 host,再用更小的载荷重复。在某个具体大小上从失败变为成功就是证据;始终失败则说明 ICMP 被过滤,什么也说明不了。

临时降低可以很快验证理论,长期方案则应写进配置档,或在转发隧道的路由器上做 MSS 钳制:

sudo ip link set dev tun0 mtu 1200
sudo iptables -t mangle -A FORWARD -p tcp --tcp-flags SYN,RST SYN -j TCPMSS --clamp-mss-to-pmtu

两个会冒充大小问题的原因

客户端读不到的密钥文件会造成同样的等待,即使在详细输出里也没有任何警告。有一种 known_hosts 写法很容易触发:@cert-authority 条目指向只有某一个账户能读的 CA 公钥。拥有该文件的账户能连上,其他账户全都会卡住。如果故障跟着用户而不是主机,就先查文件权限,再查数据包大小。

升级也可能删掉两端过去共用的算法。把服务器仍支持的一种方法固定下来作为诊断:ssh -oKexAlgorithms=ecdh-sha2-nistp521 user@host。立刻成功的连接说明路径没问题,修复应落在双方的协商策略上。

值得记下的三个事实

记下改动前后的隧道 MTU、大文件复制是否在可复现的大小上失败,以及同一隧道上不带证书的主机是否也以同样方式卡住。这三个观察比一堆命令更快地把大小问题与权限、协商区分开。

它们也能阻止后来的人为一个与大小无关的故障去调低 MTU。

如果情况仍不清楚,就从同一隧道的第二台客户端测试。能连上的客户端会把故障从路径转移到第一台机器的配置上。

相关文章