DNS 协议在设计时没有任何安全机制——查询和应答都是明文传输,没有签名、没有认证、没有加密。任何能拦截 DNS 流量的攻击者都可以伪造应答,将用户导向恶意服务器。这就是 DNS 缓存投毒(Cache Poisoning)和 DNS 劫持的根本原因。
DNSSEC(DNS Security Extensions)通过数字签名解决了 DNS 应答的完整性和真实性问题。从 2005 年 RFC 4033–4035 发布至今已经 20 年,但全球 DNSSEC 签名域名的比例仍然不到 30%,启用验证的递归解析器也仅占约 30%。
为什么?因为 DNSSEC 的工程成本远超预期——密钥管理、签名轮换、响应大小膨胀、调试困难,每一个都是实实在在的运维负担。
本文从工程视角完整拆解 DNSSEC:它怎么工作、怎么部署、怎么排查、以及为什么你可能不需要它。
一、DNS 的安全威胁
1.1 DNS 缓存投毒
DNS 缓存投毒(Cache Poisoning)是 DNSSEC 要解决的核心威胁:
正常解析:
客户端 → 递归解析器 → 权威服务器
← A 记录: 93.184.216.34(真实 IP)
缓存投毒攻击:
攻击者
│
↓ 伪造应答(抢先于权威服务器)
客户端 → 递归解析器 ←──────┘
← A 记录: 6.6.6.6(恶意 IP)
攻击条件:
1. 猜中查询的 Transaction ID(16 位,65536 种可能)
2. 猜中源端口(如果端口固定则更容易)
3. 在真实应答到达之前发送伪造应答
2008 年 Dan Kaminsky
发现的攻击方法让缓存投毒变得极其高效:通过查询不存在的子域名(如
random123.example.com),攻击者可以在短时间内发送大量伪造的权威应答(包含针对
example.com 的恶意 NS 记录),而不受已缓存记录
TTL 的限制。
1.2 DNSSEC 不解决什么
DNSSEC 解决:
✓ 数据完整性 — 应答内容未被篡改
✓ 来源认证 — 应答确实来自权威服务器
✓ 否定存在证明 — 确认某个域名确实不存在
DNSSEC 不解决:
✗ 保密性 — DNS 查询和应答仍然是明文(这是 DoH/DoT 的工作)
✗ DDoS 防护 — DNSSEC 不防止 DNS 放大攻击
✗ 域名注册安全 — 不防止域名被盗或注册商账户被入侵
✗ 最后一英里安全 — 客户端到递归解析器的链路不受保护
二、DNSSEC 核心记录类型
2.1 RRSIG(Resource Record Signature)
RRSIG 是对一组 DNS 记录的数字签名:
example.com. 300 IN A 93.184.216.34
example.com. 300 IN RRSIG A 13 2 300 (
20250815000000 ; 签名过期时间
20250715000000 ; 签名生效时间
12345 ; Key Tag(标识使用的 DNSKEY)
example.com. ; 签名者域名
base64_encoded_signature... )
RRSIG 字段解析:
- A : 被签名的记录类型
- 13 : 算法编号(13 = ECDSAP256SHA256)
- 2 : 标签数量(example.com 有 2 个标签)
- 300 : 原始 TTL
- 20250815... : 签名过期时间
- 20250715... : 签名生效时间
- 12345 : Key Tag(快速定位对应的 DNSKEY)
- example.com.: 签名者的域名
- base64... : 实际的数字签名
2.2 DNSKEY(DNS Public Key)
DNSKEY 记录发布用于验证签名的公钥:
example.com. 86400 IN DNSKEY 257 3 13 (
base64_encoded_public_key_KSK... )
example.com. 86400 IN DNSKEY 256 3 13 (
base64_encoded_public_key_ZSK... )
字段解析:
- 257 : flags,bit 7 = 1(Zone Key)+ bit 15 = 1(SEP/KSK)
257 = KSK(Key Signing Key)
- 256 : flags,bit 7 = 1(Zone Key)+ bit 15 = 0
256 = ZSK(Zone Signing Key)
- 3 : 协议(固定为 3 = DNSSEC)
- 13 : 算法编号(13 = ECDSAP256SHA256)
2.3 DS(Delegation Signer)
DS 记录存放在父域(Parent Zone),是子域 KSK 公钥的哈希值,用于构建信任链:
父域(.com)中的 DS 记录:
example.com. 86400 IN DS 12345 13 2 (
sha256_hash_of_ksk_dnskey... )
字段解析:
- 12345 : Key Tag(与 RRSIG 中的 Key Tag 对应)
- 13 : 算法编号
- 2 : 摘要类型(2 = SHA-256)
- sha256... : KSK DNSKEY 记录的 SHA-256 哈希
2.4 NSEC / NSEC3(否定存在证明)
当查询的域名不存在时,DNSSEC 需要证明”这个域名确实不存在”而不是应答被篡改了:
NSEC(Next Secure):
按字母顺序排列所有域名,每条 NSEC 指向"下一个"存在的域名。
如果查询的域名在两条 NSEC 之间的间隙中,证明不存在。
alpha.example.com. NSEC gamma.example.com. A RRSIG NSEC
→ 证明 beta.example.com 不存在(它在 alpha 和 gamma 之间)
问题: NSEC 允许"Zone Walking"——攻击者可以通过
遍历 NSEC 链枚举出整个域的所有记录名。
NSEC3(带哈希的否定存在证明):
不暴露原始域名,而是使用域名的哈希值排序。
ABC123HASH.example.com. NSEC3 1 0 10 AABB (
DEF456HASH A RRSIG )
→ 使用哈希后的域名,无法直接推断原始域名
NSEC3 参数:
- 1 : 哈希算法(1 = SHA-1)
- 0 : Opt-Out 标志
- 10 : 迭代次数
- AABB : Salt(加盐)
三、信任链(Chain of Trust)
3.1 从根到叶的信任传递
DNSSEC 的信任从根域(Root Zone)开始,逐级向下传递:
信任链:
┌─────────────┐
│ Root Zone │ DNSKEY(根的 KSK + ZSK)
│ (.) │ 由"信任锚"(Trust Anchor)预置在解析器中
└──────┬──────┘
│ DS 记录(.com KSK 的哈希)
│ + RRSIG 签名(用根的 ZSK 签)
↓
┌─────────────┐
│ .com TLD │ DNSKEY(.com 的 KSK + ZSK)
│ │ KSK 的哈希 = 根域中的 DS 记录 → 验证通过
└──────┬──────┘
│ DS 记录(example.com KSK 的哈希)
│ + RRSIG 签名(用 .com 的 ZSK 签)
↓
┌─────────────┐
│ example.com │ DNSKEY(example.com 的 KSK + ZSK)
│ │ KSK 的哈希 = .com 中的 DS 记录 → 验证通过
└──────┬──────┘
│ A 记录: 93.184.216.34
│ + RRSIG 签名(用 example.com 的 ZSK 签)
↓
验证通过 ✓
3.2 KSK 与 ZSK 的分工
为什么需要两把密钥?
如果只用一把密钥:
- 这把密钥既签名所有记录,又提交 DS 到父域
- 需要轮换时,必须同时更新本域所有签名 + 父域的 DS 记录
- 父域的 DS 更新需要跨组织协调(域名注册商 → 注册局)
- 轮换周期长、操作复杂、风险高
KSK/ZSK 双密钥体系:
KSK(Key Signing Key):
- 只签名 DNSKEY 记录集
- 提交 DS 到父域
- 密钥强度高,轮换周期长(1–2 年)
- 可以离线存储
ZSK(Zone Signing Key):
- 签名域中的所有其他记录(A/AAAA/MX/CNAME 等)
- 不需要父域配合
- 轮换频率高(1–3 个月),不影响信任链
- 需要在线(签名服务需要使用)
| 特性 | KSK | ZSK |
|---|---|---|
| 签名范围 | 仅 DNSKEY 记录集 | 其他所有记录 |
| 父域关联 | DS 记录引用 KSK | 无直接关联 |
| 轮换周期 | 1–2 年 | 1–3 个月 |
| 轮换复杂度 | 高(需更新父域 DS) | 低(仅本域操作) |
| 密钥强度 | 较强(RSA 2048+ / ECDSA P-256) | 可稍弱 |
| 存储要求 | 可离线(HSM) | 需在线 |
3.3 信任锚(Trust Anchor)
整个信任链的起点是预置在递归解析器中的根域 KSK 公钥:
# 查看 BIND 的信任锚配置
cat /etc/bind/bind.keys
# 或查看 Unbound 的信任锚
cat /var/lib/unbound/root.key
# 根域当前的 KSK(2017 年轮换后的 KSK-2017)
# Key Tag: 20326
# Algorithm: 8 (RSA/SHA-256)
# 这个密钥预置在所有支持 DNSSEC 的解析器中
# 查看根域的 DNSKEY
dig . DNSKEY +dnssec +short
# 257 3 8 AwEAAaz/tAm8... (KSK,flags=257)
# 256 3 8 AwEAAeJPf9a... (ZSK,flags=256)2018 年 10 月的根域 KSK 轮换是互联网历史上最大规模的密钥轮换操作——需要全球所有支持 DNSSEC 的递归解析器更新信任锚。
四、DNSSEC 部署实战
4.1 使用 BIND 签名域
# 环境: BIND 9.16+ 自动 DNSSEC 签名
# 1. 生成密钥对
cd /etc/bind/keys/
# 生成 KSK(ECDSAP256SHA256,推荐)
dnssec-keygen -a ECDSAP256SHA256 -f KSK example.com
# 输出: Kexample.com.+013+12345
# 生成 ZSK
dnssec-keygen -a ECDSAP256SHA256 example.com
# 输出: Kexample.com.+013+67890# named.conf 配置
zone "example.com" {
type primary;
file "/etc/bind/zones/example.com.zone";
# 启用自动 DNSSEC 签名
dnssec-policy "default";
# 或使用自定义策略
dnssec-policy "custom-policy";
# 密钥目录
key-directory "/etc/bind/keys/";
# 启用内联签名(推荐)
inline-signing yes;
auto-dnssec maintain;
};
# 自定义 DNSSEC 策略
dnssec-policy "custom-policy" {
keys {
ksk key-directory lifetime P1Y algorithm ecdsap256sha256;
zsk key-directory lifetime P3M algorithm ecdsap256sha256;
};
max-zone-ttl P1D;
zone-propagation-delay PT5M;
parent-ds-ttl P1D;
parent-propagation-delay PT1H;
# 签名有效期
signatures-validity P14D; # 签名有效 14 天
signatures-refresh P5D; # 在过期前 5 天重新签名
# NSEC3 配置
nsec3param iterations 0 optout no salt-length 0;
};
4.2 使用 dnssec-signzone 手动签名
# 手动签名流程(适合理解原理)
# 1. 准备未签名的区域文件
cat > example.com.zone << 'EOF'
$TTL 300
@ IN SOA ns1.example.com. admin.example.com. (
2025073001 ; serial
3600 ; refresh
900 ; retry
604800 ; expire
300 ; minimum
)
IN NS ns1.example.com.
IN NS ns2.example.com.
IN A 93.184.216.34
IN MX 10 mail.example.com.
ns1 IN A 93.184.216.1
ns2 IN A 93.184.216.2
www IN A 93.184.216.34
mail IN A 93.184.216.10
EOF
# 2. 签名
dnssec-signzone \
-A \ # 自动生成 NSEC 记录
-3 $(head -c 8 /dev/urandom | od -A n -t x1 | tr -d ' ') \ # NSEC3 带随机 salt
-N INCREMENT \ # 自动递增 serial
-o example.com \ # 域名
-t \ # 打印签名统计
-K /etc/bind/keys/ \ # 密钥目录
example.com.zone
# 输出:
# Verifying the zone using the following algorithms: ECDSAP256SHA256.
# Zone fully signed:
# Algorithm: ECDSAP256SHA256: KSKs: 1 active, 0 stand-by, 0 revoked
# ZSKs: 1 active, 0 stand-by, 0 revoked
# example.com.zone.signed
# 3. 签名后的文件会包含 RRSIG、DNSKEY、NSEC3 等记录
head -30 example.com.zone.signed4.3 向注册商提交 DS 记录
签名完成后,需要向域名注册商提交 DS 记录:
# 生成 DS 记录
dnssec-dsfromkey -2 Kexample.com.+013+12345.key
# example.com. IN DS 12345 13 2 E2D3C916...(SHA-256 摘要)
# 需要提交的信息:
# Key Tag: 12345
# Algorithm: 13 (ECDSAP256SHA256)
# Digest Type: 2 (SHA-256)
# Digest: E2D3C916...
# 通过注册商管理面板或 API 提交
# 各注册商界面不同,通常在 DNS 管理 → DNSSEC 设置中4.4 验证部署结果
# 1. 基本验证
dig example.com +dnssec +short
# 93.184.216.34
# A 13 2 300 20250815000000 20250715000000 67890 example.com. signature...
# 2. 查看所有 DNSSEC 记录
dig example.com DNSKEY +dnssec
dig example.com DS +trace
dig example.com A +dnssec +cd # cd = Checking Disabled
# 3. 验证信任链
# 使用 delv(BIND 自带的 DNSSEC 验证工具)
delv @8.8.8.8 example.com A +rtrace
# ;; fetch: example.com/A
# ;; fetch: example.com/DNSKEY
# ;; fetch: example.com/DS
# ;; fetch: com/DNSKEY
# ;; fetch: com/DS
# ;; fetch: ./DNSKEY
# ; fully validated
# example.com. 300 IN A 93.184.216.34
# 4. 使用 drill 验证(ldns 工具链)
drill -DT example.com
# ;; Chase successful
# 5. 使用 unbound-host 验证
unbound-host -D -v example.com
# example.com has address 93.184.216.34 (secure)
# 6. 在线验证工具
# https://dnsviz.net/ — 可视化信任链
# https://dnssec-analyzer.verisignlabs.com/ — 详细分析五、密钥轮换(Key Rollover)
5.1 ZSK 轮换(Pre-Publication 方法)
ZSK 轮换不需要更新父域的 DS 记录,可以在本域独立完成:
ZSK 轮换时间线(Pre-Publication 方法):
阶段 1: 预发布(Pre-Publish)
T=0: 生成新 ZSK,发布到 DNSKEY 记录集
但仍用旧 ZSK 签名所有记录
┌──────────────────┐
│ DNSKEY: │
│ KSK (不变) │
│ ZSK-old (签名) │
│ ZSK-new (待用) │ ← 新 ZSK 已发布但未使用
│ │
│ RRSIG: ZSK-old │ ← 仍用旧 ZSK 签名
└──────────────────┘
等待时间: ≥ DNSKEY TTL(让所有缓存获取到新 DNSKEY)
阶段 2: 切换签名
T=DNSKEY_TTL: 使用新 ZSK 重新签名所有记录
┌──────────────────┐
│ DNSKEY: │
│ KSK (不变) │
│ ZSK-old (保留) │ ← 旧 ZSK 仍然发布
│ ZSK-new (签名) │ ← 新 ZSK 开始签名
│ │
│ RRSIG: ZSK-new │ ← 新签名
└──────────────────┘
等待时间: ≥ 最大 RRSIG 有效期(让旧签名全部过期)
阶段 3: 移除旧密钥
T=RRSIG_lifetime: 从 DNSKEY 记录集中移除旧 ZSK
┌──────────────────┐
│ DNSKEY: │
│ KSK (不变) │
│ ZSK-new (签名) │ ← 只剩新 ZSK
│ │
│ RRSIG: ZSK-new │
└──────────────────┘
5.2 KSK 轮换(Double-DS 方法)
KSK 轮换需要与父域协调更新 DS 记录:
KSK 轮换时间线(Double-DS 方法):
阶段 1: 新 KSK 生成 + DS 预发布
T=0: 生成新 KSK,向父域提交新 KSK 的 DS
┌──────────────────────┐ ┌─────────────────────┐
│ 本域 DNSKEY: │ │ 父域 DS: │
│ KSK-old (签名) │ │ DS(KSK-old) │
│ KSK-new (待用) │ │ DS(KSK-new) ←新 │
│ ZSK (不变) │ └─────────────────────┘
└──────────────────────┘
等待: 父域 DS 的 TTL(让所有缓存获取到两个 DS)
阶段 2: 切换 KSK 签名
T=parent_DS_TTL: 用新 KSK 签名 DNSKEY 记录集
┌──────────────────────┐ ┌─────────────────────┐
│ 本域 DNSKEY: │ │ 父域 DS: │
│ KSK-old (保留) │ │ DS(KSK-old) │
│ KSK-new (签名) ← │ │ DS(KSK-new) │
│ ZSK (不变) │ └─────────────────────┘
└──────────────────────┘
等待: DNSKEY TTL
阶段 3: 移除旧 KSK 和旧 DS
T=final: 从本域移除 KSK-old,从父域移除 DS(KSK-old)
┌──────────────────────┐ ┌─────────────────────┐
│ 本域 DNSKEY: │ │ 父域 DS: │
│ KSK-new (签名) │ │ DS(KSK-new) │
│ ZSK (不变) │ └─────────────────────┘
└──────────────────────┘
5.3 算法轮换
当需要从旧算法(如 RSA/SHA-256)迁移到新算法(如 ECDSA P-256)时,轮换更复杂:
# 算法轮换要求: 在转换期间必须用两套算法同时签名所有记录
# 因为旧验证器可能不支持新算法
# 1. 生成新算法的 KSK 和 ZSK
dnssec-keygen -a ECDSAP256SHA256 -f KSK example.com
dnssec-keygen -a ECDSAP256SHA256 example.com
# 2. 用新旧两套密钥同时签名
# BIND inline-signing 会自动处理
# 3. 向父域提交新算法的 DS
# 等待传播
# 4. 确认新算法验证通过后,移除旧算法密钥
# 注意: 绝不能在移除旧算法签名之前移除旧 DS
# 否则使用旧缓存的解析器会验证失败六、DNSSEC 验证失败排查
6.1 常见故障模式
DNSSEC 验证失败的常见原因:
1. 签名过期(RRSIG Expired)
- 签名的有效期已过
- 原因: 签名服务故障,未按时重新签名
- 诊断: dig +dnssec,检查 RRSIG 的过期时间
2. DS 与 DNSKEY 不匹配
- 父域的 DS 记录与本域 DNSKEY 的哈希不一致
- 原因: KSK 轮换不完整,或 DS 记录输入错误
- 诊断: 手动计算 DS 哈希并与父域的 DS 比较
3. 信任链断裂
- 中间某一级没有 DS 或 DNSKEY
- 原因: 注册商不支持 DNSSEC,或 DS 被意外删除
- 诊断: dig +trace +dnssec
4. 时钟偏差
- 验证器的系统时间在 RRSIG 的 inception/expiration 窗口外
- 原因: NTP 故障或虚拟机时钟漂移
- 诊断: 检查系统时间和 RRSIG 时间窗口
5. 算法不支持
- 验证器不支持签名使用的算法
- 原因: 使用了太新的算法(如 Ed25519 在旧解析器上)
- 诊断: 检查验证器支持的算法列表
6.2 诊断命令
# 1. 检查 RRSIG 签名时间
dig example.com A +dnssec +noall +answer +comments
# 查看 RRSIG 中的 inception 和 expiration 时间
# 如果 expiration 已过去 → 签名过期
# 2. 追踪信任链
dig example.com A +trace +dnssec
# 逐级显示从根到目标域的解析过程和 DNSSEC 记录
# 3. 使用 delv 做完整验证
delv @8.8.8.8 example.com A +rtrace +vtrace
# +rtrace: 显示查询追踪
# +vtrace: 显示验证追踪(详细显示每一步验证逻辑)
# 4. 验证 DS 与 DNSKEY 匹配
# 获取 DNSKEY
dig example.com DNSKEY +short > dnskey.txt
# 手动计算 DS
dnssec-dsfromkey -f dnskey.txt -2 example.com
# 与父域的 DS 比较
dig example.com DS +short
# 5. 用 Google DNS 的 DNSSEC 调试
dig @8.8.8.8 example.com A +cd # Checking Disabled
# 如果 +cd 能解析但不加 +cd 返回 SERVFAIL
# → 确认是 DNSSEC 验证失败
# 6. 检查否定应答
dig @8.8.8.8 nonexist.example.com A +dnssec
# 查看 NSEC/NSEC3 记录是否正确6.3 紧急恢复
当 DNSSEC 验证失败导致域名全球不可解析时:
# 紧急情况: DNSSEC 验证失败 → 域名对启用 DNSSEC 验证的
# 递归解析器完全不可解析(SERVFAIL)
# 方案一(快速但不推荐): 从注册商删除 DS 记录
# 效果: 域名变为"非 DNSSEC 签名"状态
# 风险: 降级攻击窗口
# 生效时间: 取决于父域 DS 的 TTL(通常 24-48 小时)
# 这在紧急情况下太慢了
# 方案二(推荐): 修复签名
# 1. 如果签名过期: 立即重新签名
rndc sign example.com # BIND 命令
# 2. 如果 DS 不匹配: 更新 DS 记录
# 生成正确的 DS 并提交给注册商
# 方案三: 降低影响范围
# 在修复期间,通过 CDN 或备用域名维持服务
# 通知用户使用不验证 DNSSEC 的解析器(如临时方案)
# 预防措施:
# 1. 监控签名过期时间(至少在过期前 7 天告警)
# 2. 自动化重签名(BIND dnssec-policy 自动处理)
# 3. 测试环境定期模拟密钥轮换七、DNSSEC 的工程成本
7.1 响应大小膨胀
DNSSEC 显著增大 DNS 响应:
| 记录类型 | 无 DNSSEC | 有 DNSSEC | 增幅 |
|---|---|---|---|
| A 记录查询 | ~60 字节 | ~400 字节 | 6.7x |
| DNSKEY 查询 | N/A | ~800 字节 | — |
| 否定应答 | ~100 字节 | ~600 字节 | 6x |
| DS 查询 | N/A | ~300 字节 | — |
工程影响:
1. UDP 512 字节限制
DNSSEC 应答经常超过 512 字节 → 需要 EDNS0 支持更大 UDP 包
或回退到 TCP → 增加延迟和服务器负载
2. DNS 放大攻击
DNSSEC 域名的放大倍数更高
攻击者发送 60 字节请求 → 反射 800 字节响应
放大倍数: ~13x(无 DNSSEC 时约 4x)
3. 带宽消耗
权威服务器的出站带宽增加 5–10 倍
高 QPS 域名需要更多带宽预算
4. 分片风险
超过 MTU(通常 1500 字节)的 UDP 响应会被分片
某些防火墙/NAT 会丢弃 DNS 分片包
→ 导致解析失败
7.2 运维复杂度
DNSSEC 带来的额外运维工作:
密钥管理:
- 生成、存储、备份密钥对
- 定期轮换 ZSK(每 1–3 个月)
- 定期轮换 KSK(每 1–2 年)
- 跨组织协调 DS 记录更新
- KSK 私钥的安全存储(理想情况下用 HSM)
签名管理:
- 确保签名在过期前重新生成
- 监控签名有效期
- 区域文件变更后自动重签名
监控:
- 签名过期告警
- 验证成功率监控
- DS 记录一致性检查
- 信任链完整性验证
故障恢复:
- DNSSEC 故障的影响比普通 DNS 故障更严重
(域名对验证解析器完全不可解析)
- 恢复时间受限于 TTL 和父域更新速度
7.3 部署决策
应该部署 DNSSEC 的场景:
✓ 金融、政府等高安全要求的域名
✓ 域名注册商和 DNS 服务商(基础设施责任)
✓ 使用托管 DNS 服务(CloudFlare/Route53 自动管理)
✓ 已有自动化 DNS 管理基础设施
✓ 需要 DANE(基于 DNS 的证书认证)
可以暂缓的场景:
✗ 小型网站(投入产出比低)
✗ DNS 基础设施由第三方管理且不支持 DNSSEC
✗ 运维团队没有 DNSSEC 经验且无培训计划
✗ 已经使用 DoH/DoT(部分安全需求已被覆盖)
八、托管 DNS 的 DNSSEC 支持
8.1 主流 DNS 服务商的 DNSSEC 支持
| 服务商 | DNSSEC 支持 | 自动密钥管理 | 自动 DS 发布 |
|---|---|---|---|
| Cloudflare | ✓ | ✓(一键启用) | 需手动提交 DS |
| AWS Route 53 | ✓ | ✓(KMS 集成) | 需手动提交 DS |
| Google Cloud DNS | ✓ | ✓ | 需手动提交 DS |
| Azure DNS | ✗(截至 2025) | — | — |
| NS1 | ✓ | ✓ | 需手动提交 DS |
8.2 Cloudflare 一键部署
# Cloudflare 的 DNSSEC 部署最简单:
# 1. 在 Cloudflare Dashboard → DNS → DNSSEC → 点击"Enable DNSSEC"
# Cloudflare 自动:
# - 生成 KSK 和 ZSK(ECDSAP256SHA256)
# - 签名所有记录
# - 自动轮换 ZSK
# - 自动重签名
# 2. Cloudflare 提供 DS 记录信息
# 需要你手动到域名注册商处提交:
# Key Tag: 2371
# Algorithm: 13
# Digest Type: 2
# Digest: ...
# 3. 验证
dig example.com +dnssec
# 应该能看到 RRSIG 记录
# Cloudflare 的优势:
# - 完全自动化的密钥管理
# - 在线签名(不需要预签名整个区域)
# - NSEC3 + Aggressive NSEC 缓存
# - 无额外费用九、DNSSEC 算法选型
9.1 算法对比
| 算法 | 编号 | 密钥大小 | 签名大小 | 性能 | 状态 |
|---|---|---|---|---|---|
| RSA/SHA-1 | 5 | 1024–4096 bit | 128–512 字节 | 慢 | 已废弃 |
| RSA/SHA-256 | 8 | 2048–4096 bit | 256–512 字节 | 慢 | 仍在使用 |
| RSA/SHA-512 | 10 | 2048–4096 bit | 256–512 字节 | 更慢 | 较少使用 |
| ECDSA P-256 | 13 | 256 bit | 64 字节 | 快 | 推荐 |
| ECDSA P-384 | 14 | 384 bit | 96 字节 | 快 | 可用 |
| Ed25519 | 15 | 256 bit | 64 字节 | 最快 | 支持有限 |
| Ed448 | 16 | 448 bit | 114 字节 | 快 | 极少使用 |
9.2 推荐选型
2025 年推荐:
首选: ECDSAP256SHA256(算法 13)
✓ 签名小(64 字节 vs RSA 的 256+ 字节)
✓ 验证快
✓ 所有主流解析器都支持
✓ 减少响应大小膨胀
次选: Ed25519(算法 15)
✓ 性能最好
✓ 签名同样小(64 字节)
✗ 部分旧解析器不支持(约 5% 不支持)
→ 如果你的用户群主要使用现代解析器,可以选择
避免: RSA/SHA-256(算法 8)
✗ 签名大(256+ 字节),增加响应大小
✗ 验证慢
✓ 唯一优势: 兼容性最好
→ 仅在需要兼容非常旧的解析器时使用
十、DNSSEC 监控
10.1 签名过期监控脚本
#!/bin/bash
# check_dnssec_expiry.sh — 监控 DNSSEC 签名过期
# 在签名过期前 7 天、3 天、1 天分别告警
DOMAIN="${1:-example.com}"
WARNING_DAYS=7
CRITICAL_DAYS=3
EMERGENCY_DAYS=1
# 获取最早过期的 RRSIG
EXPIRY=$(dig "$DOMAIN" A +dnssec +noall +answer | \
grep RRSIG | \
awk '{print $9}' | \
sort | head -1)
if [ -z "$EXPIRY" ]; then
echo "UNKNOWN: No RRSIG found for $DOMAIN"
exit 3
fi
# 解析过期时间 (YYYYMMDDHHMMSS)
EXPIRY_EPOCH=$(date -d "${EXPIRY:0:8} ${EXPIRY:8:2}:${EXPIRY:10:2}:${EXPIRY:12:2}" +%s 2>/dev/null)
NOW_EPOCH=$(date +%s)
DAYS_LEFT=$(( (EXPIRY_EPOCH - NOW_EPOCH) / 86400 ))
if [ "$DAYS_LEFT" -le "$EMERGENCY_DAYS" ]; then
echo "EMERGENCY: $DOMAIN RRSIG expires in $DAYS_LEFT days ($EXPIRY)"
exit 2
elif [ "$DAYS_LEFT" -le "$CRITICAL_DAYS" ]; then
echo "CRITICAL: $DOMAIN RRSIG expires in $DAYS_LEFT days ($EXPIRY)"
exit 2
elif [ "$DAYS_LEFT" -le "$WARNING_DAYS" ]; then
echo "WARNING: $DOMAIN RRSIG expires in $DAYS_LEFT days ($EXPIRY)"
exit 1
else
echo "OK: $DOMAIN RRSIG expires in $DAYS_LEFT days ($EXPIRY)"
exit 0
fi10.2 Prometheus 指标
# 使用 Blackbox Exporter 监控 DNSSEC 验证
modules:
dns_dnssec:
prober: dns
timeout: 10s
dns:
query_name: "example.com"
query_type: "A"
valid_rcodes:
- NOERROR
validate_answer_rrs:
fail_if_not_matches_regexp:
- ".*RRSIG.*" # 确保应答包含 RRSIG
# 告警规则
# groups:
# - name: dnssec
# rules:
# - alert: DnssecValidationFailed
# expr: probe_dns_lookup_time_seconds{module="dns_dnssec"} == 0
# and probe_success{module="dns_dnssec"} == 0
# for: 5m
# labels:
# severity: critical
# annotations:
# summary: "DNSSEC validation failed for {{ $labels.instance }}"十一、总结
DNSSEC 从技术上优雅地解决了 DNS 数据完整性问题,但它的工程成本让大多数组织望而却步:
理解威胁模型再做决策。 DNSSEC 防的是 DNS 缓存投毒和应答篡改,不防窃听(那是 DoH/DoT 的事)。如果你的主要威胁是中间人攻击和 DNS 劫持,DNSSEC 是正确的解决方案。如果主要是隐私问题,DoH/DoT 更合适。
KSK/ZSK 双密钥体系是运维的核心。 ZSK 频繁轮换不需要跨组织协调,KSK 轮换需要与注册商/注册局协调更新 DS 记录。理解这个分工才能设计出可维护的密钥管理流程。
响应大小膨胀是最大的技术代价。 ECDSA(算法 13)的签名只有 64 字节,比 RSA 的 256+ 字节小得多。选择 ECDSA P-256 不仅是性能考虑,更是减少 DNSSEC 对 DNS 基础设施影响的关键选择。
如果用托管 DNS,DNSSEC 几乎免费。 Cloudflare 等服务商提供一键部署和全自动密钥管理,将运维成本从”需要 DNSSEC 专家”降低到”点一下按钮”。唯一的手动步骤是向注册商提交 DS 记录。
签名过期是最危险的故障。 一旦 RRSIG 过期,域名对所有启用 DNSSEC 验证的解析器完全不可解析——比普通 DNS 故障更严重。自动化重签名和过期监控是部署 DNSSEC 的硬性前提。
下一篇我们讨论加密 DNS——DoH、DoT 和 DoQ 如何解决 DNSSEC 不覆盖的 DNS 隐私问题,以及它们在企业环境中的工程部署。
下一篇:加密 DNS:DoH、DoT 与 DoQ 的工程部署
同主题继续阅读
把当前热点继续串成多页阅读,而不是停在单篇消费。
网络工程索引
汇总本站网络工程系列文章,覆盖分层模型、以太网、IP、TCP、DNS、TLS、HTTP/2/3、CDN、BGP 与故障诊断。
【网络工程】CDN 架构原理:PoP、边缘节点与 Origin Shield
系统解剖 CDN 的多层缓存架构——从 DNS 调度到 PoP 内部结构、Origin Shield 回源保护、多 CDN 部署策略。结合实际配置和响应头分析,给出 CDN 架构的工程理解。
【网络工程】全局负载均衡:GSLB、DNS 调度与 Anycast
系统讲解全局负载均衡的工程实现:GeoDNS 的原理与精度问题、Anycast 的路由收敛与故障转移、BGP 社区在流量调度中的应用、多活架构的流量切换策略,建立跨地域流量调度的完整知识体系。
【网络工程】DNS 协议解剖:查询格式、记录类型与响应码
DNS 是互联网最基础的目录服务,也是最脆弱的单点之一。本文从 wire format 出发逐字段解析 DNS 报文结构,详解 A/AAAA/CNAME/MX/SRV/TXT/NS/SOA 等记录类型的工程用途,分析 EDNS0 扩展与 DNS over TCP 的触发条件,结合 dig +trace 完整实操展示 DNS 解析的真实链路。