系统学习 故障排查学习路径:从方法论到系统、网络、数据库与 K8s

macos-dns-failed

macOS 系统 DNS 解析失败、VPN 分流异常的定位与修复

现象

浏览器提示“找不到服务器”“无法连接到服务器”,终端报 curl: (6) Could not resolve host、ping: cannot resolve example.com: Unknown host、nslookup 超时;但 dig example.com 或 dig @8.8.8.8 example.com 却能拿到结果。也可能是只有公司内网域名失败,公网域名正常,或者连接 VPN 后部分域名开始解析到错误地址。

dig、nslookup 直接向 DNS 服务器查询,不一定走 macOS 的系统解析器;浏览器、ping、curl 默认使用系统解析器,会经过 /etc/hosts、缓存、VPN 推送的 resolver 和搜索域。两者结果不同,说明问题在系统解析链路,而不是上游 DNS 完全不可用。

快速定位

先读系统当前使用的 resolver 和网络状态:

scutil --dns
scutil --nwi
scutil --proxy
dscacheutil -q host -a name example.com
cat /etc/hosts

scutil --dns 会按顺序列出 resolver #1、resolver #2 等,关注 nameserver、search domain、order、flags 和 reach。VPN 场景下通常能看到额外的 resolver;如果内网域名没有匹配的 domain 或 search domain,查询就会被送到公网 DNS。scutil --nwi 显示当前主接口和 DNS 标记,scutil --proxy 用于排除代理配置干扰。

再区分“系统解析器”和“直连 DNS”:

dscacheutil -q host -a name example.com
dig example.com
dig @8.8.8.8 example.com
dig +short example.com
nslookup example.com
ping -c 3 example.com
curl -v --max-time 10 https://example.com/

如果 dig @<DNS服务器> 成功而 dscacheutil 或 ping 失败,重点查系统 resolver、缓存、/etc/hosts 和 VPN;如果所有查询都超时,查网络、路由和防火墙。继续检查接口、路由和 DNS 配置:

ifconfig
netstat -rn -f inet
route -n get default
networksetup -listallnetworkservices
networksetup -getdnsservers "Wi-Fi"
networksetup -getsearchdomains "Wi-Fi"

服务名要按 listallnetworkservices 的实际输出填写,带空格的名称要加引号。最后看解析器日志和 DNS 流量:

/usr/bin/log show --last 5m --info --debug --style compact \
  --predicate 'process == "mDNSResponder"'
sudo tcpdump -D
sudo tcpdump -ni en0 -vvv 'port 53'

在 zsh 中 log 可能被同名内建命令占用,写 /usr/bin/log 可以避免参数错误。macOS 没有 Linux 的 any 伪接口,抓包前用 tcpdump -D 选择 Wi-Fi、有线或 utun* 的实际接口。

常见根因

  1. DHCP 下发的 DNS 服务器不可达、已下线或返回错误结果,路由器或上游 DNS 故障。
  2. VPN 分流配置不正确:内网域名没有对应的 search domain 或 resolver,查询被送到公网 DNS。
  3. VPN 断开后残留的 resolver、接口状态或缓存没有清理,导致解析继续走已经不存在的链路。
  4. 手动设置的 DNS 覆盖了 DHCP 或 VPN 下发的 DNS,或者多个网络服务同时活跃、优先级冲突。
  5. /etc/hosts 中存在错误的静态记录,或文件格式错误;系统解析器会优先使用它。
  6. 缓存了旧的失败结果或旧地址,网络切换、休眠唤醒后没有及时更新。
  7. 内网短名称缺少搜索域,应用只传主机名时无法补全为完整域名;改用 FQDN 往往能验证。
  8. IPv6 的 AAAA 记录可达性异常,部分应用没有正确回退到 IPv4。
  9. 公共 Wi-Fi 的强制门户、DNS 劫持、UDP 53 被拦截,或安全软件、内容过滤器接管 DNS。
  10. 浏览器启用了 DoH,或 iCloud 私密代理、代理自动配置(PAC)影响了解析和连接。
  11. 配置描述文件或 MDM 下发了 DNS 代理、内容过滤或限制,普通设置页看不到真实来源。
  12. 权威 DNS 或 DNSSEC 配置错误,只有特定域名失败。

修复

先清缓存并复验,排除旧结果:

sudo dscacheutil -flushcache
sudo killall -HUP mDNSResponder

这条命令只清缓存,不修复错误配置;执行后重新用 dscacheutil、ping 和浏览器验证,不要把它当成万能修复。

如果 DHCP 下发的 DNS 有问题,可以在“系统设置 > 网络 > 详细信息 > DNS”中临时指定可靠服务器,或用 networksetup 操作。恢复自动获取用 Empty:

sudo networksetup -setdnsservers "Wi-Fi" 1.1.1.1 8.8.8.8
sudo networksetup -setdnsservers "Wi-Fi" Empty

注意服务名必须是实际名称;对 VPN 接口手工设 DNS 通常不会持久,也不应覆盖 VPN 下发的内网 resolver。

VPN 场景先断开再重连,观察 scutil --dns 的 resolver 数量和顺序是否变化。只有内网域名失败时,用 VPN 提供的 DNS 直接查询验证:

dig @<VPN内网DNS> internal.example.com
dig internal.example.com
scutil --dns | grep -A 6 'resolver #'

如果直连 VPN DNS 成功而系统解析失败,说明分流或 search domain 没配对;应在 VPN 配置或服务端补上内网域名和搜索域,而不是把全局 DNS 改成内网服务器。内网短名称失败时改用完整域名,或在网络设置中增加搜索域:

sudo networksetup -setsearchdomains "Wi-Fi" example.com corp.example.com
sudo networksetup -setsearchdomains "Wi-Fi" Empty

/etc/hosts 只保留确有必要且格式正确的记录,修改后清缓存。不要手工编辑 /etc/resolv.conf,macOS 会由系统配置重新生成,手工修改容易在重启或网络切换后丢失。

怀疑 IPv6 时,用 dig AAAA example.com 和 ping6 测试;如果只有 IPv6 路径异常,先修路由器或隧道,临时关闭某个网络服务的 IPv6 只用于验证:

sudo networksetup -setv6off "Wi-Fi"
sudo networksetup -setv6automatic "Wi-Fi"

代理和隐私功能也要排除:scutil --proxy 查看系统代理,浏览器里检查 DoH 设置,临时关闭 iCloud 私密代理或内容过滤器复测。公共 Wi-Fi 先访问 http://captive.apple.com 确认是否被强制门户拦截。设备受 MDM 管理时,用 sudo profiles show -type configuration 查看 DNS 代理和内容过滤描述文件,联系管理员处理,不要自行删除描述文件。

如果只有某个域名失败而其他域名正常,按权威 DNS、DNSSEC 和域名配置排查,可参考站内的 DNS SERVFAIL 页面。修复后在当前网络、切换网络和 VPN 连接三种状态下分别复验,并观察缓存过期后的结果。

相关命令

参考链接

读完自测

合上页面,先回答,再展开对照。

  1. dig example.com 成功但 ping 和浏览器失败,说明什么?
  2. 连接 VPN 后只有内网域名解析失败,应该怎样定位?
  3. 刷新 DNS 缓存的正确命令是什么?它能解决哪些问题、不能解决哪些问题?
答案
  1. 说明上游 DNS 可能可达,但系统解析链路有问题。dig 直接查询 DNS 服务器,ping 和浏览器走系统解析器;应检查 scutil --dns 的 resolver 顺序、/etc/hosts、缓存、搜索域和 VPN 状态,再用 dscacheutil -q host 对照。
  2. 用 scutil --dns 看 VPN 是否下发了额外 resolver、search domain 和 order,用 dig @<VPN内网DNS> internal.example.com 直连验证,再和 dig internal.example.com 对比。若直连成功而系统解析失败,重点修 VPN 分流、内网域名匹配和搜索域,而不是把全局 DNS 改成内网服务器。
  3. 用 sudo dscacheutil -flushcache 和 sudo killall -HUP mDNSResponder 清除缓存。它能解决旧记录、网络切换后的陈旧结果,但不能修复错误的 DNS 服务器、VPN 分流、/etc/hosts 错误或上游故障;/etc/resolv.conf 不应手工编辑。
微信小程序码:扫码打开命令速查小程序

小程序版

微信扫码,随时查命令