
前几天同事给我发消息说服务器域名解析不通ping 外网 IP 是通的ping 域名却一直卡住。他贴出/etc/resolv.conf的内容里面有这样一行nameserver 127.0.1.1。他问我这个地址很眼熟可本机好像没装什么 DNS 服务是不是被入侵了我告诉他先别急着怀疑安全这个127.0.1.1在 Linux 网络配置里已经坑过很多人了。它跟127.0.0.1一样属于回环地址而它的出现往往意味着 DNS 配置链条出了问题——要么是系统管理工具生成了它但没有配套的解析服务在跑要么是某次手动改配置的残局。这篇文章我就把这个地址彻底讲透并且把不同 Linux 环境下如何真正设置 nameserver的几条路挨个走一遍适合所有遇到过 resolv.conf 被改乱、DNS 解析异常的读者。1. 一场由 127.0.1.1 引发的 DNS 事故很多人第一次注意到127.0.1.1时脑子里会冒出一堆问号127.0.0.1才是约定俗成的 localhost这个127.0.1.1是从哪冒出来的我当时排查同事那台服务器时也走过一段弯路先把过程完整还原一遍你大概率会遇到一模一样的场景。1.1 典型的故障表象解析卡住、文件诡异同事的服务器症状是这样的通过 IP 访问外部服务完全正常说明网络链路、路由、防火墙都没问题。通过域名访问时命令行长时间无响应偶尔报Temporary failure in name resolution。手动 ping 域名时先出现ping: example.com: Temporary failure in name resolution然后立刻退出。查看/etc/resolv.conf里面除了nameserver 127.0.1.1之外还有一两行search配置但没有任何公网 DNS。正常情况下如果服务器依赖网络上的 DNS 服务器那这个文件里应该是路由器地址、内网 DNS 地址或者公网解析地址。现在写了个回环地址在系统看来就是我可以向本机请求 DNS 解析但关键是本机到底有没有一个程序在 53 端口上监听这种请求验证方法不复杂。在终端执行ss -ulpn | grep :53如果输出结果里没有任何条目说明本机根本没有 UDP 53 端口的监听进程。这时nameserver 127.0.1.1就是个空配置系统发出的 DNS 请求相当于把消息放进了一个没人接收的信箱。同样地再查一下 TCP 53ss -tlnp | grep :53两条命令都没有输出问题定位基本就清楚了不是内核网络有问题不是防火墙拦截而是/etc/resolv.conf指向了一个不存在于本机的 DNS 服务。1.2 为什么这种配置会让排查更混乱这里有个很容易混淆的点127.0.1.1确实属于本机回环地址但它不等于本机就一定提供了 DNS 服务。回环地址的意思是你把包发给我我直接在本地处理不出网卡至于收到包的进程是谁、有没有完全是两码事。我见过有朋友在这种故障下尝试dig 127.0.1.1 example.com结果报connection timed out。他也尝试systemctl status dnsmasq发现 dnsmasq 根本没装。最终才确认是配置残局。还有更隐蔽的情况本机确实装了 dnsmasq 或 unbound但服务没启动或者启动后监听的不是127.0.1.1而是127.0.0.1。由于整个127.0.0.0/8段都属于回环网络服务如果只绑定了127.0.0.1:53对于发往127.0.1.1:53的请求内核并不认为它们是两个不同网络所以仍然会送达同一个 socket。但前提是服务真的在跑并且监听在回环地址上。所以在排查时不要只看/etc/resolv.conf写了什么必须把文件内容 端口监听 上游转发三个维度全部看一遍否则很容易得出错误结论。2. nameserver 127.0.1.1 到底是什么为什么系统偏爱它想彻底搞清楚127.0.1.1得先接受一个 Linux 里反直觉的事实回环地址并不只有127.0.0.1一个。整个127.0.0.0/8网段也就是127.x.x.x都用来表示本机回环。也就是说127.0.1.1、127.0.2.3、127.99.99.99只要是在这个范围里从协议栈角度讲全都发给本机自己行为跟127.0.0.1完全一样。2.1 它在 /etc/hosts 里的身份在 Debian、Ubuntu 这类发行版里你打开/etc/hosts通常会看到类似这样一行127.0.1.1 myhostname这是安装系统时写入的默认配置。为什么不用127.0.0.1因为 Debian 系的规范认为127.0.0.1 localhost应该只保留给 localhost 这个名称而真实主机名如果用127.0.0.0/8中的其他地址来表示不会和 localhost 的语义冲突。这样做的目的是保证本机主机名始终能解析回本机不会因为 DNS 配置问题导致主机名被解析到外网。如果你在某台机器上看到/etc/hosts里有127.0.1.1这一行并且/etc/resolv.conf里也出现nameserver 127.0.1.1那这两处不一定有直接关联但说明这台机器很可能是用 Debian 系工具链初始化的并且有人或者某个安装脚本在配置 DNS 时直接引用了这个地址。2.2 它成为 DNS 配置的真实来源那/etc/resolv.conf里的127.0.1.1到底是谁写的常见来源有三个第一个来源是 NetworkManager 的 dnsmasq 模式。在部分 Linux 发行版中NetworkManager 被配置为使用 dnsmasq 作为本机 DNS 缓存和转发器。它会生成/etc/resolv.conf把 nameserver 指向127.0.0.1或127.0.1.1具体取决于发行版补丁和配置文件。这台机器上如果将来你运行nmcli device status能看到 NetworkManager 在管理物理网卡那127.0.1.1极可能就是它的作品。第二个来源是手工配置遗留。有人用编辑器直接改/etc/resolv.conf随手写成了nameserver 127.0.1.1因为他想让本机自己解析 DNS。结果要么没安装对应的转发器要么装好之后没启动于是留下了隐患。这种案例在刚接触 Linux 的开发者机器上特别多。第三个来源是第三方软件包。例如本地安装了某种 Dnsmasq 的分发版本安装脚本检测到系统没有专门配置 DNS 时会自作主张把/etc/resolv.conf改成127.0.1.1。这类脚本通常不检测 53 端口最终是否有进程在监听所以很容易产出这种半成品配置。2.3 本机有解析服务时它可能是合理配置说句公道话127.0.1.1并不总是坑。如果本机确实跑了一个监听在回环地址上的 DNS 转发器用于缓存和过滤那么把 nameserver 指向127.0.1.1就完全正常。关键是转发器本身要能继续访问上游 DNS并且上游配置正确。你可以用一行命令验证dig 127.0.1.1 example.com short如果这个命令能返回 IP 地址说明本机确实有服务在响应nameserver 配置没毛病。如果超时或者报错那就得按第一节的排查思路往下走了。3. 动手前先分清你的 Linux 用的是哪套 DNS 管理体系很多人改 resolv.conf 失败最核心的原因是没搞明白一件事/etc/resolv.conf在大多数现代 Linux 系统里已经不是用户直接编辑的配置文件而是某个管理工具动态生成的运行时文件。系统重启、网络重连甚至 DHCP 租约续期都可能让这个文件被重新生成。你手动改得再漂亮管理工具一刷新就打回原形。所以在修改之前先花两分钟确认你面前这台机器的 DNS 管理链条。3.1 查看 resolv.conf 到底是普通文件还是符号链接ls -l /etc/resolv.conf常见的输出有几种/etc/resolv.conf - /run/systemd/resolve/stub-resolv.conf说明 systemd-resolved 在管。/etc/resolv.conf - /run/NetworkManager/resolv.conf说明 NetworkManager 在管。/etc/resolv.conf - /etc/resolvconf/run/resolv.conf说明 resolvconf 工具链在管。普通文件要么这台系统没有启用 DNS 管理工具要么工具没有接管这个文件。如果输出里面包含-那后续任何直接修改/etc/resolv.conf的操作都是危险的你只是在修改符号链接指向的临时文件或者干脆打开的是一个运行时会覆盖的缓存文件。真正的配置入口应该在管理工具那一层。3.2 检查当前哪些 DNS 相关服务是活跃的我习惯用一串命令同时检查systemctl is-active systemd-resolved systemctl is-active NetworkManager systemctl is-active dnsmasq systemctl is-active systemd-networkd systemctl is-active resolvconf哪几个输出active哪几个就是当前真正拥有 DNS 配置话语权的进程。这里有一个特殊情况NetworkManager 和 systemd-resolved 可能同时 active这时它们之间有协作关系NetworkManager 会把上游 DNS 信息交给 systemd-resolved再由 systemd-resolved 生成 stub-resolv.conf。再看 53 端口ss -ulpn | grep :53如果看到/usr/sbin/dnsmasq或/usr/lib/systemd/systemd-resolved在监听就知道实际提供本地 DNS 解析服务的是谁了。3.3 用一张表格理清对应关系resolv.conf 指向管理工具推荐修改入口stub-resolv.confsystemd-resolved/etc/systemd/resolved.conf或链路级配置文件NetworkManager 生成文件NetworkManagernmcli或 NetworkManager 连接配置resolvconf 生成文件resolvconf/etc/resolvconf/resolv.conf.d/下文件普通文件且无活动管理服务无可以直接编辑但需保证不会被网络脚本覆盖如果不做这一步直接去改文件大概率会出现我当时改了没错为什么重启后又回去了的经典困惑。我每次帮人看 DNS 问题都会先让他们把这一行ls -l的输出发过来因为后面的解法完全不同。4. 常见桌面端的设置方法NetworkManager 与 systemd-resolved如果你用的是笔记本、台式机或者安装了图形界面的 Linux 工作站绝大多数情况下 DNS 管理被 NetworkManager 或 systemd-resolved 接管。这类环境下的正确做法是在连接配置层面设置 nameserver而不是去改 resolv.conf。4.1 NetworkManager用 nmcli 改连接配置先查看当前有哪些连接nmcli connection show你会看到类似Wired connection 1这样的连接名。然后针对这个连接设置 DNSnmcli connection modify Wired connection 1 ipv4.dns 114.114.114.114 223.5.5.5 nmcli connection modify Wired connection 1 ipv4.ignore-auto-dns yes nmcli connection up Wired connection 1第二行的ipv4.ignore-auto-dns yes特别关键。如果不加这一行DHCP 获取的 DNS 配置可能和手动设置同时存在甚至优先级高于你手动设置的。加上它之后NetworkManager 就不会把 DHCP 下发的 DNS 写进 resolv.conf而是完全使用你指定的地址。也可以同时配置搜索域nmcli connection modify Wired connection 1 ipv4.dns-search example.lan这一步对连接所做的修改会被持久化保存到 NetworkManager 的配置文件里下次开机、重连都会生效。这也是图形界面里IPv4 设置面板背后实际做的事情。如果你不想记命令直接在系统设置里找到了对应网卡的 DNS 配置把 DHCP 自动改成手动填入服务器地址效果相同。4.2 NetworkManager 的 dnsmasq 模式怎么处理如果/etc/NetworkManager/NetworkManager.conf里有这样一段[main] dnsdnsmasq说明 NetworkManager 把 DNS 解析工作外包给了本地的 dnsmasq 实例。这时即便你通过nmcli设置了 DNS最终写到 resolv.conf 里的仍然可能是127.0.1.1——因为 NetworkManager 认为本机 dnsmasq 会替你转发。问题在于 dnsmasq 上游配置可能没跟上或者 dnsmasq 服务异常。遇到这个情况我建议分清你的需求如果你只是想统一走公网 DNS可以保留 dnsmasq 模式但在/etc/NetworkManager/dnsmasq.d/local.conf里添加上游server114.114.114.114 server223.5.5.5然后重启 NetworkManagersudo systemctl restart NetworkManager再cat /etc/resolv.conf你会发现 nameserver 还是 127.0.1.1但这次dig已经能正常解析了因为 dnsmasq 已经把它转发到上游。如果你希望 resolv.conf 里直接显示公网 IP不想经过本机 dnsmasq那就把dnsdnsmasq这一行移除或改成dnsdefault然后重启 NetworkManager。这个决定意味着本机不再有缓存和转发层每次解析直接请求外部 DNS延迟会稍高一点但对大多数场景完全够用。4.3 systemd-resolved 的全局配置如果第一节里的检查发现/etc/resolv.conf是指向stub-resolv.conf那真正掌握系统全局解析配置的是/etc/systemd/resolved.conf。编辑这个文件[Resolve] DNS114.114.114.114 223.5.5.5 FallbackDNS8.8.8.8 Domains~.保存后执行sudo systemctl restart systemd-resolved这里有两个细节容易踩坑。第一Domains~.的含义是把所有域名查询都交给该 DNS 服务器。如果不写这一行systemd-resolved 会把某些内部域名路由给其他配置的链路级 DNS这可能导致公网域名用公网 DNS、内网域名用内网 DNS 的同时部分没有落入任何域的查询走了不合适的服务器。加上~.后语义更直接。第二systemd-resolved 有全局配置和链路级配置两套体系。即使全局配置了 DNSNetworkManager 也可能为某个具体连接下发不同的链路级 DNS。查看实际效果resolvectl status输出里会列出每个网络接口的 DNS Servers那才是真正在每个链路上生效的配置。如果发现全局和链路级不一致以链路级优先。如果想移除某个接口上的链路级 DNS把它交给全局配置可以用resolvectl dns 例如接口名 然后重启 NetworkManager 或系统再看状态。5. 服务器端或纯静态配置Netplan、resolvconf 与直接改文件的正确姿势服务器场景通常没有图形界面也不一定跑 NetworkManager。Debian/Ubuntu 服务器常见的是 Netplan 加 systemd-networkd老系统可能用 resolvconf最小化安装的系统可能什么都没有直接读普通文件。下面分情况说。5.1 Netplan写一次配置全局生效如果你用的是 Ubuntu Server通常会有一个/etc/netplan/目录里面的 YAML 文件定义了网卡和 IP。要设置 DNS在对应网卡的nameservers段里配置network: version: 2 ethernets: enp1s0: dhcp4: true nameservers: addresses: - 114.114.114.114 - 223.5.5.5 search: - example.lan但这里有个陷阱如果dhcp4: trueDHCP 服务器通常也会下发 DNS。Netplan 不会自动让静态配置覆盖 DHCP 配置二者可能同时存在。更让人不解的是有时候你明明在nameservers.addresses里写了地址重启之后 resolv.conf 里看到的还是 DHCP 服务器指定的 DNS。解决方法是配合dhcp4-overridesnetwork: version: 2 ethernets: enp1s0: dhcp4: true dhcp4-overrides: use-dns: false use-domains: false nameservers: addresses: - 114.114.114.114 - 223.5.5.5use-dns: false的意思是即使从 DHCP 拿到了 DNS 服务器列表也不要使用它。use-domains: false则是不要采用 DHCP 下发的搜索域。改完配置后执行sudo netplan apply然后立刻验证cat /etc/resolv.conf resolvectl status在 Netplan 的环境下/etc/resolv.conf通常是指向 systemd-resolved 生成的文件的所以最终是否生效要看resolvectl status而不是只盯文件内容。5.2 resolvconf在生成链路上做手脚老派 Debian/Ubuntu 系统会安装resolvconf包它会把网络脚本提供的 DNS 信息收集起来重新生成/etc/resolv.conf。如果你检查发现系统里运行着resolvconf服务不要直接编辑/etc/resolv.conf因为它很快被覆盖。正确的做法是用resolvconf的持久化目录。常见的是/etc/resolvconf/resolv.conf.d/head每次生成时放在最前面的内容。/etc/resolvconf/resolv.conf.d/tail每次生成时放在最后面的内容。手动加入自定义 nameserver 的一个办法是编辑tailecho nameserver 114.114.114.114 | sudo tee -a /etc/resolvconf/resolv.conf.d/tail然后刷新sudo resolvconf -u看看/etc/resolv.conf你会看到生成的配置里带着你加的 nameserver。注意head和tail里通常已经有发行版给的默认内容不要删掉只追加即可。5.3 直接编辑普通文件的适用场景如果检查过后你确认/etc/resolv.conf是普通文件系统里没有活跃的 NetworkManager、systemd-resolved、Netplan 或 resolvconf那么直接编辑它才说得上真正改 DNS。sudo nano /etc/resolv.conf写入多行 nameservernameserver 114.114.114.114 nameserver 223.5.5.5保底的办法是顺手加一个搜索域search example.lan这种情况下配置很简单但也有需要注意的地方一旦以后安装了某个虚拟化工具、容器运行时或者网络管理服务它有可能会接管这个文件。为了保险可以记录当前文件是否被改动sudo chattr i /etc/resolv.confchattr i让文件变为不可修改相当于给文件加了写保护。这样即使某个工具试图覆盖它也会失败。但是这个方法要谨慎用如果系统确实有 NetworkManager 在管理加了chattr i后 NetworkManager 会报错且你的改动在系统重启后无法产生预期效果反而更难排查。所以我一般只建议在裸机、无管理服务的场景使用它。5.4 静态 IP 环境下的 DNS 与 DHCP 的优先级服务器如果配的是静态 IP那 DNS 通常也应该手动指定不依赖 DHCP。很多人在配置静态 IP 时只写了 IP、掩码、网关忽略 nameservers 字段结果系统只能靠 DHCP 或其他来源获取 DNS网络一变化就跟着断解析。检查静态配置是否完整可以看Netplan 的nameservers.addresses。传统/etc/network/interfaces里的dns-nameservers参数。NetworkManager 连接配置里ipv4.dns。我见过不少朋友在容器或者虚拟化环境里遇到容器能 ping 通 IP但域名解析失败最后发现是容器内 resolv.conf 指向了宿主机的某个服务而宿主机根本没有监听那个端口。这种跨环境的 DNS 问题基本排查思路还是回到第一节先确认 53 端口在哪监听再确认解析请求往哪走。6. 改完怎么验证以及反复被覆盖的根治思路配置改完之后最忌讳的就是只看/etc/resolv.conf里那几个 nameserver 是不是变了。文件变了不代表解析链路通。我见过的案例里有人把文件改成公网 DNS 后cat看得很满意结果一dig还是超时——原因就是系统里 dnsmasq 还在 53 端口抢地盘请求根本没走出本机。所以验证要分层。6.1 直达上游的验证方法先测系统当前默认解析getent hosts example.com这个命令会走 glibc 的解析流程跟ping走的是同一套逻辑。如果它返回 IP说明系统整体解析正常。然后测试 resolv.conf 里的每一台 named serverdig 114.114.114.114 example.com dig 223.5.5.5 example.com如果某一台服务器没有任何响应但你配置里填了它那这台服务器要么不可达要么 UDP/53 被中间网络阻断了。这种场景我建议直接换掉它而不是调试。再看缓存层是否生效resolvectl statistics能看到当前缓存命中次数、缓存大小等信息。如果系统用的是 systemd-resolved这个输出能告诉你缓存是否工作正常。6.2 追踪是谁在覆盖 resolv.conf如果你确认配置没写错但还是发现过一段时间/etc/resolv.conf里又变回127.0.1.1那就不是你再改一次能解决的而是要找到重置它的元凶。第一个做法是看文件修改时间和系统日志stat /etc/resolv.conf journalctl -u NetworkManager -u systemd-resolved --since 2 hours ago | grep -i resolv如果发现文件修改时间和 NetworkManager 或 systemd-resolved 的重启时间吻合基本就是管理工具在覆盖。第二个做法是使用 auditd 实时监控文件写入。安装 auditd 后sudo auditctl -w /etc/resolv.conf -p wa -k dnschange然后等文件被覆盖再查看审计日志sudo ausearch -k dnschange -ts recent日志里会写出是哪个进程、什么路径触发了对文件的写操作。这个方法能一锤定音地找到真凶在服务器反复被覆盖的场景里特别实用。不过 auditd 需要系统有内核审计支持多数主流发行版默认包含只是服务未必开了。6.3 本机有转发服务时的正规配置思路如果你的需求就是让解析走本机 dnsmasq 或 unbound那配置链应该这样设计先把本机转发器监听在127.0.0.1:53或127.0.1.1:53。确认转发器上游 DNS 配置正确。然后把/etc/resolv.conf或管理工具指向本机回环地址。最后验证本机转发器是否真的能解析外网域名。举个例子如果使用 dnsmasq可以在/etc/dnsmasq.conf里写listen-address127.0.0.1 server114.114.114.114 server223.5.5.5 no-resolvno-resolv告诉 dnsmasq 不要再读取/etc/resolv.conf里的 nameserver避免形成本机查本机的循环。这点特别关键如果不写dnsmasq 默认自己会去读 resolv.conf 找上游而 resolv.conf 又指向 dnsmasq 自己就死循环了。启动后检查一遍systemctl restart dnsmasq ss -ulpn | grep :53 dig 127.0.0.1 example.com这时候即使你在 resolv.conf 里保留nameserver 127.0.1.1解析也是正常的因为请求到了同一个回环段的服务上。6.4 把反复覆盖问题从根上解决最后一句话有点反直觉但很管用如果你不想让某个工具覆盖 resolv.conf你要做的不是去对抗它而是在它支持的配置入口里写上你真正想要的 nameserver。NetworkManager 管的就去改连接配置。systemd-resolved 管的就去改/etc/systemd/resolved.conf。resolvconf 管的就去改head或tail。Netplan 管的就去改 YAML。只要在正确的入口配置了文件内容被反复刷新也无所谓因为每次刷新出来的都是你想要的内容。这也是根治的真正含义。我在实际排障时还遇到过一个特殊场景容器环境。容器里的/etc/resolv.conf经常由容器引擎动态挂载指向宿主机的一个内置 DNS 服务。如果你在容器里手动改这个文件一旦容器重建配置就丢。这类问题的解法是在容器编排配置里指定dns选项让容器引擎在创建容器时就把正确的 nameserver 写进去而不是在容器运行后手动改。思路和你现在遇到的问题一样找到配置真正该落的那一层别在生成结果上反复折腾。我自己处理这类问题时最深的体会是看到一个诡异的 nameserver 地址时别急着删、别急着改先在系统里跑三条命令——ls -l /etc/resolv.conf、ss -ulpn | grep :53、resolvectl status把配置的来龙去脉搞清楚再动手。这样虽然看起来多花了半分钟但能省掉后面反复失败的几个小时。