服务器明明能 ping 通 IP,网站却打不开、apt update 报 Temporary failure resolving、邮件发不出去——这些症状凑在一起,基本可以断定是 DNS(域名解析系统,把域名翻译成 IP 地址的服务)出了问题。本文就是为解决这类 DNS 解析失败而写的排查指南。更让人头疼的是:你明明已经把 /etc/resolv.conf 改成了公共解析地址,几分钟后再看,内容又被改了回去。
这种“改了又变回去”的现象,绝大多数是 resolv.conf 与 systemd-resolved 的冲突:你手工编辑的文件会被解析服务按自己的配置重新生成。本文帮你解决这个问题:先确认问题确实出在解析环节,再弄清谁在管理 resolv.conf,最后教你如何做不会被覆盖的持久化修复。整个过程用系统自带命令即可完成,大约 10 分钟。

第一步:确认问题在解析环节
DNS 失效的典型特征是“IP 通、域名不通”,先用两条命令把这个特征坐实,避免误判成网络中断:
ping -c 2 223.5.5.5
ping -c 2 www.example.com
第一条能通、第二条报 Name or service not known,说明网络链路正常、问题出在解析。接着做一个反向验证,绕过本机解析直接向公共服务器查询:
dig @223.5.5.5 www.example.com +short
如果这条命令能返回 IP,说明服务器到外网解析服务的 UDP 53 端口是通的,问题确定在本机解析配置;如果这条也超时,则要检查防火墙是否封了 53 端口,或者上游服务商是否限制了外部解析,排查方向完全不同。这一步的分辨直接决定后面修哪里,不要跳过。

第二步:弄清谁在管理 resolv.conf
cat /etc/resolv.conf 看内容只是开始,关键是看清这个文件的真实身份。执行这两条命令:
ls -l /etc/resolv.conf
systemctl status systemd-resolved --no-pager
如果 ls -l 显示 resolv.conf -> ../run/systemd/resolve/stub-resolv.conf 这样的箭头,说明它是 systemd-resolved 托管的软链接——你直接编辑它当然会被覆盖,因为它只是个指向运行时生成文件的指针。如果 systemd-resolved 状态是 active (running),这台机器的解析链路就是:应用程序 → 本地 stub 监听(127.0.0.53) → resolved 按自己的配置向上游查询。
还有一个细节值得注意:resolvectl status 的输出里,除了 Global 全局配置,还有每个网络接口的 Link 段。如果某个接口单独设置了 DNS Servers,解析请求会优先走接口级配置,全局配置反而不生效——这解释了很多人的疑惑:为什么改了全局配置却毫无反应。处理方法是执行 resolvectl revert 网卡名 清掉接口级覆盖,或者用 resolvectl dns 网卡名 上游IP 直接指定,让配置落到实际承担流量的那张网卡上。
[Resolve]
DNS=223.5.5.5 119.29.29.29
FallbackDNS=8.8.8.8
Domains=~
修改后执行 systemctl restart systemd-resolved,再用 resolvectl status 确认 Global 层的 DNS 已生效。此时上游解析器就是你指定的地址,resolv.conf 继续保持软链接状态即可,它指向的 stub 会正确转发。解析恢复正常后,如果网站访问速度仍不理想,可以继续排查 网站优化 层面的因素,解析只是链路的第一环。

第三步:选择不冲突的持久化方案
上面是“与 resolved 共存”的修法。但有些场景你不想用 systemd-resolved——比如服务器上跑着自建解析、或某些老软件对 stub 监听兼容不佳。这时可以彻底接管:停用服务并换成静态文件。
systemctl disable --now systemd-resolved
rm /etc/resolv.conf
echo "nameserver 223.5.5.5" > /etc/resolv.conf
echo "nameserver 119.29.29.29" >> /etc/resolv.conf
chattr +i /etc/resolv.conf
逐条解释:先停掉并禁用服务(防止它重启后重建软链接),再删掉软链接写入自己的静态配置,最后用 chattr +i 给文件加上不可修改属性作为保险。注意 chattr +i 是双刃剑——以后想改这个文件必须先 chattr -i 解锁,排查网络问题时如果发现 resolv.conf 改不动,先想到这个属性。
还有一种折中方案:保留 systemd-resolved 运行,但把 /etc/resolv.conf 从软链接换成普通静态文件(同样加 chattr +i)。这种模式下 resolved 仍在为本机 hostname 解析等服务,但应用的解析路径直接走你的静态配置。三种方案怎么选,取决于你是否需要 resolved 的附加能力(LLMNR、mDNS、按链路分流),纯服务器场景通常静态文件最省心。
无论选哪种,验证动作都一样:systemctl restart 相关服务后,跑 dig www.example.com +short 确认默认路径能解析,再 resolvectl status(如果还在用 resolved)核对上游地址。最后重启一次服务器再测一遍——很多“修好了”只存活到下次重启,那是因为 NetworkManager 或 DHCP 客户端也会参与 resolv.conf 的管理,这是本主题最常见的隐藏冲突源。如果你的服务器由 DHCP 分配网络配置,检查 /etc/dhcp/dhclient.conf 里的 supersede domain-name-servers 语句,它可以强制 DHCP 续约后仍使用你指定的解析地址;使用 NetworkManager 的系统则在对应连接配置里加 dns=none,让它彻底放弃接管 /etc/resolv.conf。把这条链路上的每个管理者都安顿好,配置才算真正稳定。

常见坑与排查清单
按故障出现频率,把 DNS 解析失败的高频原因排个序:
resolv.conf被 resolved 或 NetworkManager 覆盖(本文主线,出现最多)- 防火墙出站规则封了 UDP/TCP 53 端口,表现为
dig @8.8.8.8全部超时 /etc/nsswitch.conf中hosts行顺序异常,导致优先走了错误的解析模块/etc/hosts里残留了旧 IP 的硬编码记录,症状是“只有某个域名不对”- 应用自身缓存(如 Java 的 JVM DNS 缓存、Docker 内嵌解析)未刷新
排查时按这个顺序走,基本 10 分钟内能锁定原因。我们在 Hostease 处理服务器工单时,遇到解析类报障也是按这个顺序先分流,避免一上来就重装系统。特别提醒容器场景:宿主机修好后容器里仍然解析失败,多半是 Docker 的内嵌 DNS(127.0.0.11)在转发时用错了上游,重启 Docker 守护进程或检查其 dns 配置即可。
总结一下排查心法:先区分“IP 通、域名不通”,再确认 resolv.conf 的真实身份(软链接还是静态文件),然后顺着管理系统(resolved、NetworkManager、DHCP)找到配置源头去改,最后重启验证。直接编辑 /etc/resolv.conf 从来不是终点,明白谁在生成它才是。
如果你需要一台网络配置干净、可控性强的服务器环境,我们的建议是选择带完整管理权限的 VPS 主机(VPS,虚拟专用服务器,资源独享、root 权限完整),业务规模更大时可以考虑 独立服务器。更多服务器运维的实操指南,可以查看我们整理的 服务器性能 专题。如果你在实际操作中遇到本文未覆盖的解析异常,建议先抓 dig 的完整输出再求助,信息越完整定位越快。