你在 RDP 窗口里,桌面就在屏幕上,然后你在那台远程机器上的 VPN 客户端里点了 Connect。几秒后窗口卡死,随后关闭。隧道确实起来了,VPN 日志会这样记录,而这恰恰是整个事件里最没用的事实。会话之所以死掉,是因为与你对话的机器改变了回复你的方式,所以先摸清返回路径,再去动隧道。

记录会话实际使用的端点

你在 RDP 客户端里输入的地址,未必是远程计算机回复的地址。NAT、RD Gateway 或主机前面的负载均衡器都可能改写它,而返回路径由远程机器在已建立的连接上看到的源地址决定。这一点弄错,你就会去找一条从未参与的路由。

在远程计算机上,在连接 VPN 之前,列出已建立的会话,并从表里读出对端地址。然后把它记在那台机器之外的地方,因为会话断开后你就读不到了。

Get-NetTCPConnection -LocalPort 3389 -State Established |
  Select-Object LocalAddress, RemoteAddress, RemotePort

把这个地址当作必须保持可达的东西。如果它是管理 VLAN 上的私有地址,隧道就必须别碰这条路径。如果是公网地址,回复就必须从把请求带进来的同一个接口出去。

读取通往该端点的路由

Windows 会为每个目的地选择一个接口,而 Find-NetRoute 会显示它此刻会做的决定。连接前先针对对端地址跑一次,然后在隧道起来后再跑一次,比较两次结果里的接口索引和下一跳。接口一变,整个缺陷就写在一行输出里。

Find-NetRoute -RemoteIPAddress 203.0.113.24
Get-NetRoute -DestinationPrefix 0.0.0.0/0 | Sort-Object RouteMetric
Get-VpnConnection -Name "Work VPN" | Select-Object SplitTunneling, Routes

全隧道配置文件会通过隧道装一条默认路由,正如 Windows 的 VPN 路由指南 所述,于是现在每个回复都从 VPN 出去,并取决于对端能否路由回你的客户端。拆分隧道配置默认更安全但并非免疫,因为一条覆盖对端地址的具体路由仍然可能压过物理默认路由。无论如何问题都一样:隧道起来之后,对端地址是否仍然解析到把会话带进来的那个接口?

如果不是,修复应落在配置文件里,或落在由 VPN 策略所有者批准的显式例外路由上。在事故过程中手改生产主机上的路由表,正是一次临时绕过变成无文档配置的方式。

留意防火墙配置文件的变化

新接口出现时会被分类,分类决定它的流量按哪个防火墙配置文件来判定。落进 Public 类别的隧道适配器可能在路由表看起来完美的时候悄悄挡住入站 RDP。这是第二种失效模式,症状不同:路由对了,包也到了,主机却拒绝连接。

Get-NetConnectionProfile
Get-NetFirewallProfile | Select-Object Name, Enabled
Get-NetFirewallRule -DisplayGroup "Remote Desktop" | Select-Object Name, Enabled, Profile

把绑定在隧道接口上的配置文件,与 Remote Desktop 规则所限定的配置文件做对比。只对 Domain 和 Private 启用的规则,对被分类为 Public 的接口毫无作用,改多少路由都改变不了这一点。有些 VPN 客户端在设计上还会限制访问本地子网,这从另一个控制点产生了同样形态的失效。

从还能回来的地方测试这次切换

用带外控制台或第二条管理路径,按这个顺序走完整套流程:确认现有会话,连接 VPN,开一个新会话,然后断开 VPN 再开一个。每一步测的是不同的切换,第一个失败的地方就告诉你哪个控制点要负责。

开始之前就把回滚安排好,例如一个定时任务,在规定间隔后执行 rasdial "Work VPN" /disconnect。这把丢失会话变成五分钟的中断,而不是跑一趟现场,是整个流程里最便宜的保险。

会话已经丢了之后如何回去

如果主机已经不可达,别再用同一个客户端试新的 RDP 连接,改用环境本来就有的恢复通道:RD Gateway、hypervisor 控制台或带外管理接口。请有控制台权限的人执行同样的 Find-NetRoute 和 Get-NetConnectionProfile 命令,让证据在恢复之后还留着。

然后就长期安排做决定,而不是挑最快的。要么 VPN 配置文件显式保留管理路径,要么把管理迁到不依赖主机默认路由的通道上。两种都站得住脚;靠猜网关的主机路由站不住。写清楚你选了哪一种,并记录那条必须活下来的对端地址。

相关文章