DNSSEC の信頼チェーンと署名検証
DNSの答えが本物かを暗号署名で証明する仕組みを、ルートから権威まで一段ずつ辿る信頼チェーンとして原理から理解できる。digのadフラグの意味が腑に落ちる。
- 1.DNSSECはレコード集合(RRset)に秘密鍵で署名し、RRSIGとして配布する。検証側はゾーンのDNSKEYで署名を検証し、答えの完全性と真正性を確認する。
- 2.あるゾーンのDNSKEYが本物かは、親ゾーンが置くDSレコード(KSKのハッシュ)で裏取りし、ルート→TLD→権威と委任に沿って信頼が連鎖する。起点はルートのトラストアンカー。
- 3.存在しないことの証明はNSEC/NSEC3が担う。名前を辞書順に並べた隙間を署名付きで示し、その答え自体にもRRSIGが付くため否定応答も偽造できない。
なぜDNSに署名が要るのか
通常の DNS には答えが本物かを確かめる手段がありません。DNS の名前解決内部 で見たとおり、リゾルバはルートから権威まで反復問い合わせで辿りますが、途中の応答が経路上で差し替えられても気づけません。これがキャッシュポイズニングの根です。DNSSEC(DNS Security Extensions)はこの欠落を埋めますが、通信を暗号化するのではない点に注意してください。守るのは秘匿性ではなく、データの**完全性(改ざんされていない)と真正性(本物の権威が出した)**です。盗聴は防がず、偽の答えを掴まされることだけを防ぎます。秘匿性が必要なら別レイヤ、たとえば TLS の役目です。
署名の単位は RRset、RRSIG がそれを覆う
DNSSEC が署名するのは個々のレコードではなく RRset(同じ名前・型・クラスのレコードの集合)です。たとえば www.example.com. の A レコードが2つあれば、その2つをまとめて1つの単位として署名します。署名結果が RRSIG レコードで、対象 RRset と一対一で対応します。
www.example.com. 3600 IN A 203.0.113.10
www.example.com. 3600 IN A 203.0.113.11
www.example.com. 3600 IN RRSIG A 13 3 3600 (
20260720000000 20260620000000 ; 有効期限・開始
12345 example.com. ; キータグ・署名者名
<base64署名> )
検証手順は、対象 RRset を 正準形(canonical form) に並べ直してハッシュし、署名者のゾーンが持つ公開鍵で RRSIG の署名を検証する、というものです。正準化(名前を小文字化し RR を一定順に整列)が必須なのは、サーバー間で並び順や大小文字が揺れても同じバイト列から同じハッシュを得るためです。これが揃わないと同じデータでも署名が一致しません。RRSIG には有効期間(inception/expiration)も入り、過去の署名の再利用(リプレイ)を時間で縛ります。
DNSKEY と二段鍵:KSK と ZSK
署名検証に使う公開鍵を配るのが DNSKEY レコードです。実運用では役割の異なる2つの鍵を使い分けます。
| 鍵 | 正式名 | 署名対象 | 親が指すか | 交換頻度 |
|---|---|---|---|---|
| KSK | Key Signing Key | ゾーンのDNSKEY RRset のみ | DS が KSK を指す | 低い(数年) |
| ZSK | Zone Signing Key | ゾーン内の通常 RRset 全般 | 指さない | 高い(数週〜数カ月) |
なぜ分けるのか。ZSK は大量のレコードに頻繁に署名するため運用上こまめに交換したい。一方 KSK は親ゾーンの DS レコードから参照されており、交換するたびに親への登録更新(手間とリスク)が要る。そこで KSK は DNSKEY RRset だけに署名し、ZSK は実データに署名する、と分業します。これにより ZSK のロールオーバーはゾーン内で完結し、親との連携は KSK だけに限定できます。検証側から見ると、KSK → DNSKEY RRset(ZSK含む)→ ZSK → 各 RRset という二段の信頼がゾーン内に閉じています。
DS レコードが親子をつなぐ
ここが信頼チェーンの要です。あるゾーンの DNSKEY が本物かを、そのゾーン自身の鍵で保証してもらっても循環します。だから保証は親ゾーンが与えます。親は委任の隣に DS(Delegation Signer)レコードを置きます。DS は子の **KSK のハッシュ(ダイジェスト)**です。
重要なのは、DS は親ゾーンに存在し、親の鍵で署名される点です。子の example.com. の DS は親の com. ゾーンに置かれ、com. の ZSK による RRSIG が付きます。NS による委任が「次の行き先」を親が示すのと同じ構図で、DNSSEC では「次の鍵の正しさ」を親が署名付きで示します。だから DS は委任点(ゾーンカット)にしか現れません。
検証の一段は次のように連鎖します。com. の DNSKEY で example.com. の DS の RRSIG を検証 → DS のハッシュが example.com. の DNSKEY(KSK)と一致することを確認 → その KSK で example.com. の DNSKEY RRset の RRSIG を検証 → 中の ZSK で目的の A レコードの RRSIG を検証。各段で「親の署名済み DS が子の鍵を裏書きする」ことを繰り返します。
ルートからの信頼チェーンと検証アルゴリズム
連鎖を一番上まで遡ると、最後はルートゾーン . の DNSKEY に行き着きます。ルートには親がいないので DS を置く相手がいません。そこでリゾルバはルートの KSK を設定で焼き込んでおきます。これが トラストアンカーで、暗号的に検証せず信じる唯一の起点です。検証はこの起点から下へ降りていきます。
verify(name, type):
ルート . の DNSKEY を取得し、トラストアンカー(DS相当)と一致を確認 # 起点
zone = ルート
loop:
child = name に向かって一段深い委任先ゾーン
DS = query(zone, child, DS) とその RRSIG # 親が署名した子の鍵指紋
verify_rrsig(DS, zone の DNSKEY) # 親の鍵で DS を検証
DNSKEY = query(child, child, DNSKEY) とその RRSIG
if hash(DNSKEY の KSK) != DS:
return Bogus # 鍵が DS と不一致
verify_rrsig(DNSKEY, child の KSK) # KSK で鍵束を検証
if child が目的のゾーン:
ans = query(child, name, type) とその RRSIG
verify_rrsig(ans, child の ZSK) # ZSK で答えを検証
return Secure
zone = child # 一段深へ
検証結果は通常 3 状態に分類されます。Secure(チェーンが起点まで繋がり署名も妥当)、Insecure(途中の委任に DS が無く、その先は署名対象外と正当に判断=オプトアウト的に未署名)、Bogus(DS はあるのに署名や鍵が壊れている=改ざんか設定ミス)。リゾルバが Secure と判断すると応答に AD(Authenticated Data)ビットを立てます。dig +dnssec example.com で ad フラグが立つかどうかが、検証が通った証拠です。
検証リゾルバは Bogus を「怪しいけど一応返す」ではなく SERVFAIL として遮断します。これは安全側の設計ですが、親に DS を登録したのに子の署名を止めた(あるいは鍵を入れ替えたのに DS を更新し忘れた)といった運用ミスがそのまま全断につながることを意味します。鍵ロールオーバーは新旧の鍵・DS を重複させる期間(pre-publish/double-signature)を必ず挟みます。
不在証明:NSEC と NSEC3
DNS の基本 で扱った「その名前は存在しない(NXDOMAIN)」という否定応答も、署名できなければ偽造の穴になります。しかし存在しない名前そのものには署名できません。そこで DNSSEC は名前の隙間に署名する発想を採ります。
NSEC はゾーン内の全名前を正準順(おおむね辞書順)に円環状に並べ、各名前から「次に存在する名前」へのポインタを持つレコードです。alpha.example.com. の NSEC が次として gamma.example.com. を指していれば、その間の beta.example.com. は存在し得ないと署名付きで証明できます。問い合わせた名前を挟む NSEC を返し、その NSEC 自体に RRSIG を付けることで、否定応答も改ざん不能になります。
ただし NSEC には弱点があります。隣接名を順に辿ればゾーン内の全名前を列挙(ゾーンウォーク)できてしまう。これを塞ぐのが NSEC3 で、名前を平文ではなくソルト付きハッシュにして並べます。隙間の証明という原理は同じまま、列挙耐性を加えた版です。さらに NSEC3 の opt-out を使うと、未署名の委任を証明から外して大規模 TLD の署名負荷を下げられます。
- 署名の単位は個々の RR ではなく RRset。RRSIG が対象 RRset を覆い、有効期間でリプレイを縛る。
- KSK は DNSKEY RRset だけに署名し DS が指す。ZSK は実データに署名。分業の目的は親連携の最小化と ZSK の頻繁交換。
- DS は親ゾーンに置かれ親の鍵で署名される。子の KSK のハッシュ。委任点にしか現れない。
- 信頼の起点はルートのトラストアンカー(DS で裏付けられない唯一の鍵)。結果は Secure / Insecure / Bogus、Bogus は SERVFAIL。
- 不在証明は NSEC(辞書順の隙間)/ NSEC3(ハッシュ化で列挙耐性)。否定応答にも RRSIG が付く。
一段で言うと
DNSSEC は「RRset を秘密鍵で署名し RRSIG で配り、検証側がゾーンの DNSKEY で確かめる」のが土台で、その鍵の正しさを「親が置く署名済み DS が裏書きする」連鎖でルートのトラストアンカーまで遡ります。存在の否定すら NSEC/NSEC3 で署名するため、肯定も否定も偽造できません。挙動の裏取りには dig +dnssec(RRSIG と ad フラグを確認)と、チェーン全体を一段ずつ検証する delv を使い、どの段で Secure/Bogus が決まったかを必ず確認してください。
ネットワーク Article
DNSSEC の信頼チェーンと署名検証を実務で読む
TL;DRは入口です。実際に選ぶ・使う段階では、何を解決するか、何と比較するか、導入後にどこで詰まるかまで見る必要があります。
解決すること
DNS
比較で見る軸
難易度: advanced / カテゴリ: ネットワーク / タグ数: 5
導入後に効く点
あるゾーンのDNSKEYが本物かは、親ゾーンが置くDSレコード(KSKのハッシュ)で裏取りし、ルート→TLD→権威と委任に沿って信頼が連鎖する。起点はルートのトラストアンカー。
先に潰すリスク
用語だけ覚えても、設計・実装・運用でどこに効くかを確認しないと判断を誤る。
- 難易度
- advanced
- カテゴリ
- ネットワーク
- タグ数
- 5
判断チェックリスト
- 自社の用途が「DNS / DNSSEC」に近いか確認する。
- 強みである「DNSSECはレコード集合(RRset)に秘密鍵で署名し、RRSIGとして配布する。検証側はゾーンのDNSKEYで署名を検証し、答えの完全性と真正性を確認する。」が本当に評価軸になるか確認する。
- 注意点の「用語だけ覚えても、設計・実装・運用でどこに効くかを確認しないと判断を誤る。」を運用で吸収できるか確認する。
- 公開値や仕様値は、対象プラン・対象機種・対象リージョンまで確認する。
- 既存システム、ID、ネットワーク、監視、バックアップとの接続方法を先に洗い出す。
- 小さく試してから、本番移行、権限設計、障害時手順、コスト監視を決める。