云服务器 DNS 解析异常?从 dig 到 resolv.conf 的排查顺序
业务突然连不上外部域名,ping 报 Name or service not known,curl 报 Could not resolve host,应用日志里一堆 DNS 超时——这类问题往往不是“网断了”,而是解析链路某一步坏了。下面按从现象到配置的顺序排查,命令在 EulerOS、CentOS 7+/8、Ubuntu 20.04+ 上通用;个别发行版若未装 bind-utils/dnsutils,先安装再使用 dig。
一、先分清:是 DNS 问题,还是别的连通性干扰
先用“IP 直连”和“域名访问”对照,避免一上来就改 DNS:
# 用已知公网 IP 测连通性(示例 IP 请换成你确认可达的地址)
ping -c 3 1.1.1.1
curl -I --connect-timeout 3 https://1.1.1.1
# 再用域名
ping -c 3 example.com
curl -I --connect-timeout 3 https://example.com
判断要点:
- 是否 DNS 异常,以
getent/dig为准,不要单凭 ping/HTTPS 下结论; - IP 通、域名解析失败:优先查 DNS(本机配置、上游 53、hosts/nsswitch);
- ping IP 失败:许多云环境禁用 ICMP,只能说明“探活失败”,不能直接判定整机网络不通;可改用对 IP 的 TCP 连通性测试(如
nc -vz <IP> 443)作辅助; curl https://<IP>失败:常受证书主机名、SNI、虚拟主机影响,也不足以证明出口全断;- 域名已能解析但 HTTPS/业务仍失败:多半是证书、端口或后端问题,不属于本文范围。
二、用 dig 分清:解析失败、解析错误,还是上游超时
dig 直接问 DNS,绕过 /etc/hosts 和 nsswitch;getent 走系统完整解析路径。两者对照最省事:
# dig 默认查 A;去掉 +short 才能看到 status / rcode
dig example.com
dig example.com @8.8.8.8
# getent 含 nsswitch、/etc/hosts
getent hosts example.com
关注应答头部的 status:(即 rcode)和是否超时:
| 现象 | 含义 | 下一步 |
|---|---|---|
status: NOERROR 且有 ANSWER |
解析成功 | 若业务仍异常,核对 IP 是否符合预期、是否被 hosts 覆盖 |
status: NXDOMAIN |
域名在权威侧不存在(或 search 后缀拼错) | 核对域名拼写、search/domain 后缀 |
status: SERVFAIL / REFUSED |
上游故障、拒绝递归或配置不当 | 换测另一个 nameserver,查上游与安全组 |
connection timed out; no servers could be reached |
UDP/TCP 53 到上游不可达 | 先查网络与防火墙,不要急着改域名 |
再压一下超时参数,避免默认可重试时间掩盖问题:
dig example.com +time=2 +tries=1
dig example.com @100.125.1.250 +time=2 +tries=1
三种常见对照结果:
dig @公网DNS正常,本机dig/getent失败:本机 DNS 配置或本地解析器(如systemd-resolved)有问题;- 两边都超时或 SERVFAIL:出口网络、安全组或上游 DNS 不可达/异常;
- 能解析但 IP 不对:优先查
/etc/hosts、内网 DNS 策略或缓存了旧记录。
说明:用 8.8.8.8 等公网 DNS 做对照时,只用于排查“上游通不通、权威是否正常”,不要把它当成华为云上的默认长期配置(见第六节)。
三、看系统实际在用哪几个 DNS
核心入口仍是 /etc/resolv.conf:
cat /etc/resolv.conf
ls -l /etc/resolv.conf
关注:
nameserver:glibc 解析器通常最多生效前三个(MAXNS),按书写顺序查询;search/domain:短主机名会自动补后缀,写错会出现“莫名其妙解析到内网名”或 NXDOMAIN;options timeout:n attempts:n:客户端超时与重试。
很多发行版里该文件是符号链接,由 systemd-resolved 或 NetworkManager 维护,直接手改常被覆盖:
# 常见指向示例
# ../run/systemd/resolve/stub-resolv.conf → stub 127.0.0.53
# /run/NetworkManager/resolv.conf
# ../run/systemd/resolve/resolv.conf → 列出上游(无 stub)
若是 stub(nameserver 127.0.0.53),真正的上游要看 resolved:
resolvectl status
# 较旧系统可用:systemd-resolve --status
看每个链路的 DNS Servers、Current DNS Server、DNS Domain,确认是否为当前区域预期的内网 DNS。
四、逐个验证 nameserver 是否可达
对配置里的每一个 DNS 做直连查询(把地址换成你机器 resolv.conf / resolvectl 里实际的值):
# 示例:华为云部分区域常见内网 DNS 之一为 100.125.1.250
# 第二地址因区域而异,以官方「内网 DNS 地址」表为准,不要照抄别的区域
dig @100.125.1.250 example.com +time=2 +tries=1
dig @8.8.8.8 example.com +time=2 +tries=1
关于端口探测:
# TCP 53(部分环境会强制 TCP)
nc -vz 100.125.1.250 53
# UDP 53:无连接握手,nc 成功只能说明“发出去了”,不能单凭它断定 DNS 正常
nc -vzu 100.125.1.250 53
更可靠的仍是看 dig 是否在超时内返回明确 rcode。
常见卡点:
- 安全组 / 网络 ACL:出方向未放行 UDP 53(部分场景还需 TCP 53);
- 本机防火墙:
firewall-cmd --list-all或iptables -S/nft list ruleset是否拦了 53; - 写了错误区域的内网 DNS:包可能发出,但得不到合法/预期应答;
- 只配了 IPv6 DNS:机器没有可用 IPv6 出口时,表现为间歇失败。
华为云场景优先使用当前区域 VPC 内网 DNS(官方表中许多区域第一地址为 100.125.1.250,第二地址因区域不同,例如华北-北京四为 100.125.129.250,华东-上海一为 100.125.64.250 等,以 华为云 DNS FAQ 为准)。内网 DNS 可解析 VPC 内网域名,并便于访问 OBS、SMN 等云服务的内网地址;随意改成纯公网 DNS,可能导致云服务解析到公网 IP、产生额外公网流量,并失去内网域名能力。
五、排除 /etc/hosts 和 nsswitch 的干扰
getent 失败但 dig @DNS 成功时,多半卡在本地名字服务开关:
grep -E 'hosts:' /etc/nsswitch.conf
# 常见:hosts: files dns myhostname
cat /etc/hosts
files在dns前是正常顺序,但/etc/hosts若写了错误的example.com,会一直用错 IP;- 误删
dns关键字后,系统只查 hosts,外部域名全挂; - 容器或 chroot 有时挂载了残缺的
nsswitch.conf,表现类似。
对照验证:
dig example.com +short # 不经 nsswitch
getent ahostsv4 example.com # 走完整本地解析路径
六、清理缓存,并正确改配置(避免被冲掉)
systemd-resolved 有本地缓存:
# 适用:已启用 systemd-resolved 的系统
resolvectl statistics
sudo resolvectl flush-caches
resolvectl query example.com
若使用 nscd / dnsmasq:
# 仅在对应服务确实存在时执行
sudo systemctl restart nscd 2>/dev/null
sudo systemctl restart dnsmasq 2>/dev/null
不同运行时或依赖库可能缓存解析结果;系统 DNS 改完后,是否要重启取决于该运行时的配置与缓存策略,先按文档核对,不要默认“必须重启”。
不要直接 echo 'nameserver ...' > /etc/resolv.conf 当作长期方案:DHCP 续租或 NetworkManager/systemd-resolved 一刷新就会丢。也不要在未确认区域地址前,盲目把公网 DNS 写成唯一上游。
变更前先备份现有配置(如 resolv.conf、netplan/NM 连接),并确认控制台 VNC 等恢复通道可用:nmcli con up、netplan apply 或重启网络服务都可能短暂中断 SSH。
CentOS / EulerOS(NetworkManager)示例:
nmcli con show
# 将 DNS 换成「当前区域」官方内网 DNS;下面仅为华北-北京四常见组合示例
sudo nmcli con mod '<连接名>' ipv4.dns "100.125.1.250 100.125.129.250"
sudo nmcli con mod '<连接名>' ipv4.ignore-auto-dns yes
sudo nmcli con up '<连接名>'
也可在 VPC 控制台改子网 DNS,再让 ECS 重新获取 DHCP(重启或按官方文档用 dhclient)。注意:子网级修改会影响该子网内多台实例,影响面大于单机 NM/netplan;dhclient -r 可能断开非 VNC 的远程会话,官网建议必要时改用 VNC。两种路径各有适用场景,按影响范围选择,不要默认“改子网更稳妥”。
Ubuntu(netplan + systemd-resolved)示例:
仅写 nameservers 时,DHCP 下发的 DNS 仍可能被并入。若意图只用下面列出的地址,且当前 netplan/渲染器支持,再加 dhcp4-overrides: use-dns: false(不支持时勿硬加)。下列地址为华北-北京四常见内网 DNS,其他区域请换成官方表中的对应值:
# /etc/netplan/01-netcfg.yaml 片段;网卡名按实机调整
network:
version: 2
ethernets:
eth0:
dhcp4: true
dhcp4-overrides:
use-dns: false
nameservers:
addresses: [100.125.1.250, 100.125.129.250]
# 优先试 netplan try(超时可自动回滚;部分精简环境或旧版本可能没有)
sudo netplan try
# 确认无误后再:
sudo netplan apply
resolvectl status
cat /etc/resolv.conf
dig example.com +time=2 +tries=1
改完用 resolvectl/cat 与 dig/getent 双重确认,再观察业务是否恢复。
七、监控和预防
- 定时探测:
dig @当前DNS 一个稳定域名 +time=2 +tries=1,对超时或非 NOERROR 告警,比等业务报错更早发现。 - 至少配置两个 nameserver,避免单点;华为云上优先同区域两个内网 DNS,而不是“内网 + 随意公网”凑数。
- 镜像与云初始化脚本里按区域固化 DNS,新机器不要依赖“碰巧 DHCP 给对了”。
- 容器场景:Pod/容器 DNS 常来自集群 CoreDNS 或
--dns,宿主机正常不代表容器正常,要在容器内再跑dig/getent。
小结
排查顺序可以记成一句话:先用 getent/dig 确认是不是解析问题,再用 dig 看清超时与 rcode,接着核对 resolv.conf/resolvectl 的实际上游,逐个验证 53,然后排除 hosts/nsswitch 与本地缓存,最后按发行版用 NetworkManager、netplan,或在清楚影响面后调整 VPC 子网 DNS——不要盲目覆盖 /etc/resolv.conf,也不要随手换成公网 DNS。常见落点包括上游 53 不通、配置被 DHCP 覆盖、hosts/search 写错、用了错误区域的内网 DNS;按顺序过一遍,有助于较快定位。
- 点赞
- 收藏
- 关注作者
评论(0)