一条主机路由,一个地址,而 ping 立刻以 General failure 失败,而不是请求超时。这个区别就是全部诊断。超时意味着数据包已经发出,只是被某处忽略。General failure 意味着 Windows 从一开始就无法把数据包交给任何接口。

所以,当路由表看起来完美、错误却仍是 General failure 时,拦截发生在路由决策之下,而厂商客户端正是在那里起作用的东西。

先读懂错误,再看路由表

Windows 找不到可发送的接口时就返回这个错误,它对目标会如何处理数据包只字不提。可达性、远端防火墙、服务是否可用,全都是你还没走到的下游问题。

这种情况的经典配置是一条主机路由,把单个局域网地址指向物理网关,让它绕过隧道。route add 接受它,route print 显示它,ping 却仍然失败,因为过滤驱动早已判定这个数据包不允许出去。

在接受这个解释之前,先确认这条路由确实被选中:检查接口索引和度量值,并确认重连后条目没有过期。指向已不存在接口的路由会给出相似的错误,原因却无聊得多。

三层,三个不同的负责人

胜出的是最后执行的那一层,而这三层的顺序并不是多数人以为的那样。

LayerWhat it decides
Routing tableWhich interface and next hop should carry the packet
Client filter driverWhether this packet is permitted to leave outside the tunnel at all
Client featureWhether 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 过滤,这些必须刻意重建,或者接受它们不存在。

无论选什么,都记录下拦截归哪一层所有。从未离开这台机器的数据包是过滤的结果,任何路由改动都修不好过滤器。

相关文章