同一个域名解析出三种结果,先弄清是谁在解析
开发环境里有一类让人抓狂的现象:终端里 curl 能通,浏览器打不开;宿主机上 dig 返回一个地址,容器里 curl 却连到另一个地址;断开隧道之后,某个域名依旧解析到旧的位置。这些现象的共同根因是:一台开发机上同时存在多个「解析者」,它们读取的配置不同、走的网络不同,答案自然不同。DNS 解析不一致的排查思路,就是先分清这次请求到底是谁在解析,再逐个用同一个域名对照。
本文只讨论解析层面的对照方法,不涉及具体服务商,命令在 macOS 与 Linux 上都适用,个别差异会单独标注。解析异常与出口 IP 如何影响 Claude Code、Cursor 那篇侧重现象与影响,这里侧重三处环境的对比和定位动作。
三个解析者各自读什么配置
先把三个常见解析者列出来,后面每个排查动作都围绕它们展开。
终端程序、dig 和系统解析器为什么结果不同
多数命令行程序通过系统的 getaddrinfo 调用解析,会遵循系统的解析顺序、hosts 文件和每个网络接口的 DNS 设置;而 dig、nslookup 是直接向某个 DNS 服务器发查询,不一定经过同一套逻辑。所以 dig 的结果和 curl 实际连到的地址不一致,并不稀奇。macOS 上可以用 scutil --dns 查看每个解析器的作用域,Linux 使用 systemd-resolved 时用 resolvectl status 查看按接口划分的 DNS 配置,再用 resolvectl query 域名 走系统解析器做一次对照。
浏览器的 DoH 为什么会绕开系统设置
主流浏览器提供「安全 DNS」或 DNS over HTTPS 选项,开启后浏览器会把解析请求用 HTTPS 发往它自己配置的服务,不再读取系统 DNS。结果是:终端里用公司内部解析的域名,在浏览器里解析不到;或者隧道推送的 DNS 对浏览器没有作用。判断办法很直接,在浏览器设置中查看安全 DNS 是否开启,临时关闭后重新测试同一个域名,现象消失就说明是它在起作用。
容器里的 resolv.conf 是怎么来的
容器有独立的网络命名空间。使用自定义网络的容器,/etc/resolv.conf 里通常是 127.0.0.11,这是 Docker 内置的解析服务,它再把外部域名的查询转发出去;而宿主机如果使用 systemd-resolved,/etc/resolv.conf 里常见的是只能在宿主机本机访问的 127.0.0.53,转发时需要使用实际的上游服务器地址。此外,公司隧道推送的内部 DNS 只存在于宿主机的网络接口上,容器不一定能走到。验证办法是用同一个域名分别在宿主机和容器里查询:
# 宿主机
resolvectl query example.internal
# 容器内(先确认容器里有 nslookup 或 getent)
docker exec -it 容器名 cat /etc/resolv.conf
docker exec -it 容器名 getent hosts example.internal
命令里的域名和容器名只是示例,请替换成你实际排查的对象。如果容器内解析失败而宿主机成功,可以在 Docker 守护进程配置或运行参数中显式指定可达的 DNS 服务器,而不是依赖继承宿主机配置。镜像拉取慢的问题和这里不同,可以看Docker Desktop 与 Colima 镜像拉取慢的排查。
一张对照表:现象、可能的解析者、第一步动作
| 现象 | 最可能的解析者 | 第一步动作 |
|---|---|---|
| curl 通,浏览器不通 | 浏览器 DoH 或浏览器自带代理 | 关闭安全 DNS 后复测同一域名 |
| dig 结果与 curl 实际连接地址不同 | dig 未走系统解析器 | 用 resolvectl query 或 scutil --dns 对照 |
| 宿主机通,容器内解析失败 | 容器的 DNS 配置与宿主机不同 | 检查容器 resolv.conf,显式指定 DNS |
| 内部域名只在隧道开启时可用 | 隧道推送的 DNS 仅作用于隧道接口 | 确认内部域名对应的解析器作用域 |
| 断开隧道后域名仍指向旧地址 | 系统或应用的解析缓存 | 清理系统缓存并完整重启相关应用 |
隧道与解析缓存:为什么断开之后问题还在
隧道客户端一般会在连接时修改系统 DNS 或增加按域名划分的解析规则,断开时再还原。现实里还原不完整的情况并不少见,另外还有两层缓存:系统解析缓存,以及应用自身缓存(浏览器、JVM、Node 进程都有各自的缓存逻辑)。排查时建议按下面的顺序做:
- 用
resolvectl query或dscacheutil -q host -a name 域名取一次系统解析结果,记录返回的地址。 - 清理系统解析缓存。macOS 常用的做法是刷新 mDNSResponder,Linux 使用 systemd-resolved 时执行
resolvectl flush-caches。 - 完整退出并重启出问题的应用,而不是仅仅关闭窗口。
- 仍不一致时,再对照 DNS 泄漏的成因,检查是否有部分请求没有按预期走解析通道。
如果你的开发环境需要在隧道和本地之间频繁切换,又不希望每次都手动检查解析配置,可以选择自带分流与 DNS 处理的客户端。NasaCode 在客户端侧处理开发场景下的解析与分流,减少本机、容器、隧道三处互相不一致的概率;具体效果建议按本文的对照表,用同一个域名各测一次再判断。
小结
解析不一致不是玄学,只是多个解析者各读各的配置。先确认谁在解析,再用同一个域名在宿主机、容器、隧道三处分别查询,最后处理缓存。排查命令的具体输出格式因系统版本而异,请以你机器上的实际返回为准。









