当 SSH 到服务器公网地址失效时隧道却正常建立,看起来像是服务器拒绝了连接。在 Windows 上更可能的原因在本地:当全隧道 AllowedIPs 为 /0 时,会启用限制性防火墙规则,只放行隧道自身的传输和极少数其他流量。到达该地址的加密数据包并不能说明发往同一地址的另一条 TCP 连接是否被允许发出。

在动手修改对端列表之前,先把端点的公网地址与它的内部隧道地址区分开。几乎每一次通过编辑 AllowedIPs 来修复此问题的尝试,都会让策略更弱,而不是让路由变正确。

路由许可与防火墙许可是两回事

路由决定数据包会发往哪里,防火墙规则决定它能不能被发出。因此为端点的公网 IP 添加路由,只是产生了一条仍可能被过滤器拦住的路径,而这个症状造成的困惑恰恰就在这里。在 Windows 上过滤器是实现的一部分而非附加组件,所以任何路由条目都改变不了它。这两项决策在其他系统上同样分离,只是默认值不同。

这就是为什么到端点的 traceroute 可以成功,而 SSH 尝试却失败。前者由持有该例外的服务承载,后者不是。

Windows 上的 /0 会做什么

当单个对端允许的地址覆盖整个 IPv4 空间时,WireGuard for Windows 会采用限制性的防火墙姿态,拦截本来会从隧道之外发出的流量。隧道服务自身的传输被放行,否则 VPN 无法工作。发往同一公网地址的其他应用不会获得这种许可,因为例外属于传输而不是地址。 Windows 网络说明 描述了这一行为以及编辑器中的相关控制项。

这些规则就是 kill switch 一词背后的机制。它们由配置的形状触发,而不是由名为该选项的勾选框触发。

例外会改变保护模型

把 /0 换成两个半默认前缀,是保留广泛路由而不带限制语义的文档化做法,它是另一种保护模型,而不是更短的写法。从允许前缀中减去端点地址是另一种常见变通,它会加长列表,也会改变哪些规则被触发。两者都不是只产生局部影响的局部修改。每一个都移动了机器上所有流的边界,而不只是你正在修复的那条连接。

在确实需要直接公网 SSH 的地方,配置文件的所有者必须同时设计外部路由及其防火墙许可,并决定隧道断开时无关流量会怎样。单独审视 IPv4 与 IPv6 也属于其中,因为规则是按地址族表达的。为挽救一次管理会话而添加的宽泛绕过,通常会暴露比该会话更多的东西。

测试你选择的管理路径

先决定管理流量应走隧道内部还是外部,然后只测试这个选择,而不是两者同时进行。下面的命令会检查客户端地址、对端状态以及到每个目标的连接。请在隧道建立时从 Windows 客户端运行它们。

ipconfig | findstr /i "WireGuard IPv4"
wg show
ssh -v [email protected]
Test-NetConnection 203.0.113.9 -Port 22

成功 SSH 到内部地址,说明隧道承载了管理流量,并且服务器自身的防火墙接受了来自对端网段的流量。两个目标都失败则是服务器端或密钥的问题,而不是 Windows 路由问题。如果内部地址可用而外部地址不可用, 本地防火墙姿态 正是按设计在发挥作用。修改配置文件之前,请按这个顺序阅读三项结果。

记录管理路径、使用的地址以及隧道断开时的行为。正是这条记录,能阻止下一个人为了省下五分钟而扩大绕过范围。

相关文章