适用场景

这个问题常见于 SakuraCat、Clash Verge、Clash Meta、Mihomo 一类客户端开启 TUN 后。

它看起来像 SSH 坏了,但真正坏掉的往往不是 key,也不是服务器的 sshd,而是 SSH 流量被 TUN 路由送进了代理路径。代理节点收到一个原本应该直连到服务器 22 端口的 SSH 握手,于是连接在认证前就被关掉。

怎么确认是这个问题

先确认 22 端口是否真的能碰到:

nc -G 5 -zv 203.0.113.10 22

如果这里直接失败,先不要看 TUN。那可能是安全组、防火墙、服务器 SSH 服务、端口或网络问题。

如果 nc 成功,再看 SSH 具体断在哪里:

ssh -vvv -o BatchMode=yes -o ConnectTimeout=8 your-host

典型输出会停在类似位置:

debug1: Connection established.
debug1: Local version string SSH-2.0-OpenSSH_9.9
kex_exchange_identification: Connection closed by remote host

这说明 SSH 还没走到 key 认证。它不是 Permission denied (publickey),也不是 host key 不匹配。

最后看系统路由:

route -n get 203.0.113.10

如果结果里出现下面这种路径,就说明流量被 TUN 接走了:

gateway: 198.18.0.1
interface: utun8

198.18.0.1 常见于 fake-ip / TUN 环境。utun* 是 macOS 上常见的虚拟隧道接口。

最小修复

最干净的最小修复,是让 SSH 明确从真实联网网卡出站。macOS 上 Wi-Fi 通常是 en0

ssh -o BindInterface=en0 your-host

如果这个命令能进入正常 SSH 握手,就把它写进 ~/.ssh/config

Host your-host
    HostName 203.0.113.10
    User ubuntu
    BindInterface en0
    ProxyCommand none

BindInterface 的价值是它绕过了客户端 UI、订阅刷新、规则热加载这些不稳定因素。只要你的真实出口网卡还是 en0,SSH 就不会再被默认路由带进 TUN。

配置层修复

BindInterface 是应用层修复。配置层也建议补上,因为它能让 SakuraCat、Clash Verge、Mihomo 对这些服务器 IP 直连。

只写 DIRECT 规则通常不够。规则层说“直连”,不代表 TUN 的系统路由层一定会放过这个 IP。

应该同时做两件事:

rules:
  - IP-CIDR,203.0.113.10/32,DIRECT,no-resolve

tun:
  auto-route: true
  auto-detect-interface: true
  route-exclude-address:
    - 203.0.113.10/32

这里用 /32,只排除这台 SSH 服务器。不要为了省事写一个很大的网段。

不适用情况

下面这些情况不是这篇的主要问题:

  • nc host 22 失败:先查端口、防火墙、安全组、服务器 SSH。
  • SSH 输出 Permission denied (publickey):这是 key 或服务器授权问题。
  • SSH 输出 host key 相关错误:这是 known_hosts / 主机指纹问题。
  • 服务器根本没有运行 sshd:先恢复服务器 SSH 服务。
  • 你的连接必须通过堡垒机或公司代理:不要强行 ProxyCommand none

Pattern extracted

参考