跳转至

DNS 排障检测:dig +trace 从递归到权威的六症状决策树

DNS 报错了先别急着重启服务。你看到的那个"打不开"背后,可能是递归挂了、权威配错、TTL 太长、也可能是本地缓存还没刷新。DNS 的问题不是"能不能通",是"哪一跳挂了"。

原创声明:本文所有 dig 命令组合、症状分岔、失败案例均为作者实操记录,配置片段可粘贴直接执行。未搬运任何第三方博客正文。

60 秒选型:dig / host / nslookup 该怎么用

工具 什么时候用 一句话说明
dig 90% 的排障场景 全功能,能指定 resolver / 记录类型 / trace / 关闭验证
host 快速拿答案 一行输出,脚本里方便,但没 trace 能力
nslookup 只在 Windows 上被迫用 老旧接口,Linux 上能 dig 就别用它

三个工具都能拿到答案,但排障能力差得很远。下面全程用 dig。

六症状决策树:先看报错再动手

先看症状,再选命令。症状对应错,命令再对也白搭。

用户说"DNS 有问题"
  │
  ├─ 报 NXDOMAIN ──────── 域名真的存在吗?查权威
  ├─ 报 SERVFAIL ──────── 递归或权威哪边挂了?trace
  ├─ 超时/无响应 ──────── 递归 DNS 服务挂了?换 resolver
  ├─ CNAME 不生效 ────── 循环引用?看 +noall +answer
  ├─ 缓存不刷新 ──────── TTL 是多少?看 TTL 字段
  └─ 证书校验失败 ────── 上游 DNSSEC 挂了?+cd 绕过验证

下面逐症状展开,每个都带可执行命令和"你应该看到什么"。

症状 1:NXDOMAIN —— 域名真的存在吗

# 第一步:直接问本地递归
dig example.com

# 第二步:直接问权威 NS(跳过递归)
dig @ns1.example.com example.com

你应该看到什么:

  • status: NOERROR + ANSWER SECTION 有 IP → 域名存在,NXDOMAIN 是本地缓存骗了你
  • status: NOERROR 但 ANSWER SECTION 空 → 域名存在但没配 A/AAAA 记录,加一条
  • status: NXDOMAIN(dig @ns1.example.com)→ 域名真的不存在,去注册商确认

常见失败案例:注册商控制台显示域名"已注册",但权威 NS 回 NXDOMAIN。这是注册商 DNS 服务器还没同步,等 30-60 分钟再看。别去改本地 DNS 配置。

症状 2:SERVFAIL —— 谁挂了

SERVFAIL 是 DNS 世界最讨厌的报错,因为权威服务器说"我搞不定",但没说为什么。

# 从根开始逐跳追踪
dig @8.8.8.8 example.com +trace

# 单独问某一级 NS
dig @a.root-servers.net . NS
dig @ns1.example.com example.com NS

你应该看到什么:

  • trace 中某一步回 SERVFAIL → 那一跳的 NS 服务器挂了或配置错
  • 每一步都 NOERROR 但最终 SERVFAIL → 权威自己配置循环(比如 NS 指回了自己没生效的服务器)

踩坑:SERVFAIL 有时候是递归 DNS 加了 DNSSEC 校验但权威链断了。用 dig @8.8.8.8 example.com +cd 关闭验证(+cd = CD flag)绕过,看能不能过。能过说明权威 DNSSEC 配错,不能过说明权威真挂了。

症状 3:超时/无响应 —— 递归挂了还是网络问题

# 对比三个 resolver 的响应
dig @8.8.8.8 example.com +time=3 +tries=1
dig @1.1.1.1 example.com +time=3 +tries=1
dig @223.5.5.5 example.com +time=3 +tries=1

你应该看到什么:

  • 三个都超时 → 网络问题或 DNS 端口被封
  • 只有内部 DNS(比如 10.x.x.x)超时 → 内部递归挂了,看 bind/systemd-resolved 日志
  • 都能回但只有内部慢 → 内部递归配置差,考虑换成公共 DNS

失败案例:办公网内一台机器"DNS 超时",其他机器正常。dig @8.8.8.8 example.com 也慢——这台机器的本地 DNS 缓存服务没跑起来(systemd-resolved 崩了)。systemctl restart systemd-resolved 就好。

症状 4:CNAME 循环 —— 配置错了

# 只看 CNAME 链
dig example.com +noall +answer +comments

# 看完整 CNAME 展开
dig example.com ANY

你应该看到什么:

  • example.com. 300 IN CNAME www.example.com. + www.example.com. 300 IN CNAME example.com. → 循环了
  • 只有一层 CNAME + 最终 A 记录 → 正常

踩坑:CNAME 不能和 A/AAAA/MX 在同一主机名下共存。想在同一域名配 IP 又做别名?拆两个域名(app.example.com CNAME 到 lb.example.com,lb.example.com 直接 A)。别硬塞。

症状 5:缓存不刷新 —— TTL 说了算

# 看 TTL 字段(第一列)
dig example.com | head -20

# 强制换 resolver 验证
dig @8.8.8.8 example.com
dig @1.1.1.1 example.com

你应该看到什么:

  • example.com. 86400 IN A 1.2.3.4 → TTL 24 小时,你刚才改了记录要等 24 小时
  • 两个 resolver 返回不同 IP → 本地递归用了不同的上游,缓存策略不一样
  • 两个 resolver 都返回旧 IP → 权威没同步,回权威那边查

关键规则:想立即生效,必须先改小 TTL(改成 60 秒),等一个 TTL 周期,再改记录。反序做等于白改。

症状 6:DNSSEC 验证失败 —— 上游挂了

# 正常验证
dig example.com +dnssec

# 关闭验证绕过
dig example.com +cd

你应该看到什么:

  • 加 +dnssec 有 RRSIG 签名,正常 → DNSSEC 正常
  • status: SERVFAIL 加 +cd 变 NOERROR → 上游 DNSSEC 挂了
  • 两条都 SERVFAIL → 权威真挂了

DNSSEC 排障我不完全确定所有细节(每家 DNS 厂商行为不同),但基本思路一致:先绕过验证看链路本身是否通,再看签名链是否完整。

Cheat Sheet:15 条常用 dig 姿势

命令 用途
dig +short <domain> 只要答案,一行
dig <domain> A 查 A 记录
dig <domain> AAAA 查 IPv6
dig <domain> MX 查邮件记录
dig <domain> TXT 查 TXT(SPF/DMARC)
dig <domain> NS 查权威 NS
dig <domain> CAA 查允许签发证书的 CA
dig @<resolver> <domain> 指定递归 DNS
dig @<authority> <domain> 直接问权威
dig <domain> +trace 从根递归追踪
dig <domain> +nocmd 交互式
dig <domain> +noall +answer 只显示答案
dig <domain> +noall +comments 只显示元数据
dig <domain> +dnssec 请求 RRSIG 签名
dig <domain> +cd 关闭 DNSSEC 验证

总结与判断

DNS 排障不是背命令,是判断哪一跳挂了。六症状对应六条路径,dig +trace 覆盖其中一半,剩下的一半靠对比 resolver 和看 TTL。别看到 NXDOMAIN 就改 DNS 服务器——那只是症状,不是病根。

我的判断:这套决策树对个人运维够用了。要更深的分析(DNS over HTTPS、DNSSEC 签名链细节、Anycast 排障),得单独开专题写。日常 90% 场景就这六条路。

延伸阅读


本文由 ops.jiunotes.top 独立撰写。所有 dig 命令、症状分岔、失败案例均为作者实操经验总结,未搬运任何第三方博客内容。dig 官方文档见 ISC dig man page。CC BY-NC-SA 4.0。