接入酒店网络会让你在两个不同时刻面对两个 DNS 决定:设备在登录时发出的查询,以及隧道建立之后发出的查询。热点可以通过它控制的网络影响前者。后者取决于客户端自身的策略,这是另一件需要单独检查的事。

按顺序走一遍连接过程,从第一次 DHCP 租约一直到解析出私有名称的那次查询。这样,支持工单里看起来相同的两类故障就清楚了:一类发生在隧道存在之前,另一类发生在隧道内部。

热点能碰什么、不能碰什么

接入网通过 DHCP 下发解析器地址,并且可以拦截发往该地址的 53 端口。这足以用门户地址或拦截页回答每一次不受保护的查询。也足以让端点写成主机名的 VPN 客户端无法工作。

热点做不到的,是在查询已经进入已建立的隧道之后再去读取或改写它,前提是隧道确实承载了该查询。拦截取决于能否看到明文提问。

查询仍会离开隧道,原因与热点无关:浏览器的安全 DNS 设置、把企业后缀留给本地解析器的 split-DNS 规则,或配置为把 DNS 排除在隧道之外的客户端。每一项都是客户端侧的选择,从外面看,每一项都像热点的干扰。

PathWho answersWhat a failure looks like
Lookup before the tunnel is upThe network's resolverThe client never reaches its endpoint
Lookup inside the tunnelThe resolver pushed by the clientLocal policy or tunnel DNS is misconfigured
Browser secure DNSA DoH provider over port 443Both the hotspot and the tunnel policy are bypassed

引导查询发生在隧道建立之前

拿到主机名的客户端必须先解析它,而在那一刻没有任何隧道保护这次查询。如果热点用门户地址作答,协商就会失败或挂起。如果它什么都不答,客户端会报告名称错误,隧道根本不会启动。两种结果都能解释一份看似无辜的空隧道日志。

操作系统也会执行自己的连通性检查和门户探测,这些在 RFC 8910 和 RFC 8952 中有描述,而这些请求在任何 VPN 启动之前就会发出。在代理日志里看到它们属于预期行为,而不是泄漏的证据。

实用的做法是给客户端一个不需要解析的端点。如果做不到,就先完成登录再连接。

弄清是哪个解析器作答

问系统而不是问浏览器,并把查询跑两次:一次走设备当前使用的解析器,一次针对固定地址。

resolvectl query vpn.example.com
dig +short vpn.example.com
dig +short vpn.example.com @1.1.1.1

第一条命令的答案与第三条不同,说明本地解析器返回了别的东西,而这正是会重定向的热点所做的事。第三条失败、第一条成功,指向门户:本地解析器给出了登录地址,而出站 53 端口被丢弃。两条都超时,则说明网络在认证完成前一直丢弃 DNS。

连接后重复一次并比较。缓存答案会跨越切换,所以第二次观察前要清缓存或换一个新名字查询。

让后续查询留在你预期的路径上

同时接管 DNS 的全隧道配置最简单:每个应用的每次查询都发往隧道推送的解析器,本地网络只能看到加密流量。连接后分别解析一个内部名称和一个公共名称,再把两个答案与隧道解析器单独返回的结果对比,就能验证这一点。

split-DNS 需要一份有明确意图的域名清单:企业后缀走隧道,其余全部走本地,两者之间不要重叠。

浏览器的安全 DNS 不在这套策略之内,所以如果为了让配置文件表现可预期而必须关掉它,就针对该配置文件关闭,而不是针对整台机器。要在浏览器设置里做,而不是改系统解析器,这样下次还能看到改动。每次测试用一行记录答案、解析器和连接阶段。说酒店 Wi-Fi 上 DNS 失败的报告,描述的只是至少有三种不同成因的症状。

相关文章