このページの目次
DNSSEC と DNS のセキュリティ
DNS の設計にはセキュリティが考慮されていませんでした。DNSSEC は、デジタル署名チェーンを用いて、各 DNS レコードに「偽造不可能」な証明を追加します。暗号化は行いません(暗号化は DNS over HTTPS が担当)。改ざん防止が目的であり、その代償として、署名チェーンの維持と関連ドメインの増幅効果が挙げられます。
概要
従来の DNS には暗号学的保護がありません。中間ノードは応答を偽造できます(DNS スプーフィング)。DNSSEC はクエリを暗号化するのではなく、各 DNS レコードに署名し、ルートから対象ドメインまでの信頼チェーンを形成します。リゾルバは、「この A レコードが本当に example.com の権威サーバーによって署名されたものかどうか」を検証できます。その代償として、応答パケットが大きくなる(RRSIG レコードの追加)ことや、ゾーン管理が複雑になる(KSK/ZSK のローテーション)ことが挙げられます。DNSSEC の導入率は約 30%(2024年)ですが、これはプライバシー問題を解決できないためです。そのため、DoH/DoT によって補完されています。
問題: DNS には認証がない
従来の DNS 応答には、暗号学的な保証がありません。攻撃者は以下のようなことが可能です:
- キャッシュポイズニング (Cache Poisoning): 偽の referral/glue を送信 → 再帰型リゾルバがポイズニングされた RR をキャッシュする
- 中間者攻撃: パス上のどこかで DNS 応答を偽造 → クライアントが偽の IP を受信する
DNSSEC の解決策: 各ゾーンに署名を行う → ルートからリーフまでの信頼チェーンを形成 → リゾルバが段階的に検証可能にする。
注意: DNSSEC はクエリを暗号化しません(暗号化 = DoH/DoT/DoQ)。ユーザーは依然として、「ISP がどのドメインを参照したかを見られる」という状態に晒されています。
レコードタイプ
RRSIG (type 46):
RRset 全体の署名(各 RR ごとに個別に署名するものではない!)
RDATA:
Type Covered (2B): 署名対象の RR type
Algorithm (1B): 5=RSA/SHA1 (非推奨), 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 TTL (4B): 元の TTL(RRSIG 自身の TTL ではない!)
Signature Expiration (4B): 署名の有効期限(Unix タイムスタンプ)
Signature Inception (4B): 署名の有効開始時刻
Key Tag (2B): DNSKEY を識別するための数値タグ
Signer's Name (label format): この署名を生成したゾーン(通常はゾーンの apex)
Signature (variable): 実際の署名(RRset の正規化形式に対して計算)
DNSKEY (type 48):
RRSIG の検証に使用されるゾーンの公開鍵
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): 常に 3
Algorithm (1B): RRSIG の Algorithm と同じ
Public Key (variable)
DS (type 43):
KSK のハッシュ値。親ゾーンに格納され、ゾーン間の信頼チェーンを形成する
RDATA:
Key Tag (2B): DNSKEY の key tag と一致
Algorithm (1B): DNSKEY と同じ
Digest Type (1B): 1=SHA-1 (非推奨), 2=SHA-256, 4=SHA-384
Digest (variable): SHA-256(owner name + DNSKEY RDATA)
NSEC (type 47): 存在しないことの認証済み否定
→ 「example.org A? — 存在しないだけでなく、存在しないことを証明できる」
信頼チェーンの検証
リゾルバは以下から開始する: ルート DNSKEY のハッシュ(トラストアンカー、リゾルバにプリセットされている)
www.example.com A を参照する場合:
1. A レコード + RRSIG(署名者=example.com)を受信
2. example.com DNSKEY を参照 → DNSKEY を用いて RRSIG を検証 → OK(ゾーンレベルの信頼)
3. .com ゾーンを参照: DS (example.com) + RRSIG(署名者=.com)
4. .com DNSKEY を参照 → DS の RRSIG を検証 → OK → DNSKEY のハッシュが DS と一致 → OK
5. ルートゾーンを参照: DS (.com) + RRSIG → ルート DNSKEY → トラストアンカーと一致 → OK
→ 完全な信頼チェーン: root → .com → example.com → www.example.com
Key Signing Key (KSK) と Zone Signing Key (ZSK) の違い:
KSK: DNSKEY RRset のみに署名 — 鍵の長さが長い(2048-bit RSA)、変更頻度が低い(1〜2年)
ZSK: ゾーン内の全 RRset に署名 — 鍵の長さが短い(1024-bit RSA または ECDSA)、変更頻度が高い(月単位)
→ KSK/ZSK を分離する理由: ZSK は頻繁にローテーションされる(DNSSEC の署名は頻繁に変更が必要)が、KSK
の変更は親ゾーンで DS を更新する必要があるため、親ゾーンでの操作と伝播遅延が発生する
NSEC3 (RFC 5155)
NSEC の問題点: ゾーン内の存在するすべての名前を列挙可能(NSEC チェーンを辿ると next name が返されるため)
NSEC3: 存在しないことを証明する前に、所有者名に対してハッシュ処理を行う:
NSEC3 レコード:
Hash Algorithm (1): SHA-1
Flags (1): Opt-Out (bit 0)
Iterations (2): ハッシュ反復回数(0-65535、高い反復回数は DoS のリスクとなる)
Salt Length + Salt: ゾーンごとのソルト
Hash Length + Hash (次のハッシュ化された所有者名)
Type Bit Maps: NSEC と同じ
→ NSEC3 チェーンを辿っても「hashed_abc → hashed_def」しか見えない → ゾーンを直接列挙できない
(ただしオフラインでのブルートフォース攻撃は可能。NSEC3 はコストを増加させるのみ)
DANE (RFC 6698)
TLS 証明書に対する信頼を提供するために、CA (Certificate Authority) に代わるもの:
TLSA レコード (_port._protocol.name):
port: 443, 25, ...
protocol: _tcp, _udp, ...
RDATA:
Cert Usage (1B):
0: CA 制約 (PKIX-TA)
1: サービス証明書制約 (PKIX-EE)
2: トラストアンカー主張 (DANE-TA) — 独自の CA を指定
3: ドメイン発行証明書 (DANE-EE) — 自身の証明書または公開鍵を直接指定 → 最も高いセキュリティ!
Selector (1B): 0=完全な証明書, 1=SubjectPublicKeyInfo(公開鍵のみ)
Matching Type (1B): 0=完全一致, 1=SHA-256, 2=SHA-512
Certificate Association Data: ハッシュ値または完全な証明書/公開鍵
検証: クライアントが TLS 証明書を受信 → TLSA レコードを参照 → ハッシュが一致するか? → 信頼
→ PKI/CA が必要ない。CT logs が必要ない。証明書の有効無効は DNSSEC の署名にのみ依存する
→ 問題点: 現在の導入率はほぼゼロ(ブラウザがサポートしていない)
参考
- RFC: 4033-4035, 5155, 6698, 6840 (DNSSEC アルゴリズムの更新)
- ツール:
dig +dnssec,delv @resolver,dnsviz.net
キーワード: DNSSEC, RRSIG, DNSKEY, DS, NSEC, NSEC3, DANE, trust anchor, zone signing, KSK, ZSK