VPN 客户端开启时 ping 局域网地址报 General failure
路由表看起来正常,Windows 却说完全无法到达任何适配器。判断拦截来自路由、过滤还是客户端本身。
一条主机路由,一个地址,而 ping 立刻以 General failure 失败,而不是请求超时。这个区别就是全部诊断。超时意味着数据包已经发出,只是被某处忽略。General failure 意味着 Windows 从一开始就无法把数据包交给任何接口。
所以,当路由表看起来完美、错误却仍是 General failure 时,拦截发生在路由决策之下,而厂商客户端正是在那里起作用的东西。
先读懂错误,再看路由表
Windows 找不到可发送的接口时就返回这个错误,它对目标会如何处理数据包只字不提。可达性、远端防火墙、服务是否可用,全都是你还没走到的下游问题。
这种情况的经典配置是一条主机路由,把单个局域网地址指向物理网关,让它绕过隧道。route add 接受它,route print 显示它,ping 却仍然失败,因为过滤驱动早已判定这个数据包不允许出去。
在接受这个解释之前,先确认这条路由确实被选中:检查接口索引和度量值,并确认重连后条目没有过期。指向已不存在接口的路由会给出相似的错误,原因却无聊得多。
三层,三个不同的负责人
胜出的是最后执行的那一层,而这三层的顺序并不是多数人以为的那样。
| Layer | What it decides |
|---|---|
| Routing table | Which interface and next hop should carry the packet |
| Client filter driver | Whether this packet is permitted to leave outside the tunnel at all |
| Client feature | Whether a named feature, such as LAN blocking, is active right now |
中间层正是路由可以同时正确又无用的原因。厂商客户端会安装过滤器和防火墙规则,把隧道之外的流量丢弃,这也正是实现其断网开关的同一套机制。路由表里没有任何东西参与这个决定。
第三层解释了一种经常出现的奇怪报告:即使断开客户端,本地子网仍然无法访问。服务还在运行,过滤器也还装着,所以“没连接”并不等于“没过滤”。在下结论之前,请退出客户端,而不只是断开它。
按顺序该试什么
先去掉那些移除成本低、恢复也容易的功能。局域网发现(有时称为局域网隐身)会拦下发往私有地址段的流量,让这台机器对邻居隐身。打印机、本地文件服务器和路由器本身都会消失在这个开关后面。过滤 DNS 的威胁防护功能会安装自己的钩子,据说也会以几乎相同的方式破坏本地可达性。
把两者都关掉,完全退出客户端,然后再测那个地址。这个顺序把“拦截流量的功能”和“错误路由流量的隧道”分开,只需两分钟,而不是花一下午折腾静态路由。
ping 192.168.1.50
tracert -d 192.168.1.50
route print -4
如果关闭功能后地址有回应,你面对的是策略选择而不是故障:在让功能保持关闭、添加例外,或接受这台机器在本地网络中隐身之间做选择。
把客户端的例外路径用窄
当某个功能必须保持开启时,客户端自带的分流隧道才是受支持的出路。把例外保持得尽可能小,通常是一个服务器对应一个主机地址,或一个网段对应一个前缀。覆盖整个私有地址段的规则是一个永久的洞,没人会记得加过,也没人敢删。
然后先按地址验证,再按名称验证。如果地址有回应且第一跳在物理网关上,例外就是有效的。如果名称仍然失败,你已经转到 DNS 上,因为隧道的解析器不认识本地区域,任何路由改动都教不会它。
保留路由或例外,不要两个都留,并记下是哪一个在起作用。两套重叠的机制会互相掩盖,下一个调试这台机器的人会删掉其中一个,然后看不到任何变化。
当客户端本身成为障碍
有些版本过滤流量的方式,既不是静态路由也不是客户端例外能击败的。如果结论是这样,诚实的选项是等绕过功能,或者用厂商自己的配置文件走一个普通的 OpenVPN 客户端——原始报告里厂商支持的回复推荐的正是这个。
做这个替换之前先理解代价。普通配置文件的举止和任何普通隧道一样:它安装自己的路由,不重构其余协议栈,所以窄主机路由仍然按你预期的方式工作。你失去的是品牌客户端在隧道周围实现的一切,包括断网开关和 DNS 过滤,这些必须刻意重建,或者接受它们不存在。
无论选什么,都记录下拦截归哪一层所有。从未离开这台机器的数据包是过滤的结果,任何路由改动都修不好过滤器。