DNS 解析排查顺序:从客户端到权威的 5 步定位法
先确认故障范围
拿到「域名解析不了」的反馈,第一步不是改配置,而是确认影响面。三件事同时做:
- 在故障机器上执行
curl -v --resolve example.com:443:1.2.3.4 https://example.com,绕过 DNS 直连 IP。能通说明问题在解析层,不通说明还有网络层问题。 - 在正常机器上解析同一域名,确认是单机问题还是全局问题。
- 记录故障时间点,后面查权威日志和缓存 TTL 都要用到。
这一步能把问题切成两类:本地配置问题、服务端权威问题。后续排查路径完全不同,混在一起查会浪费大量时间。
第二步:看客户端到底在问谁
Linux 上先看 /etc/resolv.conf 和 /etc/nsswitch.conf。前者决定上游服务器,后者决定解析顺序。常见配置:
cat /etc/resolv.conf # nameserver 100.125.1.250 # nameserver 100.125.129.250 # options timeout:2 attempts:2 grep hosts /etc/nsswitch.conf # hosts: files dns myhostname
注意 options timeout:2 attempts:2:单个 nameserver 超时 2 秒、重试 2 次,换下一个服务器。两个服务器全挂时,一次解析要等 8 秒左右,表现成「偶尔很慢」。
用 strace -e trace=network -f getent hosts example.com 可以直接看到进程发出的 UDP 包目的地址和端口,确认它是不是真的走了预期的 DNS 服务器。Systemd 环境下还要检查 resolvectl status,systemd-resolved 会覆盖 /etc/resolv.conf 的内容。
第三步:逐级查询,定位断在哪一跳
从本地缓存一路查到权威,每层都用 dig 指定服务器:
# 本地缓存 dig @127.0.0.53 example.com # 上游递归服务器(华为云内网 DNS 为 100.125.1.250) dig @100.125.1.250 example.com +norecurse # 根服务器,拿到 .com 的 NS dig @198.41.0.4 example.com +norecurse # .com TLD dig @a.gtld-servers.net example.com +norecurse # 权威服务器 dig @ns1.example.com example.com +norecurse
递归服务器返回的 ANSWER SECTION 为空但 AUTHORITY SECTION 有记录,是 NXDOMAIN 或 NODATA;返回 SERVFAIL 通常意味着上游超时或 DNSSEC 校验失败。加上 +dnssec 可以看到 AD 标志位是否置位。
坑一:CNAME 和 A 记录冲突导致解析间歇性失败
某次线上业务做了灰度,一部分流量解析失败,一部分正常。查权威日志发现查询量翻倍且响应正常,问题出在记录配置:同一名字下同时存在 CNAME 和 A 记录。RFC 1034 明确规定 CNAME 不能与其它记录共存,但部分 DNS 服务商允许保存,递归服务器在缓存了 A 记录时直接返回,缓存了 CNAME 时走另一条链,行为取决于缓存状态,于是表现为间歇性失败。
排查命令:
dig +short example.com A dig +short example.com CNAME dig example.com ANY
修复方式是把 A 记录迁到 CNAME 指向的目标名下,例如 example.com CNAME lb.example.com、lb.example.com A 1.2.3.4,改完等旧记录 TTL 过期(建议改之前先把 TTL 调到 60 秒,观察 10 分钟)。
坑二:TTL 设置过长,切流后旧 IP 仍被使用
机房迁移时把 A 记录从旧 IP 改成新 IP,结果 6 小时后仍有约 15% 的请求打到旧机器。当时记录 TTL 是 86400 秒,递归服务器的缓存无法主动清除,只能等。
标准做法是切换前一周把 TTL 降到 60 秒,切换时按 60 秒的节奏观察,确认无旧 IP 流量后再恢复。检查缓存剩余时间可以用:
dig example.com +noall +answer # example.com. 3600 IN A 1.2.3.4 # 第三列就是剩余 TTL
如果个别递归服务器不遵守 TTL,只能通过业务层兜底:旧机器保留 24 小时并返回 301 跳转,比直接下线安全。
第四步:抓包确认协议层
前三步都正常但现象依旧时,抓包。UDP 53 端口:
tcpdump -i eth0 -nn -s0 'udp port 53' -w dns.pcap # 大响应被截断时走 TCP,需要一并抓 tcpdump -i eth0 -nn 'tcp port 53'
关注三点:查询是否发出、响应是否返回、响应中的 TC 标志。TC 置位说明响应超过 512 字节被截断(EDNS0 协商后通常是 1232 字节),客户端需要改用 TCP 重查。防火墙放行 UDP 不放行 TCP 时,带 DNSSEC 签名的大响应就会失败,表现为「小域名能解析,大域名解析不了」。
小结
排查顺序固定为:确认影响范围 → 看客户端配置与实际查询目标 → 用 dig @服务器 逐级定位断点 → 抓包看协议层。多数故障在前两步就能定位,剩下的是缓存时效和记录配置类问题。改动前先降 TTL、改完观察旧记录流量,能避免大部分切流事故。
- 点赞
- 收藏
- 关注作者
评论(0)