openfortivpn 老是覆盖 DNS?找出真正的写入者
两个开关分别让客户端与 pppd 的 DNS 写入者闭嘴,但谁都没指定接替者。沿着交接链路排查,选定一个所有者,再按链路逐条验证解析。
从连接建立的那一刻开始追:客户端完成认证,pppd 完成协商,接着某个东西把 DNS 设置写进操作系统。如果你只知道 VPN 改了你的解析器,那还不知道是这三个阶段里的哪一个干的。其中两个都可能,而在使用文档所述 pppd 集成的客户端上,两者跑得足够近,看起来就像同一个行为者。给写入者点名是第一步;选它的接替者是第二步,而那是一个独立决定,有它自己的失败模式。
下面的顺序沿着客户端由内向外走:连接到底改了什么、哪个开关压制哪个写入者、谁应当接手、以及如何确认结果在重连后仍然成立。每个阶段留下的痕迹不同,而痕迹正是判断交接是否真的发生的依据。
先弄清连接到底改了什么
用平常的命令连一次,比较前后的解析结果。在运行 systemd-resolved 的 Linux 主机上,resolvectl status 会按链路打印 DNS 服务器与搜索域;出现一条自带服务器的新 tun 或 ppp 链路,就是客户端侧更新的指纹。在 macOS 上,scutil --dns 会按应用查询的顺序显示解析器配置。
把它和你以为会变的那个文件对照。按链路视图里那条连接作用域的记录,与被改写的 /etc/resolv.conf,是两种不同结果,后者可能是一个完全由别的东西托管的符号链接。在同一时刻记录解析器地址、搜索域和接口名;其中任何一项变化都指向另一个写入者。没有这条基线,之后每一次修复都只是在猜三个组件里哪个动了。
两个开关,以及各自压制的写入者
openfortivpn 文档给出了一个选项片段,把它能控制的两个写入者一起关掉;每个开关都有一个完整写法的等价形式,手册把两者当作同一个设置。
openfortivpn gw.example.com:443 --no-dns --pppd-no-peerdns
# written out in long form
openfortivpn gw.example.com:443 --set-dns=0 --pppd-use-peerdns=0
--no-dns 让客户端不再应用它从网关学到的 DNS 服务器,而 --pppd-no-peerdns 让 pppd 不再把对端 DNS 推进系统。 upstream 手册 警告说,PPP 触发的 DNS 更新可能与客户端自身的 DNS 更新互相竞争,所以两个开关都该写进片段,而不是认为其中一个就够了。
两个开关都没有指定替代解析器,也没有阻止网络管理器、DHCP 客户端或另一套 VPN 集成在之后写入解析。压制两个写入者只是把这块地空出来,而不是有人接手。如果第三个组件本来就在管 DNS,这个片段不会改变任何你能观察到的东西;如果没有任何东西在管,你刚刚拆掉了私有域名解析的唯一来源。只有在替代所有者先被选定并单独验证过之后,这种安排才成立。
先选所有者,再关任何东西
先决定谁来应答业务域名的查询,因为这个选择约束后面的一切。沿用现有解析器意味着私有区必须从客户端所在的位置本来就可达,而办公楼里的私有解析器需要一条在隧道建起后仍然有效的路由。把所有查询都发给单一内部服务是第三种策略,失败模式更尖锐:那个服务不可达时,公网域名会和私有域名一起失效。
路由归属刻意保持分离。路由选项并不是因为你改了 DNS 就必须动,而在没有装好替代方案的情况下关掉路由安装,可能让你刚选定的解析器变得不可达。要针对解析器地址单独查路由表,而不只是查你顺手测的那个应用子网。
按链路查解析,而不是按文件
在有作用域或按域解析的主机上,单个 /etc/resolv.conf 并不等于应用实际所用配置的清单,所以请按平台公开的方式读取解析器状态。
resolvectl status
resolvectl query vpn.internal.example.com
resolvectl query example.com
ip route get 10.20.0.53
连接起来之后,分别查一个私有域名和一个公网域名,并记下各自由哪条链路应答。当 VPN 链路带有按域的搜索列表时,私有域名可以正确解析,而公网域名仍走本地解析器;这种分工是设计在起作用,不是故障。如果私有查询失败,先查通往解析器的路由,再动 DNS;如果它成功而应用仍然失败,那应用可能在读自己的缓存或另一套配置的解析器。
重连并确认断开后的状态
把连接降下来,重跑两个查询。选定的所有者装进去的东西,应当由它自己撤掉或恢复,而不是被你已经压制的客户端留在原地。比隧道活得更久的过期链路记录,会继续把私有查询发往一个已经不可达的地址。
然后再连一次,重新读同样三个值:解析器地址、搜索域、接口。
如果它们与你记下的策略一致,交接就完成了,VPN 客户端不再是写入者之一。如果链路起来几秒后某个值又退回去,说明还有别的东西在应用配置,下一步是找出那个组件,而不是再加一个开关。你想要的最终状态是平淡无事的:一个所有者、一份成文策略,以及一台断开后解析行为与隧道存在之前完全一致的主机。