排错与常用命令
DNS 出问题时,最常见的错误是同时改好几处。先确定问题出在哪一段,再动手,通常几条命令就能定位。
先确定是哪一段#
- 本机:hosts 文件、系统缓存、浏览器自带的 DoH。换一个程序(比如用 dig 而不是浏览器)能不能复现?
- 递归解析器:直接问它(
dig @解析器),再换一个公共解析器对比。只有某一家解析器出错,多半是它的缓存、过滤或 DNSSEC 验证。 - 权威服务器:绕过所有缓存,直接问区的权威服务器(
+norecurse)。所有权威服务器的回答一致吗? - 委派:从根开始走一遍(
+trace),看父区给出的 NS 和子区自己声明的是否一致。 - 网络:UDP/53、TCP/53、853 能否通?大应答能否通过?
dig 速查#
shell
$ dig example.com # 默认 A 记录,用系统配置的解析器
$ dig @9.9.9.9 example.com AAAA # 指定解析器和类型
$ dig +short example.com MX # 只要数据
$ dig +trace example.com # 从根开始迭代,逐级显示转介
$ dig @ns1.example.com example.com +norecurse # 直接问权威,不要递归
$ dig +dnssec example.com # 请求签名(置 DO 位)
$ dig +cd example.com # 让解析器跳过 DNSSEC 验证
$ dig +tcp example.com # 强制 TCP
$ dig +bufsize=1232 example.com DNSKEY # 声明 EDNS 缓冲区大小
$ dig +nsid @k.root-servers.net . SOA # 问出任播实例的身份
$ dig +subnet=198.51.100.0/24 example.com # 附带 ECS,观察按地区的应答
$ dig -x 192.0.2.10 # 反向解析kdig(Knot DNS)的选项基本相同,额外的 +tls、+https、+quic 用来测试加密传输,-d 打印传输层细节。drill -TD example.com 能同时做迭代和 DNSSEC 链检查。
读懂 dig 的输出#
dig 输出
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 20517
;; flags: qr rd ra ad; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1
;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 1232
;; ANSWER SECTION:
example.com. 1726 IN A 192.0.2.10
;; Query time: 18 msec
;; SERVER: 9.9.9.9#53(9.9.9.9) (UDP)
;; MSG SIZE rcvd: 56status是 RCODE;NOERROR 加空回答节就是 NODATA。flags里有aa说明是权威应答;有ad说明解析器验证通过;有tc说明被截断。- 回答里的 TTL 是剩余时间。对同一解析器连续查两次,TTL 递减说明命中缓存。
SERVER一行告诉你实际是谁回答的,用的什么传输——排查“到底问了谁”时先看这里。
RCODE 对照#
| 值 | 名称 | 常见原因 |
|---|---|---|
| 0 | NOERROR | 成功;回答节为空时表示名字存在但没有该类型(NODATA) |
| 1 | FORMERR | 对方看不懂报文,老服务器遇到 EDNS 时偶尔这样回 |
| 2 | SERVFAIL | 服务器无法完成:DNSSEC 验证失败、权威全部不可达、超时、上游出错 |
| 3 | NXDOMAIN | 名字不存在 |
| 4 | NOTIMP | 不支持该操作,例如对不支持 NOTIFY 的服务器发 NOTIFY |
| 5 | REFUSED | 按策略拒绝:不为你递归、不负责这个区、区传送未授权 |
| 6–10 | YXDOMAIN 等 | 动态更新的前提条件不满足 |
| 16 | BADVERS / BADSIG | EDNS 版本不支持;在 TSIG 语境下表示签名错误 |
扩展错误码(EDE)#
SERVFAIL 太笼统。RFC 8914 定义的扩展错误码以 EDNS 选项的形式附在应答上,dig 会显示为 ; EDE: 6 (DNSSEC Bogus) 这样的行。并非所有解析器都会发送。
| 码 | 名称 | 含义 |
|---|---|---|
| 0 | Other Error | 其他,看附带的文本 |
| 1 | Unsupported DNSKEY Algorithm | 区使用了解析器不支持的签名算法 |
| 2 | Unsupported DS Digest Type | DS 的摘要类型不受支持 |
| 3 | Stale Answer | 返回的是过期缓存(serve-stale) |
| 4 | Forged Answer | 应答被解析器有意改写,例如按策略拦截 |
| 5 | DNSSEC Indeterminate | 验证无法得出结论 |
| 6 | DNSSEC Bogus | 验证失败 |
| 7 | Signature Expired | 签名已过期 |
| 8 | Signature Not Yet Valid | 签名尚未生效,检查双方时钟 |
| 9 | DNSKEY Missing | 找不到与 DS 对应的 DNSKEY |
| 10 | RRSIGs Missing | 应有签名却没有 |
| 11 | No Zone Key Bit Set | DNSKEY 未设置区密钥标志 |
| 12 | NSEC Missing | 缺少证明不存在所需的 NSEC/NSEC3 |
| 13 | Cached Error | 返回的是缓存下来的错误 |
| 14 | Not Ready | 服务器尚未准备好(如刚启动) |
| 15 | Blocked | 名字被运营方的黑名单拦截 |
| 16 | Censored | 因外部要求被拦截 |
| 17 | Filtered | 因客户端自己要求的过滤被拦截 |
| 18 | Prohibited | 客户端无权使用该服务器 |
| 19 | Stale NXDOMAIN Answer | 返回的是过期缓存里的 NXDOMAIN |
| 20 | Not Authoritative | 服务器不是权威,且不提供递归 |
| 21 | Not Supported | 不支持请求的操作或类型 |
| 22 | No Reachable Authority | 没有一台权威服务器可达 |
| 23 | Network Error | 与权威服务器通信时发生网络错误 |
| 24 | Invalid Data | 权威返回的数据无效 |
常见现象#
- 只有某些解析器返回 SERVFAIL
- 先用
+cd再查一次:加上就能解析,问题在 DNSSEC(签名过期、DS 不匹配最常见)。用delv看具体哪一环失败。 - 改了记录,有的地方生效有的地方没生效
- 旧记录还在各处缓存里,要等原来的 TTL 过去。也检查是否所有权威服务器都已更新(序列号是否一致)。
- 时好时坏
- 多半是若干台权威服务器中有一台出了问题,或者父区与子区的 NS 不一致。逐台
+norecurse查询比对。 - 小记录正常,大记录(DNSKEY、长 TXT)失败
- 大 UDP 应答被分片丢失,或者截断后改用 TCP 时被防火墙挡住。分别用
+bufsize=1232和+tcp测试。 - 网站很慢才打开
- 可能发布了 AAAA 但 IPv6 不通,客户端先尝试 IPv6 等到超时。用
curl -6和curl -4分别测试。 - 浏览器能打开,命令行解析不了(或反过来)
- 浏览器可能开着自己的 DoH,绕过了系统解析器。见浏览器设置。
清理缓存#
shell
# Windows(管理员命令提示符或 PowerShell)
ipconfig /flushdns
# macOS
$ sudo dscacheutil -flushcache; sudo killall -HUP mDNSResponder
# Linux,systemd-resolved
$ resolvectl flush-caches
# Chrome / Edge:在地址栏打开
chrome://net-internals/#dns (Edge 为 edge://net-internals/#dns),点 Clear host cache清的只是本机这一层。递归解析器的缓存你一般清不了,只能等 TTL 过期;部分公共解析器提供了网页上的“清除缓存”入口。
TTL 换算#
区文件和各种控制台里的 TTL 有的写秒数,有的写 1h、2d。两边任填一个: