“nslookup 有结果,DNS 没问题。”
然后工单里还在刷:有人秒开、有人转圈、公司内网能开、手机流量打不开、发版切了 IP 还有 5% 用户落在旧节点。
DNS 最容易被误用的,是把“能返回 A 记录”当成“解析正确”。
一次解析背后是一条链:
浏览器缓存 → 系统缓存 → hosts → 本地递归(运营商/企业 DNS)→ 根/TLD → 权威 → CDN GSLB → ECS 策略
任何一跳都能返回“能通但错”的 IP:旧缓存、运营商劫持、ECS 没带、VPN 下发了另一套 DNS、DoH 走了不同递归器。
本文给一套工程向“DNS 解析查询取证”方法:多递归对照、+trace 打点、TTL 与缓存一致性、CDN 调度验证、解析 SLI 化。
一、先定性:DNS 查询回答的是“信任链”,不是“真相”
dig [](@replace=10001) +short 只给你一个 IP,不告诉你:
- 是谁答的(运营商递归?企业 DNS?DoH?)
- 答的是哪一层缓存(浏览器?系统?递归器?)
- 有没有 ECS(CDN 知不知道用户真实位置)
- 是不是被污染/劫持后的“假正确”
- TTL 还剩多少、旧记录会不会再活 10 分钟
解析“有结果”≠“解析对”。
二、基础三连:别只跑 +short
1. 多递归对照(先定范围)
bash
dig @8.8.8.8 example.com +short dig @1.1.1.1 example.com +short dig @223.5.5.5 example.com +short dig @114.114.114.114 example.com +short
现象判读:
- 公共 DNS 对、运营商 DNS 错 → 递归层劫持/旧缓存
- 全部对但用户侧错 → 本地缓存/浏览器 DoH/hosts
- 返回不同 CDN 节点 IP → 调度策略或 ECS 问题
2. 完整迭代链(定位哪一跳变坏)
bash
dig +trace example.com
看:
- 根/TLD 是否正常委派
- 权威 NS 是不是预期那组
- 哪一跳开始返回异常 IP
- 权威答的 TTL 是多少
3. 看应答元信息
bash
dig example.com +noall +answer +stats dig example.com ANY +noall +answer dig example.com +dnssec
重点字段:
Query time:递归耗时SERVER:实际应答的递归器ttl:剩余缓存寿命CNAME链:是不是绕到意外 CDN 厂商RRSIG:DNSSEC 验没过
三、解析链路分层:把“谁在解析”画出来
text
浏览器(DoH/安全DNS/代理) ▼ 系统解析器(/etc/resolv.conf、hosts) ▼ 企业/运营商递归 DNS ▼ 根 → TLD → 权威 DNS ▼ CDN GSLB(按源 IP / ECS 调度) ▼ 返回边缘节点 IP
典型误判现场:
现象 |
真因 |
nslookup 正常,浏览器打不开 |
浏览器走 DoH/代理,解析器不同 |
公司内能开,外网打不开 |
Split DNS / VPN 下发不同递归 |
同域名有人快有人慢 |
递归 DNS 位置导致 CDN 调度歪 |
切了新 IP 还有人访问旧机 |
TTL 没降、递归缓存没过期 |
IPv4 正常 IPv6 慢 |
AAAA 有结果但 IPv6 路径差 |
四、TTL 与缓存:改完记录不是“立刻生效”
DNS 变更真实传播路径:
text
权威改记录 ▼ 递归器按 TTL 继续返回旧值 ▼ 浏览器/系统缓存各自过期 ▼ 用户侧逐步切到新 IP
生产变更铁律:
- 切流量前把 TTL 先降到 60s(提前 5–10 分钟)
- 切完观察“解析一致性”再缩容旧节点
- 负缓存(NXDOMAIN)也会按 TTL 留
- 浏览器缓存不认权威 TTL,需配合版本化域名或强制刷新
验证:
bash
# 看 TTL 倒计时 dig example.com +noall +answer # 指定源 IP 模拟 ECS(权威侧支持时) dig example.com +subnet=1.2.3.0/24 +short
五、CDN 调度验证:返回 IP 对不对,比有没有 IP 重要
智能解析通常看:
- 递归 DNS 出口 IP(不是用户真实 IP)
- ECS 携带的子网(用户位置)
- 运营商/地域策略
- 节点健康度
排查 CDN 慢:
bash
# 不同地域递归看返回哪个边缘 dig @8.8.8.8 example.com +short dig @223.5.5.5 example.com +short # 看 CNAME 终点到哪 dig example.com CNAME +noall +answer
结论模板:
- 广州用户但解析到北京节点 → 递归 DNS 集中出口,没开 ECS
- 海外快国内慢 → 国内解析到海外 Anycast
- 同运营商不同省结果差 → GSLB 策略/GeoIP 库旧
六、多节点 DNS 查询:把“我这边通”变成“全局一致”
单机 dig 只代表一条链路。工程做法:
- 多地域探针(华东/华南/华北/海外)
- 多递归(电信/联通/移动/公共 DNS)
- 同时间窗对照 A / AAAA / CNAME
- 记录:解析成功率、P95 解析延迟、结果集合一致性
脚本化:
bash
#!/bin/bash DOMAIN=$1 for NS in 8.8.8.8 1.1.1.1 223.5.5.5 114.114.114.114; do echo -n "$NS: " dig @$NS $DOMAIN +short | sort | tr '\n' ' ' echo done
输出不是“IP 列表”,是“信任分布”。
排障时顺手用 KKCE 的 dns 解析查询做多递归对照,把自建探针和公开节点结果放一起,能更快看出是不是某运营商递归在回脏数据。
七、把 DNS 查询做成 SLI(别只监控“通不通”)
建议监控维度:
SLI |
阈值参考 |
解析成功率 |
≥99.99% |
P95 解析延迟 |
≤150ms(同地域) |
SERVFAIL 率 |
突增即告警 |
NXDOMAIN 突增 |
疑似爆破/配置误删 |
多节点结果一致性 |
同线路差异>1 个 IP 即查 |
ECS 地理命中率 |
返回节点与用户地域匹配度 |
接入 CI/CD:
- 发版前先降 TTL
- 发版后自动跑多节点解析一致性
- 不一致不摘旧节点
八、排障 SOP:同域名访问不一致时
text
1. 确认范围:全量/单运营商/单地域/单用户 2. 多递归 dig 对照(8.8.8.8/223.5.5.5/114) 3. dig +trace 看哪一跳变答案 4. 查 CNAME 链和最终边缘 IP 5. 检查 ECS / 递归出口 / VPN / DoH 6. 看 TTL 剩余,确认是不是缓存没过期 7. 结论落点: - 递归劫持 → 切 DoH/公共 DNS/投诉运营商 - 调度歪 → 开 ECS / 调 GSLB - 缓存旧 → 降 TTL 等窗口 - 权威错 → 改 NS/A 记录
九、什么别用 DNS 查询干
- 看到 A 记录就回“DNS 正常”
- 只在公司网络 dig 一次下结论
- 改记录不降 TTL 直接缩容旧节点
- 忽略 CNAME 链(CDN 厂商跳错)
- 不区分 IPv4/IPv6 解析路径
- 把内网域名提交公共解析平台
- 以为“能解析”=“用户访问路径对”
十、总结
DNS 解析查询最被用废的地方,是把它当“域名转 IP 的转换器”。
它该是:
解析链路的取证工具。
谁解析、走哪条递归、答的是不是权威、带没带 ECS、TTL 还剩多少、CDN 调度到哪个边缘——
每一层都可能撒谎。
排障不是证明“我有 IP”,
是证明“用户拿到的那个 IP,是对的那个”。
公司内能开、外网转圈,
命令行通、浏览器卡,
切了 IP 还有旧节点接流量,
都不是玄学,
是解析链某一跳没对齐。
把 dig 从“查一下”升级成“多递归对照 + trace 打点 + 一致性基线”,
“DNS 没问题”这句话,
才会变成一句能派单的结论:
“广东移动递归没带 ECS,CDN 返回北京节点,
降 TTL、开 ECS 透传,重测解析一致性。”
一台机器 dig 得再漂亮,
也救不了一个把 A 记录当真相的排障习惯。