WSL 2 中的 resolv.conf:VPN 一连上,DNS 就失灵
WSL 会用它能看到的 Windows 网卡重新生成 resolv.conf,所以 VPN 的解析器可能永远到不了。先停掉自动生成,再测一个公司内网域名。
在发行版里浏览网页是正常的,可隧道一建立,第一个内网主机名就解析失败。下意识的反应是加一个公共解析器,这会让外网恢复,却让公司域名在当天剩下的时间里彻底不可达。在 WSL 2 中,/etc/resolv.conf 是生成出来的产物而不是配置,这一点才是真正值得弄清的机制。解决办法不是换更好的解析器,而是把文件的所有权拿回来。
这个文件是生成的,不是配置的
WSL 2 在启动时按当时能看到的 Windows 网卡写出该文件,并在顶部打印一条说明这一点的注释。如果 VPN 客户端之后新增或重写了某块网卡,发行版未必会重新生成任何东西,于是文件仍然在描述一个已不存在的网络。
第二种故障更安静:WSL 可能只从部分网卡复制服务器。如果物理网卡已有 IPv6 解析器,VPN 网卡提供的 IPv4 服务器就可能被丢弃而不是追加,文件看起来完整,却恰好漏掉那个能应答内网域名的服务器。
把 Windows 侧的视图和 Linux 侧的视图对照起来
动手前先读两边。在发行版里看文件内容,并确认它是普通文件还是链接。在 Windows 上列出每块网卡的解析器,包括 VPN 创建的那块:
ls -l /etc/resolv.conf
cat /etc/resolv.conf
Get-DnsClientServerAddress -AddressFamily IPv4
Get-NetAdapter | Where-Object Status -eq 'Up'
当 VPN 网卡显示公司 DNS 而 Linux 显示别的东西,分歧出在生成环节而不是连通性。网卡列表和地址都要比,因为少了网卡就解释了为什么少了服务器。这个区分决定了你是在修 WSL 还是在修防火墙,两者毫无共同点。
关掉自动生成,自己写文件
有一个有文档记录的设置能让 WSL 不再重写该文件,它位于 /etc/wsl.conf 中。给这个文件加上网络段:
[network]
generateResolvConf = false
然后在 Windows 上执行 wsl --shutdown 关停发行版,再重新启动。如果该路径是符号链接而不是普通文件,先删掉链接再写自己的内容,因为顺着链接写可能在下一次启动时把生成目标重新创建出来。从那一刻起文件归你所有,没有东西会再重写它。
nameserver 172.28.4.10
nameserver 172.28.4.11
search site.corp.example
options timeout:1 attempts:2 rotate
没有搜索域时,不带后缀的主机名会用公共根补齐,然后返回“无此域名”。timeout 阻止一个已经失效的首个服务器拖住每次查询,attempts 限制一次查询最多花几次尝试,rotate 把重试轮转开,而不是每次都从第一个开始。代价是文件不再跟随那种会话间会更换解析器地址的 VPN。
处理会搬家的解析器,然后验证
有些客户端下发的是会话专属解析器,于是一个静态文件在下一次连接时就崩了。两种做法都站得住。地址一变就用小脚本重写文件,或者保留自动生成,并确保 WSL 复制来源的那块网卡带着公司服务器。后者不需要钩子,但一旦生成过程跳过 VPN 网卡就会失败;两者都仍然要求先解决 IPv6 冲突。
Windows 还会应用自己的名称策略,比如后缀搜索列表或针对特定域名的解析策略,而复制网卡地址并不能复现这些规则。如果同一个服务器下某个名字在 Windows 能解析、在发行版里不能,先比后缀的处理方式,再去怪隧道。
用名字来测,而不是用包:getent hosts sensor-access0.corp.example 会走完整的解析器栈,而 ping 可能对着缓存地址或字面地址成功。然后在断开再重连之后重测一遍,因为一个只生效一次、恢复时又被重新生成的设置从来没有被修好。把之前的内容存下来,并记下那台机器上这条路径归哪个组件所有,这样下一次改动才能从证据开始。