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* 的实际接口。
/etc/hosts 中存在错误的静态记录,或文件格式错误;系统解析器会优先使用它。先清缓存并复验,排除旧结果:
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 连接三种状态下分别复验,并观察缓存过期后的结果。
合上页面,先回答,再展开对照。
dig example.com 成功但 ping 和浏览器失败,说明什么?dig 直接查询 DNS 服务器,ping 和浏览器走系统解析器;应检查 scutil --dns 的 resolver 顺序、/etc/hosts、缓存、搜索域和 VPN 状态,再用 dscacheutil -q host 对照。scutil --dns 看 VPN 是否下发了额外 resolver、search domain 和 order,用 dig @<VPN内网DNS> internal.example.com 直连验证,再和 dig internal.example.com 对比。若直连成功而系统解析失败,重点修 VPN 分流、内网域名匹配和搜索域,而不是把全局 DNS 改成内网服务器。sudo dscacheutil -flushcache 和 sudo killall -HUP mDNSResponder 清除缓存。它能解决旧记录、网络切换后的陈旧结果,但不能修复错误的 DNS 服务器、VPN 分流、/etc/hosts 错误或上游故障;/etc/resolv.conf 不应手工编辑。
小程序版
微信扫码,随时查命令