DNSSEC 故障排查:SERVFAIL 多半是它的锅

DNSSEC 开好了是保护,开错了是灾难——全网解析失败,而你可能还不知道原因。这篇讲怎么排查和避免。

一、先看信任链

bash
根服务器(信任锚)
  → 签名 .net,告诉递归服务器「.net 的密钥是这个」(DS 记录)
  → .net 签名 www.bzii.cn(又是 DS 记录)
  → www.bzii.cn 的权威服务器用私钥签名 A 记录(RRSIG)
  → 递归服务器逐级验证签名

任何一环断掉,校验就失败,返回 SERVFAIL。

二、最常见的错误:换了 NS 没更新 DS

这是 DNSSEC 的头号事故:

bash
1. 你在 Cloudflare 开了 DNSSEC,去注册商填了 DS 记录
2. 后来你把 NS 从 Cloudflare 换成了别的 DNS 服务商
3. 注册商那边的 DS 还指向 Cloudflare 的密钥
4. 新 DNS 服务商的签名对不上 DS
5. → 全网 SERVFAIL,站点彻底打不开

正确顺序

bash
# 换 DNS 服务商之前:
1. 在新服务商加好域名、抄全记录
2. 【关键】关闭 DNSSEC,删除注册商的 DS 记录
3. 等 DS 记录的 TTL 过期(通常几小时到一天)
4. 再改 NS 记录
5. 确认新 DNS 工作正常
6. 重新开启 DNSSEC,把新的 DS 填到注册商

第 3 步的等待不能省。DS 记录被缓存着,立刻换 NS 会有窗口期失败。

三、诊断

1. 看状态码

bash
dig www.bzii.cn
# status: SERVFAIL   ← DNSSEC 校验失败的典型表现

对比:

bash
dig +cd www.bzii.cn     # +cd 关闭 DNSSEC 校验
# 如果 +cd 能正常解析,不加就不行 → 100% 是 DNSSEC 问题

这是最快速的判定方法

2. 看 DS 与 DNSKEY 是否匹配

bash
# 看注册商/上级发布的 DS
dig +short www.bzii.cn DS

# 看权威服务器实际的 DNSKEY
dig +short www.bzii.cn DNSKEY

# 详细模式,看签名
dig +dnssec www.bzii.cn A
# 应答里应有 RRSIG 记录

3. 在线工具(最直观)

bash
# DNSSEC Analyzer(图形化显示信任链,直接指出断在哪)
# https://dnssec-analyzer.verisignlabs.com/www.bzii.cn

# DNSViz
# https://dnsviz.net/d/www.bzii.cn/dnssec/

这两个工具会用红色标出断链位置,比手工分析快得多。

四、常见错误类型

错误表现原因
DS 不匹配SERVFAIL换了 NS 没更新 DS
DS 缺失校验跳过(不报错)没在注册商填 DS
算法不支持SERVFAIL用了老算法(如 RSASHA1)
签名过期SERVFAIL权威服务器没及时重签名
时钟不同步SERVFAIL服务器时间偏差过大
bash
# 检查签名有效期
dig +dnssec www.bzii.cn A | grep RRSIG

五、Cloudflare 场景的特殊处理

Cloudflare 的 DNSSEC 有个细节:

  • 在 Cloudflare 开启后,它会给出 DS 记录;
  • 必须去注册商(不是 Cloudflare)填 DS
  • 如果域名也在 Cloudflare Registrar,后台会自动同步。
bash
# 确认 DS 是否真的发布到了上级
dig +short www.bzii.cn DS
# 有输出 = 已生效
# 空 = 还没填或还没传播

橙色云与 DNSSEC

Cloudflare 代理模式下,用户看到的是 CF 返回的记录。CF 会为代理的域名生成签名,一般没问题。但如果:

  • 用了 CNAME 接入;
  • 或者改成了灰色云(DNS only);

可能出现签名不一致。遇到这种情况,先关 DNSSEC,稳定后再开。

六、如何安全地关闭

出了问题需要紧急恢复时:

bash
1. 去注册商删除 DS 记录(这是最关键的一步)
2. 在 DNS 服务商那边关闭 DNSSEC
3. 等 DS 的 TTL 过期(几分钟到几小时)
4. 验证:dig www.bzii.cn 应恢复正常
bash
dig www.bzii.cn | grep status
# NOERROR → 已恢复

dig +short www.bzii.cn DS
# 空 → DS 已删除

只关 DNS 服务商的开关不够,必须删注册商的 DS。 只关一边会导致更长时间的故障。

七、定期自检

把这几条加进巡检脚本:

bash
#!/usr/bin/env bash
# dnssec-check.sh
DOMAIN="www.bzii.cn"

echo "== 解析状态 =="
dig $DOMAIN | grep "status:"

echo "== 关闭校验对比 =="
dig +cd $DOMAIN | grep "status:"

echo "== DS 记录 =="
dig +short $DOMAIN DS

echo "== RRSIG =="
dig +dnssec $DOMAIN A | grep -c RRSIG

判读:

  • 正常情况:status: NOERROR、有 DS、有 RRSIG;
  • 如果 SERVFAIL+cd 正常 → DNSSEC 有问题。

八、要不要开 DNSSEC

我的判断:

情况建议
DNS 托管在 Cloudflare 且不常换✅ 开
经常换 DNS 服务商⚠️ 谨慎,每次都要记得处理 DS
注册商不支持填 DS❌ 开不了
对原理不了解⚠️ 先搞懂再开,否则出事不会排查

DNSSEC 防的是 DNS 缓存投毒(把用户引导到假站点)。对普通个人站点,这个攻击发生的概率很低——但开了之后搞错的风险反而是实实在在的

结论:开,但一定要理解 DS 与 NS 的关系。不理解就先别开,这比开了出事强。

九、一份操作备忘

bash
开启:DNS 服务商开启 → 拿 DS → 去注册商填 DS → dig 验证 → 在线工具确认

换 DNS:关 DNSSEC → 删注册商 DS → 等 TTL → 改 NS → 验证 → 重开 DNSSEC

故障:dig 看 status → +cd 对比确认 → 删 DS → 等生效 → 排错后重开

DNSSEC 的口诀:改 NS 之前先动 DS。 记住这一条,就能避开最大的坑。