昨天原来的客户端还能用。今天新来的客户端占住了连接,而旧配置却停在一个从前毫不费力就能通过的阶段。凭据很少是原因,网关通常也无辜。真正变化的是,两套 VPN 栈现在要抢同一个独占资源,而修复取决于能否把它指认出来。与其把两个都重装,不如按层逐一排查。

按顺序走过四层

一个 VPN 产品需要四种可能冲突的资源:一个常常拒绝运行两次的后台服务、一个固定端口、一个先于路由表看到流量的虚拟网卡或内核过滤器,以及把路由插到默认路由之前的权限。知道是哪一种让了步,就能把含糊的冲突变成一个有可检验答案的问题。

在动手之前,先把症状对应到某一层。起不来的客户端指向服务;能启动却从不协商的指向端口;一方连上而另一方完全断网的,指向过滤器或默认路由。把这个对应关系写下来,它能省下一小时抱着侥幸重装软件的时间。

从那个不愿运行两次的服务开始

在 Windows 上,企业客户端通常不止是一条隧道,因为它会随配置一起安装服务、过滤器驱动,有时还有凭据提供程序。记下变更前和变更后分别有哪些服务在运行,然后对比两份清单,而不是反复重启直到碰巧能用。服务之间还会通过依赖关系互相排斥,启动一个就会停掉另一个;同样的模式也出现在 macOS 的 launchd 任务和共享守护进程上。几秒内启动又退出的客户端,报告的是归属权,而不是配置问题。

先读服务状态和它的日志,再读配置。在同一分钟内启动又停止的服务,就是要找的模式,它自己的事件日志会点名把它挤掉的那个依赖。配置修不好一个没有运行的进程,花在编辑配置上的时间,就是没花在真正冲突上的时间。

接着问端口归谁

端口归属是最清楚的证据,因为绑定失败会直接点名冲突。两个 IKE 实现不可能同时应答同一个本地地址和 UDP 端口,再重试多少次也不会改变。

Get-NetUDPEndpoint -LocalPort 500,4500 | Select-Object LocalAddress,LocalPort,OwningProcess
netstat -ano | findstr :500
sudo lsof -nP -iUDP:500
ss -lunp | grep -E ':500|:4500'

无论哪一行匹配你的平台,你要的答案都是一个进程,以及孕育它的那个服务。如果监听者是内置 IKE 服务,第二个客户端就是闯入者;如果是厂商代理,内置客户端才是闯入者。决定谁可以在登录时启动,并关掉另一方的自启动,而不是每个会话都去杀它。

过滤器驱动位于路由之下

网络过滤器驱动会拦截网卡与协议栈之间的流量,所以无论路由表怎么说,它都能改写或阻断数据包。看起来正确的路由被忽略,原因就在这里;ping 能通、旁边的浏览器却什么都打不开,原因也在这里。

厂商组件还会绑定到特定的连接。绑定在某块网卡上的旧过滤器,可能让本来正确的配置无法完成握手;把该组件从网卡属性上解绑,比整个卸载产品更窄、更可逆。既然绑定是按连接生效的,就该比较各块网卡,而不是整栈。

决定哪个产品拥有启动权,然后记录下来

只有两个客户端在设计上各占一层时,共存才现实,比如 IPsec 栈旁边放一个只处理应用流量的代理。当两者都要同一个端口、同一层过滤器或发布默认路由的权利时,它们就会一直轮流坐庄,每次故障都像新问题。

有意识地选定归属。能扛过重启的形态包括:把第二个客户端放进虚拟机、把它留在专用硬件上,或者统一到一个同时会说两种协议的客户端上。关掉失败一方的自启动和服务,比每次启动后重建路由表改动更小,而且改一处设置就能回退。

相关文章