本页目录
DNSSEC 与 DNS 安全
DNS 设计时没有考虑安全——DNSSEC 用数字签名链给每一条 DNS 记录加上"不可伪造"的证明。它不加密(DNS over HTTPS 做加密),它防篡改——代价是签名链的维护和相关域名的放大效应。
概述
传统 DNS 没有密码学保护:任何中间节点都可以伪造应答(DNS spoofing)。DNSSEC 不加密查询,而是给每个 DNS 记录签名,形成从 root 到目标 domain 的信任链。resolver 可以验证"这个 A record 确实是 example.com 的 authoritative server 签发的"。代价是更大的响应包(RRSIG records)和更复杂的 zone 管理(KSK/ZSK 轮换)。DNSSEC 部署率约 30%(2024),部分原因在于其不能解决隐私问题——所以有 DoH/DoT 补充。
问题: DNS 没有认证
传统 DNS 响应没有任何密码学保证。攻击者可以:
- 缓存投毒 (Cache Poisoning): 发送伪造的 referral/glue → recursive resolver 缓存 poisoned RR
- 中间人攻击: 在路径上伪造 DNS 响应 → 客户端收到假 IP
DNSSEC 解决: 对每个 zone 签名 → 形成从 root 到 leaf 的信任链 → resolver 可逐级验证。
注意: DNSSEC 不加密查询 (加密 = DoH/DoT/DoQ)。用户仍然暴露在: "ISP 看到你查了什么域名"。
记录类型
RRSIG (type 46):
对一组 RRset 的签名 (不是对每个 RR 单独签名!)
RDATA:
Type Covered (2B): 被签的 RR type
Algorithm (1B): 5=RSA/SHA1 (deprecated), 7=RSASHA1-NSEC3-SHA1, 8=RSA/SHA-256,
10=RSA/SHA-512, 13=ECDSA-P256-SHA256, 14=ECDSA-P384-SHA384,
15=ED25519, 16=ED448
Labels (1B): original owner name 的 label 数
Original TTL (4B): 原始 TTL (不是 RRSIG 自己的 TTL!)
Signature Expiration (4B): 签名过期时间 (Unix timestamp)
Signature Inception (4B): 签名生效时间
Key Tag (2B): 用于标识 DNSKEY 的 numeric tag
Signer's Name (label format): 产生此签名的 zone (通常是 zone 的 apex)
Signature (variable): 实际签名 (对 RRset 的 canonical form)
DNSKEY (type 48):
用于验证 RRSIG 的 zone 公钥
RDATA:
Flags (2B):
bit 7 (Zone Key): 1 → 此密钥用于 DNSSEC
bit 15 (Secure Entry Point): 1 → KSK (Key Signing Key),
0 → ZSK (Zone Signing Key)
Protocol (1B): always 3
Algorithm (1B): same as RRSIG Algorithm
Public Key (variable)
DS (type 43):
KSK 的 hash, 存在 parent zone 中 → 形成跨 zone 信任链
RDATA:
Key Tag (2B): 匹配 DNSKEY 的 key tag
Algorithm (1B): 与 DNSKEY 相同
Digest Type (1B): 1=SHA-1 (deprecated), 2=SHA-256, 4=SHA-384
Digest (variable): SHA-256(owner name + DNSKEY RDATA)
NSEC (type 47): authenticated denial of existence
→ "example.org A? — 不仅不存在, 而且能证明不存在"
信任链验证
Resolver 开始于: root DNSKEY hash (trust anchor, 预置在 resolver 中)
查 www.example.com A:
1. 收到 A record + RRSIG (signer=example.com)
2. 查 example.com DNSKEY → 用 DNSKEY 验证 RRSIG → OK (zone-level trust)
3. 查 .com zone: DS (example.com) + RRSIG (signer=.com)
4. 查 .com DNSKEY → 验证 DS 的 RRSIG → OK → DNSKEY hash matches DS → OK
5. 查 root zone: DS (.com) + RRSIG → root DNSKEY → trust anchor match → OK
→ 完整信任链: root → .com → example.com → www.example.com
Key Signing Key (KSK) vs Zone Signing Key (ZSK):
KSK: 只签名 DNSKEY RRset — 密钥长 (2048-bit RSA), 很少换 (1-2 年)
ZSK: 签名 zone 中的所有 RRsets — 密钥短 (1024-bit RSA or ECDSA), 经常换 (月)
→ 分离 KSK/ZSK 原因: ZSK 频繁轮换 (DNSSEC signature 需要频繁换) 但 KSK
换一次需要 parent zone 更新 DS → 父 zone 操作 + 传播延迟
NSEC3 (RFC 5155)
NSEC 的问题: 枚举 zone 中所有存在的 name (遍历 NSEC chain → 返回 next name)
NSEC3: 在证明 nonexistence 之前对 owner name 做 hash:
NSEC3 record:
Hash Algorithm (1): SHA-1
Flags (1): Opt-Out (bit 0)
Iterations (2): hash iterations (0-65535, 高迭代 = DoS 风险)
Salt Length + Salt: per-zone salt
Hash Length + Hash (next hashed owner name)
Type Bit Maps: 与 NSEC 相同
→ 遍历 NSEC3 chain 只看到 "hashed_abc → hashed_def" → 不能直接枚举 zone
(但仍可 offline brute-force, NSEC3 只增加成本)
DANE (RFC 6698)
取代 CA (Certificate Authority) 为 TLS 证书提供信任:
TLSA record (_port._protocol.name):
port: 443, 25, ...
protocol: _tcp, _udp, ...
RDATA:
Cert Usage (1B):
0: CA constraint (PKIX-TA)
1: Service certificate constraint (PKIX-EE)
2: Trust anchor assertion (DANE-TA) — 指定自己的 CA
3: Domain-issued certificate (DANE-EE) — 直接指定本端的证书或公钥 → 最大安全!
Selector (1B): 0=full certificate, 1=SubjectPublicKeyInfo (仅公钥)
Matching Type (1B): 0=exact, 1=SHA-256, 2=SHA-512
Certificate Association Data: hash or exact cert/pubkey
验证: client 收到 TLS certificate → 查 TLSA record → hash matches? → 信任
→ 不需要 PKI/CA, 不需要 CT logs, certificate 有效与否只取决于 DNSSEC 签名
→ 问题: current adoption 几乎为零 (浏览器不支持)
参考
- RFC: 4033-4035, 5155, 6698, 6840 (DNSSEC algorithm updates)
- 工具:
dig +dnssec,delv @resolver,dnsviz.net
Keywords: DNSSEC, RRSIG, DNSKEY, DS, NSEC, NSEC3, DANE, trust anchor, zone signing, KSK, ZSK