OpenVPN 推送的路由未安装:时序、权限或策略
推送的路由可能消失于时序竞争、权限缺失或客户端策略。请先对比服务器的推送列表与真实路由表。
服务器说它推送了路由,客户端说它已连接,而目标地址依然不可达。正是三种原因造成了这副景象。添加路由在设备存在之前就执行了,客户端缺少修改路由表的权限,或者某条策略要求客户端忽略推送的选项。
从外部看它们一模一样,却需要不同的修复方式。请在做出路由决定的位置阅读客户端日志。
证明路由是不存在,而不只是坏掉
首先要证明路由不存在,而不是坏掉。在 Linux 上,ip route show dev tun0 会列出客户端在隧道设备上安装了哪些内容。在 Windows 上,route print 或 Get-NetRoute 以表格形式显示同样的内容。
路由存在却不转发流量是另一个问题。这会把排查引向转发和防火墙规则,而不是路由安装。
时序:添加在设备存在之前就执行了
客户端在控制通道建立、并且配置好接口之后,才会解析服务器的 PUSH_REPLY。也只有到那时,它才用平台提供的机制去改动路由表。Linux 走 netlink,Windows 使用需要提升令牌的 API。脚本或客户端如果在读到配置时就立即添加路由,就可能在 TUN/TAP 设备出现之前运行,内核会拒绝这次添加。
同一个竞争解释了为什么手写的路由能用而自动添加的不能:等你写入时,接口早已启动。
route-delay 就是为这种情况准备的,而 route-up 指定一个在接口和路由配置完成之后运行的脚本。把依赖隧道地址的路由放进那个钩子,而不是放在早期阶段。
权限:谁可以修改路由表
修改 Windows 路由表需要提升的令牌。普通用户启动的 GUI 可以通过服务设置适配器地址,却依然无法添加路由。此时日志显示的是类似拒绝访问的错误,而不是推送缺失。
以管理员身份启动 GUI,或使用基于服务的客户端,会改变这个结果。在不带所需令牌的情况下启动客户端的计划任务不会。
在改动任何东西之前,先确认客户端实际以哪个账户运行。版本和服务模式决定了哪些原因有可能成立,所以请把两者都记录在路由输出旁边。
策略:推送的路由可以被有意丢弃
route-nopull 会让客户端忽略服务器推送的路由,包括推送的默认路由,而隧道地址仍然被接受。推送的 DNS 和 DHCP 选项也会被同一条指令丢弃。这样的客户端并没有故障;它期待在自己配置里看到显式的路由行。
route-noexec 是另一种控制:它彻底阻止客户端执行路由变更。客户端无法映射的拓扑也可能产生类似结果,路由会被记录为被拒绝而不是被添加。请阅读报告决定的那一行日志,而不是猜测三者中哪一个成立。然后再检查实际生效的配置文件,因为导入器或管理工具可能添加了用户从未编辑过的选项。
在文本编辑器里看起来干净的配置文件,运行时仍可能携带被添加的指令。
对比推送列表与路由表
连接之后,把服务器的推送列表放在客户端的路由表旁边。在 Linux 上就是 ip route show dev tun0;在 Windows 上则是 route print 或 Get-NetRoute。如果路由不存在,先修复安装。如果路由存在而流量失败,就转向转发和防火墙策略。
记录客户端版本、运行账户,以及是否基于服务。这三点能告诉下一个人哪些原因已被排除。