服务器DNS解析失败怎么办

结论: 服务器 DNS 解析失败先执行 dig 域名 +trace 与 curl -v,判断是"域名解析不出 IP"还是"解析成功但连不上"。本地侧依次检查 /etc/resolv.conf、systemd-resolved 状态、53 端口 UDP/TCP 是否放行;权威侧核查域名状态(serverHold/clientHold)、NS 记录与 DNSSEC 是否验证失败,必要时更换公共 DNS(223.5.5.5 / 119.29.29.29 / 8.8.8.8)。

引言:DNS 一挂,全站报错

DNS(Domain Name System,域名系统)是服务器对外通信的第一跳。它一旦失效,表现极具迷惑性:ping 域名失败、yum/apt 无法更新、Nginx 反向代理报 502、应用日志刷 Temporary failure in name resolution,甚至安装了付费 SSL 证书的业务也会因为无法完成 DNS-01 校验而续期失败。

难点在于,"网站打不开"和"DNS 解析失败"的症状几乎一样。因此排查的第一原则是先做分区举证:同一台机器上 ping 114.114.114.114 能通说明网络正常、ping www.baidu.com 不通才是解析层问题。这一步只要 10 秒,却能避免把接下来半小时浪费在错误的方向上。

另一类常见场景是"部分失败":本机解析正常但从外网访问异常,或者某个运营商网络下解析到旧 IP。这类问题通常出在权威 DNS、TTL 缓存与递归 DNS 的 LDNS 缓存上,排查重心要从本机移向域名侧。

第一步:分清"解析不了"还是"连不上"

结论: 用三条命令做分区:能 ping 通公网 IP、不能 ping 通域名 → DNS 问题;两者都不通 → 网络/路由问题;域名能解析但 HTTP 报错 → 是应用层问题。

DNS 解析链路上的四个角色

  1. 本地解析器:/etc/resolv.conf 里配置的 DNS 服务器地址,由 glibc 或 systemd-resolved 调用。
  2. 递归 DNS(Local DNS):运营商或公共 DNS,负责替你向各级权威服务器迭代查询,并缓存结果。
  3. 权威 DNS:域名注册/托管商处设置的 NS 记录指向的服务器,保存域名真正的解析记录。
  4. 本机缓存:nscd、systemd-resolved、dnsmasq、Java JVM 自身缓存等,可能造成"改了记录不生效"。

症状与归属对照表

现象可能的故障层快速验证方式
ping 8.8.8.8 通,ping www.baidu.com 不通本地解析器 / 递归 DNSdig www.baidu.com +short
Temporary failure in name resolutionresolv.conf 错误或 DNS 不可达cat /etc/resolv.conf、systemctl status systemd-resolved
connection timed out; no servers could be reached53 端口被阻断 / DNS 服务器故障dig +tcp @223.5.5.5 www.baidu.com
SERVFAIL权威 DNS 异常或 DNSSEC 校验失败dig +dnssec 域名、dig +trace 域名
NXDOMAIN记录不存在 / 域名状态被 holdwhois 域名 看 Status
本机正常、外网 DNS 查不到权威 DNS / NS 配置 / 本地 DNS 缓存用多地公共 DNS 交叉验证

第二步:用 dig / nslookup / host 精准取证

结论: dig 是 Linux 上信息量最大的工具,+trace 能看完整迭代链路;Windows Server 用 nslookup -debug 或 PowerShell 的 Resolve-DnsName。

安装:yum install bind-utils(RHEL 系)或 apt install dnsutils(Debian/Ubuntu)。

bash
# 1) 最简:只返回 IP,判断能否解析
dig www.example.com +short

# 2) 完整回应,重点看 status(NOERROR/SERVFAIL/NXDOMAIN)、ANSWER 段、Query time
dig www.example.com

# 3) 指定 DNS 服务器,区分"本机配置问题"还是"DNS 服务器问题"
dig @223.5.5.5 www.example.com +short
dig @119.29.29.29 www.example.com +short
dig @8.8.8.8 www.example.com +short
dig @114.114.114.114 www.example.com +short

# 4) 追踪从根到权威的完整链路,定位卡在哪一级
dig www.example.com +trace

# 5) 反向解析与邮件 MX 排查常用
dig -x 8.8.8.8 +short
dig example.com MX +short
dig example.com NS +short

输出解读要点:status: NOERROR 且 ANSWER ≥ 1 表示解析成功但可能是错的 IP;status: NXDOMAIN 表示记录不存在;status: SERVFAIL 表示服务器无法完成查询,多为权威侧异常或 DNSSEC 失败;Query time: 2003 msec 且反复超时,多半是 UDP 53 被丢。

Windows Server 侧:

powershell
Resolve-DnsName www.example.com -Server 223.5.5.5
Resolve-DnsName www.example.com -Type MX
ipconfig /displaydns            # 查看本机 DNS 缓存
ipconfig /flushdns              # 清空本机 DNS 缓存
nslookup -debug www.example.com

第三步:修正本机解析器配置

结论: Linux 的解析行为主要由 /etc/resolv.conf 决定;若启用 systemd-resolved,则该文件通常只是指向 127.0.0.53 的软链接,直接改文件会被覆盖,应改 resolved 配置。

先看一眼现状,再决定改哪里:

bash
ls -l /etc/resolv.conf
cat /etc/resolv.conf
systemctl status systemd-resolved
resolvectl status            # systemd-resolved 的实际生效 DNS

情况 A:使用 systemd-resolved(Ubuntu 18.04+、Debian 11+、RHEL 8+ 默认)

bash
# 修改 /etc/systemd/resolved.conf
sudo tee -a /etc/systemd/resolved.conf > /dev/null <<'EOF'
[Resolve]
DNS=223.5.5.5 119.29.29.29
FallbackDNS=114.114.114.114 8.8.8.8
Domains=~.
DNSSEC=allow-downgrade
Cache=yes
DNSStubListener=yes
EOF

sudo systemctl restart systemd-resolved
resolvectl status | head -30

情况 B:直接用 NetworkManager / 网卡配置文件

bash
# nmcli 方式(推荐,重启不丢)
nmcli con show --active
nmcli con mod "System eth0" ipv4.dns "223.5.5.5 119.29.29.29"
nmcli con mod "System eth0" ipv4.ignore-auto-dns yes
nmcli con up "System eth0"

# 静态配置:Debian/Ubuntu 的 /etc/network/interfaces
# dns-nameservers 223.5.5.5 119.29.29.29
# RHEL 系网卡配置:/etc/sysconfig/network-scripts/ifcfg-eth0
# DNS1=223.5.5.5
# DNS2=119.29.29.29

# 最后用 nmcli/netplan 校验
systemd-resolve --status 2>/dev/null || resolvectl status

给 /etc/resolv.conf 补充的关键参数:options timeout:2 attempts:3 rotate 可以让 DNS 查询在单台 DNS 服务器无响应时快速 failover,nameserver 最多写 3 条。若文件被云初始化(cloud-init)或 DHCP 反复覆盖,需要改 cloud-init 配置而非只改文件。

第四步:放行 53 端口(UDP 与 TCP 都要)

结论: DNS 同时使用 UDP 53 与 TCP 53:普通查询走 UDP,响应超过 512 字节、DNSSEC、区域传输走 TCP。只放行 UDP 会出现"小域名能解析、大响应或带 DNSSEC 的域名解析失败"。

bash
# firewalld 放行
firewall-cmd --permanent --add-service=dns
firewall-cmd --permanent --add-port=53/udp --add-port=53/tcp
firewall-cmd --reload

# iptables / nftables 放行
iptables -A OUTPUT -p udp --dport 53 -j ACCEPT
iptables -A OUTPUT -p udp --sport 53 -j ACCEPT
iptables -A OUTPUT -p tcp --dport 53 -j ACCEPT

# 联通性实测:分别用 UDP 与 TCP 查询
dig @223.5.5.5 www.example.com +short          # UDP
dig @223.5.5.5 www.example.com +short +tcp     # TCP
nc -vzu 223.5.5.5 53                           # UDP 端口联通性
nc -vz  223.5.5.5 53                           # TCP 端口联通性

# 抓包确认请求是否发出、是否收到回应
tcpdump -ni any port 53 -c 20 -vv

注意云服务器还有一层安全组:出站规则默认通常全放通,但如果被收窄过(例如只放行 80/443),53 端口必须显式加入。此外,部分运营商会对外部 DNS 的 UDP 查询做限制,此时改用 TCP 查询或运营商本地 DNS 反而更快。

第五步:清理缓存与更换公共 DNS

结论: 修改解析记录后不生效,九成是缓存问题:本机有 nscd/systemd-resolved/dnsmasq 缓存,外部有递归 DNS 的 TTL 缓存。清理本机缓存后再用多个公共 DNS 交叉验证。

bash
# systemd-resolved 清缓存
resolvectl flush-caches
resolvectl statistics | head -20      # 查看缓存命中情况

# nscd(Name Service Cache Daemon)清缓存
systemctl restart nscd
nscd -i hosts

# dnsmasq
systemctl restart dnsmasq

# 应用层也要注意:systemd 之外的缓存
service nginx reload                   # Nginx 的 resolver 缓存

公共 DNS 选择建议(截至 2026 年,以下地址长期稳定):

服务商IPv4特点
阿里 DNS223.5.5.5 / 223.6.6.6国内解析快,电商/cdn 场景表现好
DNSPod / 腾讯119.29.29.29国内节点多,稳定低延迟
114 DNS114.114.114.114老牌公共 DNS,运营商兼容性好
Google DNS8.8.8.8 / 8.8.4.4海外服务器首选,国内直连可能不稳定
Cloudflare1.1.1.1海外场景优异,支持 DoH/DoT

企业级建议是主备各配两个不同服务商,避免单点。国内业务服务器优先 223.5.5.5 + 119.29.29.29;海外业务服务器优先 8.8.8.8 + 1.1.1.1。

最后核查域名侧,这一步常被跳过:

bash
whois example.com | grep -iE 'status|expiry|name server'
dig example.com NS +short
dig example.com +dnssec +multiline | grep -iE 'RRSIG|flags|ad'

需重点确认:域名未过期;状态里没有 clientHold / serverHold(有则整套解析停摆);NS 记录指向的服务商与实际托管处一致;DNSSEC 若在注册商开启但托管侧未正确签名,会出现 SERVFAIL,此时应统一两边设置。

把 DNS 纳入日常监控

DNS 属于典型的"平时无人关注、一挂全站停摆"的依赖。服务器 DNS 解析失败的最佳处置是提前发现:给关键域名做分钟级拨测,监控项包括解析是否返回 NOERROR、返回的 IP 是否在预期集合内、各地递归 DNS 的响应耗时。

bash
# 轻量自查脚本:每 60 秒检测一次,失败追加到日志,可接入告警
cat > /usr/local/bin/dns_check.sh <<'EOF'
#!/bin/bash
DOMAIN="www.example.com"
EXPECT="223.5.5.5 119.29.29.29 8.8.8.8"
for NS in $EXPECT; do
  IP=$(dig +short +time=2 +tries=1 @$NS "$DOMAIN" | tail -n1)
  if [ -z "$IP" ]; then
    echo "$(date '+%F %T') FAIL $NS cannot resolve $DOMAIN" >> /var/log/dns_check.log
  else
    echo "$(date '+%F %T') OK $NS -> $IP" >> /var/log/dns_check.log
  fi
done
EOF
chmod +x /usr/local/bin/dns_check.sh
echo '* * * * * /usr/local/bin/dns_check.sh' | crontab -

生产环境建议再加三项:一是监控 /etc/resolv.conf 是否被 cloud-init 或 DHCP 覆盖(可用 auditd 或配置漂移检测);二是对域名到期日设置提前 30 天告警;三是把权威 DNS 的可用性也纳入拨测,避免只监控本机而漏掉域名侧故障。

常见误区 / 排错提示

  1. 直接改 /etc/resolv.conf 却不生效:该文件可能是 systemd-resolved 或 NetworkManager 管理的软链接,重启即回滚。应改 resolved.conf、nmcli 或 netplan/network-scripts 源文件。
  2. 只放行 UDP 53:DNSSEC、大响应、AXFR 走 TCP 53,仅放 UDP 会造成间歇性解析失败,且难以复现。
  3. 忽略 search / ndots 的影响:resolv.conf 中 options ndots:5 会让不带点的短域名先拼接搜索域查询,Kubernetes 集群内尤其容易踩坑,表现为解析慢而非失败。
  4. 把 NXDOMAIN 当成 DNS 服务器故障:NXDOMAIN 是权威服务器的正常答复,说明记录本身不存在或写错主机记录(如多写了一个 www),重点应查控制台记录。
  5. 改完记录立刻下结论:TTL 未过期前各地递归 DNS 仍返回旧值,应先用 dig @权威DNS 确认权威已生效,再等 TTL 过期或用多地工具交叉验证。