linux dns解析顺序由/etc/nsswitch.conf中hosts行配置控制,决定查询/etc/hosts、dns或其他源的优先级与流程。

Linux DNS解析顺序由谁控制
Linux系统里DNS解析顺序不是由/etc/resolv.conf单独决定的,真正起调度作用的是/etc/nsswitch.conf中hosts这一行的配置。它决定了当程序调用getaddrinfo()或gethostbyname()时,系统先查本地文件、再查DNS,还是反过来,甚至是否启用mDNS、LDAP等其他源。
修改nsswitch.conf中hosts行的关键规则
打开/etc/nsswitch.conf,找到形如hosts: files dns的行——这就是默认行为:先查/etc/hosts,再走DNS服务器。调整顺序就能改变优先级:
-
hosts: dns files→ 优先发起DNS查询,失败后才 fallback 到/etc/hosts(注意:部分老程序或glibc版本可能不完全遵守此顺序) -
hosts: files [NOTFOUND=return] dns→ 显式控制流程:若/etc/hosts中没找到,立刻返回,不继续查DNS(避免无谓延迟) -
hosts: files resolve [!UNAVAIL=return] dns→ 启用systemd-resolved(需已启用该服务),失败时跳过它直连DNS
⚠️ 注意:[NOTFOUND=return]这类动作修饰符只对前一个源生效;空格和方括号间不能有空格;改完无需重启,但已有进程的DNS缓存(如nscd)可能需手动清理。
为什么改了nsswitch.conf却没生效
常见失效原因不是配置写错,而是被更高优先级机制覆盖:
- 某些发行版(如Ubuntu 22.04+)默认启用
systemd-resolved,它会劫持/etc/resolv.conf为指向127.0.0.53的stub resolver,此时hosts: dns实际走的是systemd-resolved而非直连上游DNS -
nscd(Name Service Caching Daemon)正在运行:它缓存gethostbyname结果,修改nsswitch.conf后必须执行sudo systemctl restart nscd或sudo nscd -i hosts - 容器或chroot环境使用独立的
/etc/nsswitch.conf,宿主机修改不影响其内部行为 - 程序自己实现DNS逻辑(如curl加
--resolve、Java应用设sun.net.inetaddr.ttl)会绕过系统NSS机制
验证DNS解析路径是否按预期工作
别只靠ping或curl,它们可能被缓存或走自定义逻辑。用getent最直接:
getent hosts example.com
它严格按nsswitch.conf中hosts行定义的顺序和策略执行,并显示最终命中的来源(如/etc/hosts或DNS响应IP)。配合strace可进一步确认调用链:
strace -e trace=openat,connect getent hosts example.com 2>&1 | grep -E "(resolv|hosts|connect)"
真正难处理的是多源嵌套场景——比如files resolve dns中resolve本身又依赖/etc/resolv.conf,而后者又被NetworkManager动态覆盖。这种链式依赖,得一层层查systemctl status systemd-resolved、nmcli dev show、ls -l /etc/resolv.conf才能定位断点。











