服务器要自主完成域名解析,靠的是“本机解析器加递归DNS”接力:应用先问操作系统,操作系统按 nsswitch.conf 查 hosts 和缓存,必要时把查询交给递归解析器,递归解析器从根、顶级域到权威服务器逐级取回 A/AAAA/CNAME 等记录,再按 TTL 缓存并返回。
服务器自主解析域名到底是谁在干活?
服务器不会凭空知道 api.example.com 对应哪个 IP,它更像一个谨慎的信使,先翻自己的小本本,再决定要不要打电话问上游。
从 getaddrinfo() 到 DNS 报文:一次解析的完整调用链
应用通常调用 getaddrinfo(),而不是直接发 DNS 包,接下来发生的事,按顺序大致如下:
- 应用发起解析请求,
curl https://example.com、ping example.com。 - 系统读取
/etc/nsswitch.conf,看名称服务顺序,常见配置是hosts: files dns。 files命中/etc/hosts,直接返回 IP,不再发 DNS 查询。- 如果没命中,glibc 的 resolver 读取
/etc/resolv.conf,拿到nameserver、search、options timeout:2 attempts:2等参数。 - 服务器向
nameserver发 UDP 53 查询,响应被截断时,再改用 TCP 53。 - 如果启用 DoT 或 DoH,端口会变为 853 或 443,但解析逻辑不变。
nameserver是本地systemd-resolved的0.0.53,它会先查缓存,再决定转发还是递归。- 递归解析器查根提示,根返回顶级域,顶级域返回权威服务器,权威服务器返回最终记录。
- 遇到 CNAME 链,递归解析器继续追,直到拿到 A 或 AAAA 记录。
- 结果按 TTL 缓存,TTL 到期后重新查询。
据 IANA 公开资料,根服务器系统由 13 个根服务器标识组成,据 ICANN 公开资料,这些根服务器通过 Anycast 在多地部署,服务器实际访问的是最近或路由最优的实例,不是固定一台机器。
本地 hosts 和缓存先于递归查询
很多“解析慢”并非递归慢,而是本地顺序没管好,可以按下面顺序排查:
| 顺序 | 数据源 | 典型位置或命令 |
|---|---|---|
| 1 | 应用缓存 | 浏览器、Java、Go 自带缓存 |
| 2 | /etc/hosts | cat /etc/hosts |
| 3 | NSS 缓存 | nscd、systemd-resolved |
| 4 | 本地 DNS 缓存 | dnsmasq、Unbound、BIND |
| 5 | 上游递归 | 8.8.8、5.5.5
等 |
| 6 | 权威查询 | 根、顶级域、权威服务器 |
据统计,多数服务器查询在本地缓存命中后,无需再发递归请求。
Linux服务器如何配置本地DNS缓存?systemd-resolved、nscd与BIND场景对比
在 Linux 服务器上,本地缓存能明显减少跨地域查询和上游压力,选哪套方案,要看你是单机、容器宿主还是自建递归。
systemd-resolved 快速启用
适合多数现代 Linux 发行版,操作路径如下:
- 启用服务:
sudo systemctl enable --now systemd-resolved - 查看状态:
resolvectl status - 查询测试:
resolvectl query example.com - 检查 stub 文件:
ls -l /etc/resolv.conf - 常见结果:
/etc/resolv.conf指向/run/systemd/resolve/stub-resolv.conf - 清缓存:
resolvectl flush-caches
它的优点是开箱即用,支持 DNSSEC 验证和 DoT,缺点是配置分散,排错时要同时看 /etc/systemd/resolved.conf、resolvectl 和上游 DNS。
dnsmasq 或 Unbound 做本地缓存和递归
dnsmasq 轻量,适合小规模服务器和容器宿主,Unbound 更偏递归解析器,适合希望自主查询根、顶级域和权威服务器的场景。
以 Unbound 为例,典型配置如下:
- 安装:
sudo apt install unbound - 编辑
/etc/unbound/unbound.conf.d/recursive.conf - 核心项包括:
interface: 127.0.0.1access-control: 127.0.0.0/8 allowroot-hints: "/var/lib/unbound/root.hints"qname-minimisation: yesharden-dnssec-stripped: yes
- 检查配置:
sudo unbound-checkconf - 重启服务:
sudo systemctl restart unbound - 测试查询:
dig @127.0.0.1 example.com
dnsmasq 常配合 server=223.5.5.5 做转发缓存,配置项包括 listen-address=127.0.0.1、bind-interfaces、cache-size=10000,改完执行 sudo systemctl restart dnsmasq,再用 dig @127.0.0.1 example.com 验证。
BIND 自建递归解析适合谁
BIND 功能全,适合已经有 DNS 运维经验的团队,关键配置在 named.conf:
listen-on { 127.0.0.1; };allow-recursion { 127.0.0.1; localnets; };recursion yes;dnssec-validation auto;- 根区域:
zone "." { type hint; file "/etc/bind/db.root"; };
改完执行 named-checkconf,再 rndc reload,业内专家指出,递归解析器最怕开放递归,必须限制

allow-recursion,否则容易被利用做放大攻击。
| 方案 | 缓存 | 递归 | 加密 | 适用场景 | 运维成本 |
|---|---|---|---|---|---|
| systemd-resolved | 支持 | 有限 | DoT | 单机、桌面、常见服务器 | 低 |
| dnsmasq | 支持 | 转发为主 | 有限 | 小规模、容器宿主 | 低 |
| Unbound | 支持 | 支持 | DoT | 自建递归、隐私要求高 | 中 |
| BIND | 支持 | 支持 | 有限 | 专业 DNS 团队 | 高 |
云服务器域名解析流程和公网DNS有啥区别?自建递归的成本与地域延迟
云服务器通常拿到一组内网 DNS 地址,再转发到公网递归,公网 DNS 如 8.8.8、1.1.1、5.5.5,直接对外提供递归服务,两者差别在于查询路径、可控性和延迟。
云服务器默认 DNS 怎么查
- 查看
/etc/resolv.conf - 查看
resolvectl status - 查看 NetworkManager:
nmcli dev show | grep DNS - 查看 DHCP 租约:
cat /var/lib/dhcp/dhclient.leases - 测试上游:
dig @内网DNS example.com - 测试公网:
dig @223.5.5.5 example.com
云内 DNS 往往更近,但可能受 VPC、安全组和私网解析影响,公网 DNS 覆盖广,却可能跨地域绕路。
自建递归解析器会不会更省钱
有人问“自建DNS服务器成本高吗”,软件本身免费,成本在别处:
- 公网 IP 和带宽费用。
- DDoS 防护和流量清洗。
- 多地域部署成本。
- 根提示、DNSSEC 信任锚更新。
- 值班和故障排查人力。
小团队用本地缓存加可靠上游更划算,大型业务才考虑自建递归加 Anycast,行业共识认为,缓存命中率决定解析延迟,TTL 太短会增加上游压力。
北京服务器域名解析延迟怎么优化
如果服务器在北京,访问广州或海外递归可能增加往返时间,优化思路:
- 启用本地
systemd-resolved或dnsmasq缓存。 - 选择就近递归,例如华北地域优先用本地云 DNS。
- 对核心域名设置合理 TTL,避免过短。
- 用
dig +stats看 Query time。 - 用
tcpdump -ni any port 53观察是否反复查询。 - 容器环境注意
ndots和 search 域,减少无效查询。
服务器域名解析失败怎么排查?从本地缓存到递归查询逐层定位

别一上来就改 /etc/resolv.conf,按层查,最快。
- 应用层:
getent hosts example.com,看 NSS 返回什么。 - 本地 hosts:
cat /etc/hosts,确认没写错。 - 本地解析器:
resolvectl query example.com。 - 直接问本地缓存:
dig @127.0.0.1 example.com。 - 直接问上游:
dig @223.5.5.5 example.com。 - 追整个路径:
dig +trace example.com。 - 检查端口:
ss -lunp | grep :53,ss -ltnp | grep :53。 - 抓包:
tcpdump -ni any port 53 -nn。 - 看防火墙:
iptables -L -n、nft list ruleset。 - 看 SELinux 或 AppArmor 是否拦截。
| 现象 | 可能原因 | 验证命令 |
|---|---|---|
| timeout | 上游不可达、防火墙拦截 | dig @8.8.8.8 example.com |
| SERVFAIL | DNSSEC 失败、递归失败 | dig +cd @127.0.0.1 example.com |
| NXDOMAIN | 域名不存在、权威配置错 | dig NS example.com |
| REFUSED | 递归未授权 | 检查 allow-recursion |
| 旧 IP | TTL 缓存未过期 | resolvectl flush-caches、rndc flush |
| 容器内失败 | ndots、search 域问题 | cat /etc/resolv.conf |
一句话收束:服务器自主解析的本质,是把“先问谁、缓存多久、失败去哪查”三件事管清楚,管好本地解析器和递归路径,域名解析就从黑盒变成可验证的链路。
服务器自主完成域名解析流程Q&A
服务器能完全不依赖外部DNS吗?
不能,除非所有名称都写在 /etc/hosts 或由内部权威服务器覆盖,根和顶级域查询仍需外部递归,内网可以部署私有根或拆分视图,但公网域名解析仍要向上游或权威查询。
服务器域名解析失败怎么排查最快?
先跑 getent hosts example.com,区分应用和 NSS,再跑 dig @127.0.0.1 example.com,看本地解析器,最后跑 dig @上游DNS example.com 和 dig +trace example.com,定位是缓存、递归还是权威问题。
自建DNS服务器成本高吗?
软件许可通常为零,主要成本是公网 IP、带宽、DDoS 防护、多地域部署和运维人力,单机或小规模场景,用 systemd-resolved、dnsmasq 做缓存更实际,自建递归解析器需要持续更新根提示和 DNSSEC 信任锚,并限制开放递归。
