DNSSEC の信頼チェーンと NSEC ウォーキング
DNS 応答を偽装できない理由とゾーンの中身が覗かれる理由。RRSIG/DNSKEY/DS の署名チェーン、KSK/ZSK のロールオーバー、NSEC/NSEC3 の不在証明を原理から押さえ、検証失敗の切り分けと設計判断ができる。
- 1.DNSSEC は各 RRset を ZSK で署名(RRSIG)し、ZSK を含む DNSKEY を KSK で署名、親ゾーンの DS が子の KSK ハッシュを保証する。ルートまで連なる DS→DNSKEY→RRSIG の鎖が信頼チェーンの本体。
- 2.KSK と ZSK を分離するのは更新頻度の違いを吸収するため。ZSK は Pre-Publish、KSK は Double-Signature でロールし、DS の伝播遅延(親の TTL)を待たずに切り替えると検証が壊れる。
- 3.不在証明は「該当名がない」ことを署名付きで示す NSEC/NSEC3。NSEC は名前を平文で連結するためゾーン全体を列挙(ウォーキング)でき、NSEC3 はハッシュ+ソルトで緩和するが総当たりは残る。
DNSSEC が守るのは「機密」ではなく「真正性」
DNSSEC の目的を一言で言うと、DNS 応答が正規のゾーン管理者に由来し、改ざんされていないことを暗号学的に保証することです。守るのは真正性(authenticity)と完全性(integrity)であって、機密性ではありません。応答は暗号化されず、誰でも平文で読めます。ここを取り違えると、後述の NSEC ウォーキング(ゾーンの中身が漏れる問題)が「DNSSEC の欠陥」に見えてしまいますが、そもそも秘匿は守備範囲外なのです。
DNSSEC が解こうとしたのは、キャッシュポイズニングに代表される応答すり替えです。素の DNS は UDP で識別子も狭く、攻撃者が偽の応答を先に返せばリゾルバはそれを信じます。DNSSEC は応答に署名を付け、リゾルバが署名を検証することでこの攻撃を封じます。署名の数学的基盤は 署名方式 を参照してください。
DNSSEC は既存の DNS にいくつかのリソースレコード(RR)タイプを追加して実装されます。RRSIG(署名そのもの)、DNSKEY(検証用の公開鍵)、DS(子ゾーンの鍵への委任)、NSEC/NSEC3(不在証明)です。これらは通常の A や MX と同じく DNS 応答で運ばれ、対応リゾルバだけが検証に使います。
RRSIG・DNSKEY・DS が作る三段の鎖
DNSSEC の信頼チェーンは、署名対象・署名鍵・鍵の委任という三つの役割を別レコードに分けて構成します。
- RRSIG: ある名前・タイプの RRset 単位(同じ名前・同じタイプのレコード群をまとめた集合)に対する署名。個々のレコードではなく集合に署名する点が重要で、これにより一部だけ抜き取る改ざんを防ぎます。署名対象には有効期間(inception/expiration)も含まれ、古い署名の再利用を防ぎます。
- DNSKEY: 署名検証に使う公開鍵を載せるレコード。ゾーンは通常 2 種類の鍵、KSK(Key Signing Key)と ZSK(Zone Signing Key)を持ちます。
- DS(Delegation Signer): 子ゾーンの KSK のハッシュを、親ゾーンに置くレコード。親が子の鍵を保証する「委任の釘」です。
検証リゾルバは下から上へ鎖をたどります。あるレコードの RRSIG を、ゾーンの ZSK(DNSKEY)で検証する。その ZSK を含む DNSKEY RRset の RRSIG を、同じゾーンの KSK で検証する。その KSK が正しいことを、親ゾーンの DS が保証する。親の DS RRset もまた親の ZSK で署名され…と続き、最終的にルートゾーンの KSKに行き着きます。ルートの KSK だけはどこからも委任されないため、リゾルバにトラストアンカーとして焼き込まれています(PKI のルート CA に相当)。
| レコード | 何を署名/保証するか | 置き場所 |
|---|---|---|
| RRSIG | A や MX など各 RRset への署名 | そのゾーン自身 |
| DNSKEY | ZSK と KSK の公開鍵を公開 | そのゾーン自身 |
| DS | 子ゾーンの KSK ハッシュを保証 | 親ゾーン |
DS が「ハッシュ」である点が設計の妙です。子の鍵を更新しても、新旧でハッシュが変わるため親に置く DS だけ差し替えればよく、親に公開鍵全体を持たせる必要がありません。子と親の境界をまたぐ唯一の連結点が DS であり、後述するロールオーバーの難所もここに集中します。
KSK と ZSK を分ける理由
なぜ鍵を 2 つに分けるのか。答えは更新頻度と委任コストの非対称性にあります。
ZSK はゾーン内の全レコードに日常的に署名するため、攻撃面を小さく保ちたく、比較的短い鍵で頻繁に交換します。一方 KSK は DNSKEY RRset だけに署名し、その存在は親の DS から指されています。KSK を換えると親の DS も更新しなければならず、親子間の調整(多くはレジストラ経由)と TTL の伝播待ちが発生します。
もし鍵が 1 つだけなら、日常的な鍵交換のたびに毎回この重い親調整が要ります。KSK(めったに換えない・親と連動)と ZSK(頻繁に換える・ゾーン内で完結)を分離することで、日常の鍵更新を親に触れずに回せるのです。これは設計上の 最小権限 と同種の発想で、影響範囲の広い鍵ほど触る頻度を下げています。
ロールオーバー:署名を切らさずに鍵を入れ替える
鍵交換(ロールオーバー)の鉄則は、検証中のリゾルバが古い鍵で署名を確かめている間は、その古い鍵を消さないことです。リゾルバはキャッシュに古い DNSKEY や DS を TTL の間保持しているため、新旧の重複期間を必ず設けます。鍵ごとに定石が違います。
| 対象 | 手法 | 勘所 |
|---|---|---|
| ZSK | Pre-Publish(事前公開) | 新 ZSK を DNSKEY に先に載せ、十分に伝播してから署名を新鍵へ切替、最後に旧鍵を撤去 |
| KSK | Double-Signature(二重署名) | 新旧 KSK 両方で DNSKEY を署名し公開、親の DS を新 KSK 用に差替え、伝播後に旧 KSK を撤去 |
ZSK の Pre-Publish は「鍵を先に見せておき、後から使う」順序です。リゾルバが新 ZSK をキャッシュ済みになってから新鍵で署名すれば、署名を検証できない瞬間が生じません。KSK の Double-Signature は、DNSKEY を新旧両 KSK で署名してどちらの DS を持つリゾルバでも検証できる状態を作り、その上で親の DS を入れ替えます。
KSK ロールで最も多い事故が、親の DS を更新した「つもり」で旧 KSK を消す、または旧 DS の TTL が切れる前に新 KSK だけにする操作です。リゾルバのキャッシュにまだ旧 DS が残っているのに、対応する旧 KSK がゾーンから消えると、DS→DNSKEY の鎖が切れて SERVFAIL(検証失敗)になります。必ず「親の DS が新旧両方見えている重複期間」を、親側の DS の TTL 以上確保してください。
ルートゾーンの KSK ロールは特別で、トラストアンカー自体の更新になります。これは RFC 5011 の自動更新(新鍵を旧鍵で署名して公開し、リゾルバが一定期間観測してから信頼する hold-down 方式)で配布されます。手動更新に頼ると、更新漏れのリゾルバが一斉に検証不能になるためです。
不在証明:「ない」ことを署名する難問
DNSSEC の難所が不在証明(authenticated denial of existence)です。「その名前は存在しない(NXDOMAIN)」「その名前にそのタイプはない」という否定の応答にも署名が要ります。しかし素朴にやると、問い合わせのたびに「存在しません」という応答をその場で署名する必要があり、秘密鍵をオンラインのサーバーに置くことになって危険です。DNSSEC は秘密鍵をオフラインに保ったまま事前署名する設計を守るため、別の工夫をしました。
その答えが NSEC です。ゾーン内の全名前を辞書順(canonical order)に並べ、隣り合う 2 つの名前の「すき間」を 1 レコードにして事前署名しておきます。たとえば alpha.example の次が gamma.example なら、alpha の NSEC は「次は gamma」と示します。問い合わせが beta.example なら、alpha と gamma の間に落ちる NSEC を返すだけで「beta は存在しない」を事前署名済みの署名付きで証明できます。NSEC は同時に「この名前にはどのタイプが存在するか」のビットマップも持ち、タイプ不在も示せます。
NSEC ウォーキング:不在証明が招くゾーン漏洩
ここで前述の「機密性は守らない」が牙をむきます。NSEC は隣の名前を平文で指すため、攻撃者は適当な名前を問い合わせて NSEC を受け取り、「次の名前」へジャンプし、そこをまた問い合わせて…と数珠つなぎにゾーン内の全名前を列挙できます。これが **NSEC ウォーキング(zone walking)**です。署名は完全に正しく、暗号は破れていません。NSEC が定義上、隣接名を露出しているだけです。社内ホスト名など、ゾーンの中身を知られたくない場合に問題になります。
緩和策が NSEC3 です。名前を平文で連結する代わりに、各名前をハッシュ化し、ハッシュ値を辞書順に並べてすき間を署名します。返るのは元の名前ではなくハッシュなので、単純なウォーキングでは元の名前が分かりません。さらにソルトと反復回数を加え、辞書総当たりのコストを上げます(パスワードハッシュ と同じ発想です)。
NSEC3 が露出するのは「ハッシュ値の列」です。攻撃者はゾーンから NSEC3 を集め、辞書や総当たりで候補名をオフラインにハッシュして一致を探せます(NSEC3 walking)。ハッシュは一方向でも、DNS 名の空間は狭く推測しやすいため、ソルトと反復回数を上げても列挙を遅くするだけで不能にはできません。反復回数の上げすぎはリゾルバの計算負荷を増やし DoS 面を広げるため、現在は反復 0・ソルトなしが推奨されるほどで、NSEC3 は「機密対策」ではなく「ウォーキングの敷居上げ」と理解すべきです。本気の秘匿には別ゾーン分離やオンライン署名方式を検討します。
検証リゾルバの動作:トップダウンに鎖をたどる
検証リゾルバ(validating resolver)は、応答を受け取ると次の手順で信頼チェーンを検証します。
1. ルートの DNSKEY を取得し、焼き込み済みトラストアンカー(ルート KSK)と照合
2. ルートの DS(対象 TLD 用)を ルート ZSK の RRSIG で検証
3. TLD の DNSKEY を取得 → その KSK のハッシュが上の DS と一致するか確認
4. TLD の DS(対象ドメイン用)を TLD ZSK の RRSIG で検証
5. ドメインの DNSKEY → KSK が DS と一致、ZSK が DNSKEY RRSIG で有効か確認
6. 目的の RRset(例 A)を ドメイン ZSK の RRSIG で検証、有効期間も確認
7. すべて成立 → AD(Authenticated Data)ビットを立てて応答を返す
各段で「DS のハッシュ=下位 KSK のハッシュ」「RRSIG が上位の鍵で検証可」を確かめ、一つでも欠ければ SERVFAIL を返します。クライアントから見ると、検証成功は応答ヘッダの AD ビットで示されます。逆に、ゾーンが DNSSEC 未対応なら親に DS がないことを NSEC/NSEC3 で署名付きに証明し、「ここから下は検証対象外」と安全に判定します(これを保証する仕組みがあるからこそ、攻撃者が DS を消して DNSSEC を無効化するダウングレードを防げます)。
信頼チェーンは「RRSIG を ZSK で、DNSKEY を KSK で、KSK を親の DS で、最後はルートのトラストアンカーで」検証する、と順序で言えること。KSK/ZSK 分離の理由(親調整コストの分離)と、ZSK=Pre-Publish・KSK=Double-Signature の対応を押さえること。NSEC が平文隣接ゆえにゾーンウォーキングを許し、NSEC3 はハッシュ+ソルトで「遅くするが防げない」こと。DNSSEC は真正性を守り機密は守らない、という前提が全体を貫く論点です。
まとめ
DNSSEC は各 RRset を RRSIG で署名し、検証鍵を DNSKEY(KSK と ZSK)で公開し、子の KSK を親の DS が保証する三段の鎖を、ルートゾーンのトラストアンカーまで連ねて真正性を保証します。鍵を 2 種に分けるのは、親調整を伴う KSK と日常更新の ZSK で触る頻度を分離するためで、ロールオーバーは ZSK が Pre-Publish、KSK が Double-Signature、そして DS の伝播遅延を待つのが鉄則です。
不在証明は NSEC/NSEC3 が担いますが、機密は守備範囲外のため NSEC は隣接名の平文露出でゾーンウォーキングを許し、NSEC3 もハッシュ化でコストを上げるだけです。検証リゾルバはルートから鎖を下りて各段の DS と RRSIG を確認し、成立すれば AD ビットを立てます。暗号と署名の前提は 暗号の基礎、ハッシュの性質は ハッシュ化と暗号化の違い と合わせて押さえると、DNS の信頼モデル全体が一本の線でつながります。
セキュリティ Article
DNSSEC の信頼チェーンと NSEC ウォーキングを実務で読む
TL;DRは入口です。実際に選ぶ・使う段階では、何を解決するか、何と比較するか、導入後にどこで詰まるかまで見る必要があります。
解決すること
DNSSEC
比較で見る軸
難易度: advanced / カテゴリ: セキュリティ / タグ数: 5
導入後に効く点
KSK と ZSK を分離するのは更新頻度の違いを吸収するため。ZSK は Pre-Publish、KSK は Double-Signature でロールし、DS の伝播遅延(親の TTL)を待たずに切り替えると検証が壊れる。
先に潰すリスク
用語だけ覚えても、設計・実装・運用でどこに効くかを確認しないと判断を誤る。
- 難易度
- advanced
- カテゴリ
- セキュリティ
- タグ数
- 5
判断チェックリスト
- 自社の用途が「DNSSEC / DNS」に近いか確認する。
- 強みである「DNSSEC は各 RRset を ZSK で署名(RRSIG)し、ZSK を含む DNSKEY を KSK で署名、親ゾーンの DS が子の KSK ハッシュを保証する。ルートまで連なる DS→DNSKEY→RRSIG の鎖が信頼チェーンの本体。」が本当に評価軸になるか確認する。
- 注意点の「用語だけ覚えても、設計・実装・運用でどこに効くかを確認しないと判断を誤る。」を運用で吸収できるか確認する。
- 公開値や仕様値は、対象プラン・対象機種・対象リージョンまで確認する。
- 既存システム、ID、ネットワーク、監視、バックアップとの接続方法を先に洗い出す。
- 小さく試してから、本番移行、権限設計、障害時手順、コスト監視を決める。