版本信息最后核对:2026-10-25
Lab 状态:实跑通过
TTL 预降、区导入、NS 切换、回滚与探针均通过;宿主 5353 被占用时用 15353 等价验证
本 Lab 用本地 CoreDNS 文件区和显式 upstream 模拟委派与递归解析,真实环境还涉及注册商控制面、父区缓存、Anycast、运营商解析器和 DNSSEC 验证器,不能直接外推结论。
安全边界:只允许在一次性虚拟机或本地 Docker Compose 中进行。不要修改公司域名、真实注册商 NS、生产 DNS、线上 zone 或证书。所有命令都带
timeout;实验结束只清理本项目,保留其他 Compose 项目。任何真实切换都必须有变更单、回滚窗口和决策人。
准备 Docker/Compose v2、dig、curl 和 GNU timeout。本页按 Linux/bash 编写;macOS 默认没有 timeout,先安装 coreutils,并把命令中的 timeout 替换为 gtimeout。所有文件放在 /tmp/lab-dns-failover,Compose 项目名固定为 lab-dns-failover,网络名固定为 lab-dns-failover-net,避免误删其他项目。
启动前先检查宿主机端口:lsof -nP -iUDP:5353 -iUDP:5354 -iUDP:5355 -iUDP:5356。macOS 的 mDNS(Chrome、avahi 等)常占用 UDP 5353,docker compose up 会报 bind: address already in use;此时只需把 parent 的宿主机端口改为 127.0.0.1:15353:53/udp 和 127.0.0.1:15353:53/tcp,并把本页所有父区查询的 -p 5353 改为 -p 15353,容器 IP、委派和缓存逻辑不变。
网络使用 172.29.0.0/24:父区 172.29.0.10,旧权威 172.29.0.11,新权威 172.29.0.12,递归缓存 172.29.0.13,旧应用 172.29.0.20,新应用 172.29.0.21,探针 172.29.0.22。父区和旧权威通过回环端口 5353、5355 暴露,新权威和递归缓存分别用 5356、5354。
先创建目录、父区、旧权威和递归缓存配置。父区只负责 example. 委派,旧权威负责 lab.example.;初始委派指向 ns1.old.example.:
timeout 10 mkdir -p /tmp/lab-dns-failover/{parent,old,new,resolver,www/old,www/new,backup}
timeout 10 tee /tmp/lab-dns-failover/parent/Corefile >/dev/null <<'EOF'
example:53 {
file /etc/coredns/example.zone
log
errors
}
EOF
timeout 10 tee /tmp/lab-dns-failover/parent/example.zone >/dev/null <<'EOF'
$ORIGIN example.
$TTL 60
@ IN SOA ns1.example. hostmaster.example. (2026102501 60 30 300 60)
IN NS ns1.example.
ns1 IN A 172.29.0.10
lab IN NS ns1.old.example.
ns1.old IN A 172.29.0.11
ns1.new IN A 172.29.0.12
EOF
timeout 10 tee /tmp/lab-dns-failover/old/Corefile >/dev/null <<'EOF'
lab.example:53 {
file /etc/coredns/lab.example.zone
log
errors
}
EOF
timeout 10 tee /tmp/lab-dns-failover/old/lab.example.zone >/dev/null <<'EOF'
$ORIGIN lab.example.
$TTL 30
@ IN SOA ns1.old.example. hostmaster.lab.example. (2026102501 60 30 300 30)
IN NS ns1.old.example.
IN MX 10 mail.lab.example.
IN TXT "v=spf1 -all"
IN CAA 0 issue "letsencrypt.org"
app IN A 172.29.0.20
www IN CNAME app.lab.example.
mail IN A 172.29.0.20
_verify IN TXT "lab-dns-failover"
_acme-challenge IN TXT "lab-token"
*.apps IN A 172.29.0.20
EOF
timeout 10 tee /tmp/lab-dns-failover/new/Corefile >/dev/null <<'EOF'
lab.example:53 {
file /etc/coredns/lab.example.zone
log
errors
}
EOF
timeout 10 tee /tmp/lab-dns-failover/resolver/Corefile >/dev/null <<'EOF'
.:53 {
cache 300
forward . 172.29.0.11
log
errors
}
EOF
timeout 10 tee /tmp/lab-dns-failover/www/old/index.html >/dev/null <<'EOF'
old
EOF
timeout 10 tee /tmp/lab-dns-failover/www/new/index.html >/dev/null <<'EOF'
new
EOF
写 Compose。new-auth 先定义但不启动,等记录导入后再加入;探针通过本地递归缓存解析 app.lab.example,应用端口只绑定回环地址,便于从宿主机核对旧、新后端:
timeout 10 tee /tmp/lab-dns-failover/compose.yaml >/dev/null <<'EOF'
name: lab-dns-failover
services:
parent:
image: coredns/coredns:1.11.3
container_name: lab-dns-parent
command: -conf /etc/coredns/Corefile
ports:
- "127.0.0.1:5353:53/udp"
- "127.0.0.1:5353:53/tcp"
volumes:
- ./parent:/etc/coredns:ro
networks:
lab:
ipv4_address: 172.29.0.10
old-auth:
image: coredns/coredns:1.11.3
container_name: lab-dns-old
command: -conf /etc/coredns/Corefile
ports:
- "127.0.0.1:5355:53/udp"
- "127.0.0.1:5355:53/tcp"
volumes:
- ./old:/etc/coredns:ro
networks:
lab:
ipv4_address: 172.29.0.11
new-auth:
image: coredns/coredns:1.11.3
container_name: lab-dns-new
command: -conf /etc/coredns/Corefile
ports:
- "127.0.0.1:5356:53/udp"
- "127.0.0.1:5356:53/tcp"
volumes:
- ./new:/etc/coredns:ro
networks:
lab:
ipv4_address: 172.29.0.12
resolver:
image: coredns/coredns:1.11.3
container_name: lab-dns-resolver
command: -conf /etc/coredns/Corefile
ports:
- "127.0.0.1:5354:53/udp"
- "127.0.0.1:5354:53/tcp"
volumes:
- ./resolver:/etc/coredns:ro
networks:
lab:
ipv4_address: 172.29.0.13
app-old:
image: nginx:stable
container_name: lab-dns-app-old
ports:
- "127.0.0.1:8080:80"
volumes:
- ./www/old:/usr/share/nginx/html:ro
networks:
lab:
ipv4_address: 172.29.0.20
app-new:
image: nginx:stable
container_name: lab-dns-app-new
ports:
- "127.0.0.1:8081:80"
volumes:
- ./www/new:/usr/share/nginx/html:ro
networks:
lab:
ipv4_address: 172.29.0.21
probe:
image: curlimages/curl:8.10.1
container_name: lab-dns-probe
dns:
- 172.29.0.13
depends_on: [resolver, app-old, app-new]
entrypoint: ["/bin/sh", "-c"]
command:
- |
while :; do
timeout 5 curl -sS --max-time 4 http://app.lab.example/ || echo probe_failed
timeout 5 sleep 2
done
networks:
lab:
ipv4_address: 172.29.0.22
networks:
lab:
name: lab-dns-failover-net
ipam:
config:
- subnet: 172.29.0.0/24
EOF
启动父区、旧权威、缓存、应用和探针,并用循环等待 DNS 与 HTTP readiness,不要只等容器 Running:
timeout 300 docker compose -f /tmp/lab-dns-failover/compose.yaml up -d parent old-auth resolver app-old app-new probe
timeout 120 bash -c 'until timeout 5 dig @127.0.0.1 -p 5353 +short ns1.old.example A | grep -q 172.29.0.11; do timeout 5 sleep 2; done'
timeout 120 bash -c 'until timeout 5 dig @127.0.0.1 -p 5355 +short app.lab.example A | grep -q 172.29.0.20; do timeout 5 sleep 2; done'
timeout 120 bash -c 'until timeout 5 dig @127.0.0.1 -p 5354 +short app.lab.example A | grep -q 172.29.0.20; do timeout 5 sleep 2; done'
timeout 120 bash -c 'until timeout 5 curl -fsS http://127.0.0.1:8080/ >/dev/null; do timeout 5 sleep 1; done'
timeout 120 bash -c 'until timeout 5 curl -fsS http://127.0.0.1:8081/ >/dev/null; do timeout 5 sleep 1; done'
固定基线并导出旧 zone。成功基线应同时满足:父区委派到旧 NS、递归缓存返回 .20、旧权威 SOA 序列为 2026102501、探针日志输出 old。基线不通过就不要继续:
timeout 20 dig @127.0.0.1 -p 5353 +noall +answer +authority lab.example NS | tee /tmp/lab-dns-failover/backup/parent-ns-before.txt
timeout 20 dig @127.0.0.1 -p 5354 +noall +answer app.lab.example A | tee /tmp/lab-dns-failover/backup/app-before.txt
timeout 20 dig @127.0.0.1 -p 5354 +noall +answer lab.example SOA | tee /tmp/lab-dns-failover/backup/soa-before.txt
timeout 20 dig @127.0.0.1 -p 5355 +noall +answer lab.example MX lab.example TXT lab.example CAA | tee /tmp/lab-dns-failover/backup/records-before.txt
timeout 20 dig @127.0.0.1 -p 5355 +noall +answer www.lab.example CNAME demo.apps.lab.example A | tee /tmp/lab-dns-failover/backup/alias-before.txt
timeout 20 dig @127.0.0.1 -p 5353 +dnssec +norecurse DS lab.example | tee /tmp/lab-dns-failover/backup/ds-before.txt
timeout 20 dig @127.0.0.1 -p 5355 +dnssec DNSKEY lab.example | tee /tmp/lab-dns-failover/backup/dnskey-old.txt
timeout 10 cp /tmp/lab-dns-failover/old/lab.example.zone /tmp/lab-dns-failover/backup/zone-export-before.txt
timeout 20 docker compose -f /tmp/lab-dns-failover/compose.yaml logs --tail=10 probe | tee /tmp/lab-dns-failover/backup/probe-before.txt
timeout 20 curl -sS http://127.0.0.1:8080/ | tee /tmp/lab-dns-failover/backup/app-old.txt
timeout 5 sh -c 'date -u +"%FT%TZ stage=baseline_ok" >> /tmp/lab-dns-failover/backup/timeline.log'
把旧权威的默认 TTL 从 30 秒降到 5 秒,同时降低 SOA minimum,覆盖正向和负向缓存。真实环境通过提供商 API 修改,等待时间取旧 TTL 的上限;只改权威记录而不等递归缓存过期,切换后仍会返回旧地址:
timeout 10 sed -E 's/^\$TTL 30$/$TTL 5/; s/\(2026102501 60 30 300 30\)/(2026102501 60 30 300 5)/' /tmp/lab-dns-failover/old/lab.example.zone > /tmp/lab-dns-failover/old/lab.example.zone.tmp
timeout 10 mv /tmp/lab-dns-failover/old/lab.example.zone.tmp /tmp/lab-dns-failover/old/lab.example.zone
timeout 90 docker compose -f /tmp/lab-dns-failover/compose.yaml restart old-auth
timeout 20 dig @127.0.0.1 -p 5355 +noall +answer app.lab.example A
timeout 60 sleep 31
timeout 20 dig @127.0.0.1 -p 5354 +noall +answer app.lab.example A
timeout 10 sleep 2
timeout 20 dig @127.0.0.1 -p 5354 +noall +answer app.lab.example A
timeout 5 sh -c 'date -u +"%FT%TZ stage=ttl_lowered" >> /tmp/lab-dns-failover/backup/timeline.log'
成功判据:旧权威和递归缓存的 Answer TTL 均小于等于 5;两次缓存查询的 TTL 递减;探针没有持续失败。失败判据:TTL 仍为 30、解析中断超过 10 秒、探针连续失败。回滚:恢复 $TTL 30 和原 SOA minimum,重启旧权威,确认解析恢复后再继续。
从旧权威导出 zone 文件,复制后只改三项计划内差异:SOA 主服务器与 NS 改为 ns1.new.example.、序列号递增、app 从 .20 改为 .21。其余 A、CNAME、MX、TXT、CAA、通配符和 TTL 必须保持一致:
timeout 10 cp /tmp/lab-dns-failover/old/lab.example.zone /tmp/lab-dns-failover/backup/zone-export-ttl5.txt
timeout 10 sed -E -e 's/ns1[.]old[.]example[.]/ns1.new.example./g' -e 's/2026102501/2026102502/' -e 's/^app IN A 172[.]29[.]0[.]20$/app IN A 172.29.0.21/' /tmp/lab-dns-failover/old/lab.example.zone > /tmp/lab-dns-failover/new/lab.example.zone
timeout 120 docker compose -f /tmp/lab-dns-failover/compose.yaml up -d new-auth
timeout 120 bash -c 'until timeout 5 dig @127.0.0.1 -p 5356 +short app.lab.example A | grep -q 172.29.0.21; do timeout 5 sleep 2; done'
timeout 20 dig @127.0.0.1 -p 5356 +noall +answer app.lab.example A
timeout 20 dig @127.0.0.1 -p 5356 +noall +answer lab.example SOA
timeout 20 dig @127.0.0.1 -p 5356 +noall +answer lab.example MX lab.example TXT lab.example CAA
timeout 20 dig @127.0.0.1 -p 5356 +noall +answer www.lab.example CNAME demo.apps.lab.example A
timeout 10 grep -Ev '^(@ IN (SOA|NS)|[[:space:]]+IN NS|app IN A)' /tmp/lab-dns-failover/old/lab.example.zone > /tmp/lab-dns-failover/backup/old-rest.txt
timeout 10 grep -Ev '^(@ IN (SOA|NS)|[[:space:]]+IN NS|app IN A)' /tmp/lab-dns-failover/new/lab.example.zone > /tmp/lab-dns-failover/backup/new-rest.txt
timeout 20 diff -u /tmp/lab-dns-failover/backup/old-rest.txt /tmp/lab-dns-failover/backup/new-rest.txt
timeout 5 sh -c 'date -u +"%FT%TZ stage=import_ok" >> /tmp/lab-dns-failover/backup/timeline.log'
成功判据:新权威直接查询返回 .21、新序列号,MX/TXT/CAA/CNAME/通配符与旧权威一致,差异文件为空。失败判据:导入缺记录、TTL 被改写、CNAME 与其它记录冲突、通配符覆盖异常、SOA 未更新。回滚:新权威尚未被委派,直接停止 new-auth 并保留文件即可,不影响旧权威。
在改父区委派前先记录 DS 和 DNSKEY。本 Lab 的 zone 未签名,DS 应为空;如果真实域名有 DS,必须先确认每个仍被解析器使用的 DS 都能在当前对外权威区找到匹配的 DNSKEY,否则验证型解析器会返回 SERVFAIL:
timeout 20 dig @127.0.0.1 -p 5353 +dnssec +norecurse DS lab.example | tee /tmp/lab-dns-failover/backup/ds-imported.txt
timeout 20 dig @127.0.0.1 -p 5355 +dnssec DNSKEY lab.example | tee /tmp/lab-dns-failover/backup/dnskey-old-2.txt
timeout 20 dig @127.0.0.1 -p 5356 +dnssec DNSKEY lab.example | tee /tmp/lab-dns-failover/backup/dnskey-new.txt
timeout 20 dig @127.0.0.1 -p 5356 +dnssec RRSIG lab.example | tee /tmp/lab-dns-failover/backup/rrsig-new.txt
timeout 5 sh -c 'date -u +"%FT%TZ stage=dnssec_checked" >> /tmp/lab-dns-failover/backup/timeline.log'
判断规则:DS 为空且 zone 未签名时,记录“无 DNSSEC 链”并继续;DS 非空时,新提供商必须沿用原密钥,或先做成双签名/双 DS 过渡,再切 NS。不要在旧 zone 仍对外服务时把 DS 指向旧区没有发布的新密钥,也不要为了赶进度临时删除 DS 而不记录安全取舍。
把父区的 lab 委派从 ns1.old.example. 改为 ns1.new.example.,保留两条 glue。然后重启父区和递归缓存。真实递归器会自己跟随委派,本 Lab 用显式 upstream 模拟“解析器已按新 NS 选择权威”的状态,重启会清空本地缓存,生产环境不会这样做:
timeout 10 sed 's/^lab IN NS ns1[.]old[.]example[.]$/lab IN NS ns1.new.example./' /tmp/lab-dns-failover/parent/example.zone > /tmp/lab-dns-failover/parent/example.zone.tmp
timeout 10 mv /tmp/lab-dns-failover/parent/example.zone.tmp /tmp/lab-dns-failover/parent/example.zone
timeout 90 docker compose -f /tmp/lab-dns-failover/compose.yaml restart parent
timeout 20 dig @127.0.0.1 -p 5353 +noall +answer +authority lab.example NS | tee /tmp/lab-dns-failover/backup/parent-ns-after.txt
timeout 20 dig @127.0.0.1 -p 5353 +short ns1.new.example A
timeout 10 sed 's/forward [.] 172[.]29[.]0[.]11/forward . 172.29.0.12/' /tmp/lab-dns-failover/resolver/Corefile > /tmp/lab-dns-failover/resolver/Corefile.tmp
timeout 10 mv /tmp/lab-dns-failover/resolver/Corefile.tmp /tmp/lab-dns-failover/resolver/Corefile
timeout 90 docker compose -f /tmp/lab-dns-failover/compose.yaml restart resolver
timeout 20 dig @127.0.0.1 -p 5354 +noall +answer app.lab.example A | tee /tmp/lab-dns-failover/backup/app-after.txt
timeout 20 dig @127.0.0.1 -p 5354 +noall +answer lab.example SOA | tee /tmp/lab-dns-failover/backup/soa-after.txt
timeout 30 docker compose -f /tmp/lab-dns-failover/compose.yaml logs --tail=20 probe
timeout 5 sh -c 'date -u +"%FT%TZ stage=ns_switched" >> /tmp/lab-dns-failover/backup/timeline.log'
成功判据:父区 NS 只有新 NS 且 glue 指向 .12;递归缓存返回 .21 和新序列号;探针日志从 old 切到 new;旧权威仍能直接查询到旧记录。失败判据:父区仍返回旧 NS、glue 缺失、递归缓存仍返回 .20、探针持续失败、新权威返回 REFUSED/SERVFAIL。回滚:把父区 NS 改回旧值,恢复缓存 upstream,重启后验证;新权威保持运行,便于排查。
阶段 1 只看到 TTL 从 30 降到 5,探针仍输出 old;对递归缓存连续查询时,TTL 会逐步递减,缓存过期后重新从权威取得 5 秒记录。阶段 2 新权威直接查询已经返回 .21 和新序列号,但父区和递归缓存仍指向旧权威,探针也仍是 old,说明“新权威可用”不等于“已经切换”。阶段 3 的 DS 查询没有答案,DNSKEY 和 RRSIG 也为空,记录的是未签名路径。阶段 4 父区 NS 变为 ns1.new.example.,递归缓存返回 .21、序列号 2026102502,探针在数秒内切到 new;旧权威仍可查询,作为回滚材料保留。
建议把实际时间线整理成下表,“目标耗时”只是演练预算,不是生产 SLO:
| 阶段 | 动作 | 关键观察 | 目标耗时 |
|---|---|---|---|
| 0 | 建立基线 | 父区旧 NS、缓存 .20、探针 old |
— |
| 1 | TTL 30→5 | 权威与缓存 TTL ≤ 5、TTL 递减 | ≤ 1 分钟 |
| 2 | 导入新 zone | 新权威 .21、序列号递增、记录一致 |
≤ 5 分钟 |
| 3 | 检查 DS/DNSKEY | DS 为空或与新 DNSKEY 匹配 | ≤ 2 分钟 |
| 4 | 切父区 NS 与缓存 | 父区新 NS、缓存 .21、探针 new |
≤ 2 分钟 |
| 5 | 回滚或收尾 | 旧 NS、旧记录、探针恢复 old |
≤ 2 分钟 |
dig NS 确认 NS 集合,用 glue 查询确认每个 NS 地址可达。父区已经更新但递归仍返回旧值时,优先怀疑父区 TTL 或解析器缓存,而不是新权威故障。dig 默认走系统解析器,必须显式写 @127.0.0.1 -p 5354,否则可能测到宿主机或公司 DNS。dig 可能仍返回答案,验证型解析器却返回 SERVFAIL。不要把 dig 成功当作 DNSSEC 通过。old,常见原因是连接池、长连接、客户端缓存或负缓存;探针重启只能作为实验手段,不能当作生产修复。app 记录改到 .21 是本次演练的计划内差异,不能把它当成导入错误;www 是 CNAME,验证时要沿链查到最终 A 记录。回滚顺序与变更顺序相反:先恢复父区 NS 和 DS,再恢复递归缓存 upstream,最后验证应用。父区 NS 的 TTL 由父区控制,真实环境不能像普通记录一样提前调低,回滚后要按父区 TTL 等待缓存过期。旧权威、旧 zone 和旧密钥在观察窗口结束前不得删除:
timeout 10 sed 's/^lab IN NS ns1[.]new[.]example[.]$/lab IN NS ns1.old.example./' /tmp/lab-dns-failover/parent/example.zone > /tmp/lab-dns-failover/parent/example.zone.tmp
timeout 10 mv /tmp/lab-dns-failover/parent/example.zone.tmp /tmp/lab-dns-failover/parent/example.zone
timeout 90 docker compose -f /tmp/lab-dns-failover/compose.yaml restart parent
timeout 10 sed 's/forward [.] 172[.]29[.]0[.]12/forward . 172.29.0.11/' /tmp/lab-dns-failover/resolver/Corefile > /tmp/lab-dns-failover/resolver/Corefile.tmp
timeout 10 mv /tmp/lab-dns-failover/resolver/Corefile.tmp /tmp/lab-dns-failover/resolver/Corefile
timeout 90 docker compose -f /tmp/lab-dns-failover/compose.yaml restart resolver
timeout 20 dig @127.0.0.1 -p 5353 +noall +answer +authority lab.example NS
timeout 20 dig @127.0.0.1 -p 5354 +noall +answer app.lab.example A
timeout 20 dig @127.0.0.1 -p 5354 +noall +answer lab.example SOA
timeout 20 docker compose -f /tmp/lab-dns-failover/compose.yaml logs --tail=20 probe
timeout 5 sh -c 'date -u +"%FT%TZ stage=rollback_ok" >> /tmp/lab-dns-failover/backup/timeline.log'
回滚触发条件:父区 NS 无法正确更新、关键记录缺失或值不一致、DNSSEC 验证出现 SERVFAIL、递归缓存持续返回旧地址超过两个 TTL、探针连续失败超过 2 分钟、新提供商控制面不可用。触发后停止后续步骤,由负责人决定继续向前修复还是回滚;不要在两个提供商之间反复切换。
如果新提供商已经接收动态更新、签发了 ACME 证书或产生新记录,回滚前先导出并核对,避免这些数据只存在于新 zone。实验结束只清理本项目,不要对其他 Compose 项目执行 down -v:
timeout 60 docker compose -f /tmp/lab-dns-failover/compose.yaml down -v --remove-orphans
timeout 30 sh -c "docker ps -a --format '{{.Names}}' | grep '^lab-dns-' || true"
timeout 30 rm -rf /tmp/lab-dns-failover
最终验证覆盖委派、权威、缓存、记录和 DNSSEC 五个层面。所有命令都带超时,并且显式指定服务器和端口:
timeout 20 dig @127.0.0.1 -p 5353 +noall +answer +authority lab.example NS
timeout 20 dig @127.0.0.1 -p 5353 +short ns1.old.example A ns1.new.example A
timeout 20 dig @127.0.0.1 -p 5354 +noall +answer app.lab.example A
timeout 20 dig @127.0.0.1 -p 5354 +noall +answer lab.example SOA
timeout 20 dig @127.0.0.1 -p 5354 +noall +answer www.lab.example CNAME
timeout 20 dig @127.0.0.1 -p 5354 +noall +answer demo.apps.lab.example A
timeout 20 dig @127.0.0.1 -p 5354 +noall +answer lab.example MX lab.example TXT lab.example CAA
timeout 20 dig @127.0.0.1 -p 5355 +noall +answer app.lab.example A
timeout 20 dig @127.0.0.1 -p 5356 +noall +answer app.lab.example A
timeout 20 dig @127.0.0.1 -p 5353 +dnssec +norecurse DS lab.example
timeout 20 curl -sS http://127.0.0.1:8080/
timeout 20 curl -sS http://127.0.0.1:8081/
timeout 30 docker compose -f /tmp/lab-dns-failover/compose.yaml logs --tail=20 probe
app 的 .21 和新 SOA 序列号,回滚后是 .20 和旧序列号;MX/TXT/CAA/CNAME/通配符一致,TTL 小于等于 5。.20 和旧序列号,新权威返回 .21 和新序列号;两边差异只有 SOA、NS 和计划内的 app 变更。old 切到 new,或者在回滚后恢复 old,没有持续 probe_failed。lab-dns-* 容器、网络或临时目录。dig 可能掩盖 DNSSEC 故障?dig 可能仍显示正常答案。
小程序版
微信扫码,随时查命令