DNSSECで固めるキャッシュポイズニング対策:ネットワークエンジニアの視点

PowerAutomate

インターネットの基盤であるDNSは、ドメイン名とIPアドレスを紐付ける重要な役割を担っています。しかし、その信頼性に疑義が生じると、私たちは意図しないサイトへ誘導されたり、フィッシング詐欺の被害に遭ったりするリスクに晒されます。今回は、DNSの脆弱性を突く「キャッシュポイズニング」から身を守るための強力な盾、DNSSECについて、プロトコル実装に携わるネットワークエンジニアの視点から掘り下げていきます。

背景

DNSはもともと、セキュリティをあまり考慮せずに設計されたプロトコルです。そのため、再帰リゾルバが受け取った応答が本物であるかを検証する仕組みがありませんでした。この脆弱性を悪用するのが「DNSキャッシュポイズニング」です。攻撃者は、偽のDNS応答をリゾルバに送りつけ、正規のドメイン名に誤ったIPアドレスを紐付けさせます。一度キャッシュされてしまうと、そのリゾルバを利用するユーザーは、正規のサイトにアクセスしているつもりでも、実際には攻撃者の用意した偽サイトに誘導されてしまいます。かつてKaminsky氏が発見した攻撃手法は、その影響の大きさから広く知られることとなりました。

このような脅威に対抗するために開発されたのがDNS Security Extensions (DNSSEC) です。DNSSECは、DNS応答の「真正性」と「完全性」を保証するための拡張機能であり、その基盤はRFC 4033, RFC 4034, RFC 4035で定義されています。

設計目標

DNSSECの導入にあたり、主要な設計目標は以下の通りです。

  • データ起点の認証と完全性の保証: DNS応答が改ざんされておらず、信頼できるソースから発行されたものであることを検証可能にする。
  • キャッシュポイズニングの防止: 偽の情報がキャッシュされることを防ぎ、ユーザーが常に正規の情報にアクセスできるようにする。
  • 信頼の連鎖の提供: ルートゾーンから各ゾーンまで、暗号学的な署名によって信頼の連鎖を構築する。
  • 段階的導入のサポート: 既存のDNSインフラに大きな変更を強いることなく、段階的にDNSSECを導入できるようにする。
  • パフォーマンスへの影響の最小化: セキュリティ強化に伴う処理オーバーヘッドを許容範囲に抑える。

詳細

DNSSECは、公開鍵暗号技術を利用してDNSレコードにデジタル署名(RRSIGレコード)を付与し、その署名を検証することでデータの真正性を確認します。

DNSSECの仕組み

  1. デジタル署名 (RRSIG): 各DNSレコードセット (RRset) には、そのゾーンのプライベートキーで署名されたRRSIGレコードが関連付けられます。
  2. 公開鍵 (DNSKEY): ゾーンの公開鍵はDNSKEYレコードとして公開されます。この鍵を使ってRRSIGの署名を検証します。
  3. 委任署名者 (DS) レコード: 親ゾーンは子ゾーンの公開鍵のハッシュ値をDSレコードとして保持し、このDSレコードを親ゾーンの鍵で署名します。これにより、ルートから各ゾーンまで「信頼の連鎖」が構築されます。
  4. 認証済み不在 (NSEC/NSEC3): 存在しないドメイン名やレコードタイプに対する問い合わせに対しても、それが実際に存在しないことを暗号学的に証明します。NSEC3 (RFC 5155) は、NSECの持つゾーン列挙のプライバシー課題を解決するためにハッシュ化された名前を使用します。

DNSSECバリデーター(通常は再帰リゾルバ)は、問い合わせに対する応答を受け取ると、含まれるRRSIGレコードを用いて署名を検証し、さらにDSレコードを辿ってルートゾーンまで信頼の連鎖を検証します。この検証が成功して初めて、その応答を信頼できるものとしてユーザーに返します。

RRSIGレコードの構造例

DNSSECでは、特にRRSIGレコードが重要な情報を含みます。以下にその主要なフィールドを整理します。

RRSIG Record (Simplified)
Owner Name: variable (署名されたRRsetの所有者名)
Type: 16 bits (値: 46, RRSIGを示す)
Class: 16 bits (例: IN)
TTL: 32 bits (レコードの生存期間)
RDLENGTH: 16 bits (RDATAの長さ)
RDATA:
  Type Covered: 16 bits (署名されているRRsetのタイプ, 例: A, MX)
  Algorithm: 8 bits (署名アルゴリズム, 例: RSASHA256は値8)
  Labels: 8 bits (オリジナルRRsetの所有者名のラベル数)
  Original TTL: 32 bits (署名されたRRsetのオリジナルのTTL)
  Signature Expiration: 32 bits (署名の有効期限 - Unix timestamp)
  Signature Inception: 32 bits (署名の開始日時 - Unix timestamp)
  Key Tag: 16 bits (署名に使用されたDNSKEYレコードのKey ID)
  Signer's Name: variable (署名に使用されたDNSKEYレコードの所有者名)
  Signature: variable (デジタル署名データ本体)

Note: Signature ExpirationとSignature Inceptionのフィールドは、署名の有効期間を定義し、リプレイ攻撃などに対する防御機構の一部となります。

DNSSECバリデーションの流れ

DNSSECのバリデーションは、DNSクエリと検証のために複数のステップを踏みます。

sequenceDiagram
    participant Client
    participant "Recursive Resolver"
    participant "Authoritative Server"
    participant "Trust Anchor (e.g., Root DNSKEY)"

    Client ->> "Recursive Resolver": DNS Query (example.com, A)
    "Recursive Resolver" ->> "Authoritative Server": DNS Query (example.com, A)

    alt Initial response attempt failure
        Note over Authoritative Server: サーバー負荷やネットワークの問題
        "Authoritative Server" --x "Recursive Resolver": (Timeout/Drop)
        "Recursive Resolver" ->> "Authoritative Server": DNS Query (example.com, A) [Retransmission]
    end

    "Authoritative Server" -->> "Recursive Resolver": example.com A (RDATA), RRSIG(A)
    "Recursive Resolver" ->> "Authoritative Server": DNS Query (example.com, DNSKEY)
    "Authoritative Server" -->> "Recursive Resolver": example.com DNSKEY (RDATA), RRSIG(DNSKEY)

    "Recursive Resolver" ->> "Trust Anchor": Query for DS record (e.g., .com DS for example.com)
    "Trust Anchor" -->> "Recursive Resolver": .com DS (RDATA), RRSIG(DS)

    Note over Recursive Resolver: RRSIG(A)をexample.com DNSKEYで検証
    Note over Recursive Resolver: RRSIG(DNSKEY)を親ゾーンのDSレコードで検証
    Note over Recursive Resolver: ルートのKSK (Key Signing Key) までDSレコードの連鎖を検証

    "Recursive Resolver" -->> Client: example.com A (Validated)

このシーケンスは、DNSSECを有効にした再帰リゾルバが、権威DNSサーバーからAレコードとその署名、そして署名に使用された公開鍵を取得し、さらに上位のゾーンからDSレコードを辿って最終的に信頼の起点(トラストアンカー)まで検証を行う一連の流れを示しています。途中で応答が失われた場合、リゾルバは自動的に再送を行います。

相互運用性

DNSSECは段階的な導入を前提としており、以下の点で相互運用性が考慮されています。

  • DNSSEC非対応クライアント/リゾルバ: DNSSEC署名付きゾーンであっても、非対応のクライアントやリゾルバは署名情報を無視して通常のDNS応答として扱います。これにより、後方互換性が保たれます。
  • EDNS(0) (RFC 6891): DNSSECレコードは既存のDNSパケットサイズを超えることが多いため、EDNS(0)によってUDPのDNSメッセージサイズを拡張し、TCPへのフォールバックなしに大きな応答を扱えるようにします。
  • DNS over TCP vs. DNS over UDP: 伝統的にDNSはUDPで動作しますが、DNSSECによって応答サイズが大きくなるため、EDNS(0)で対応できない場合はTCPへのフォールバックが必要になります。DNS over QUIC (DoQ, RFC 9250)のような新しいトランスポートプロトコルは、より効率的なセキュアDNS通信を提供しますが、その普及はまだこれからです。

Note: DNSSECの導入には、ゾーンの署名、公開鍵の親ゾーンへの登録、そしてリゾルバでの検証有効化と、多岐にわたる設定が必要です。

セキュリティ考慮事項

DNSSECはDNSのセキュリティを大幅に向上させますが、実装と運用にはいくつかのセキュリティ考慮事項があります。

  • リプレイ攻撃: RRSIGレコードには署名の有効期限 (Signature Inception/Expiration) が含まれており、署名された応答が有効期間外であれば検証は失敗します。これにより、過去の不正な応答が再送されても、その検証は通らないため、リプレイ攻撃に対する耐性を提供します。
  • ダウングレード攻撃: DNSSECが導入されている環境で、攻撃者が意図的にDNSSEC非対応の応答を送りつけたり、DNSSECバリデーションを無効化させたりしようとする攻撃です。リゾルバはトラストアンカーが設定されているゾーンに対しては、常にDNSSEC検証を試みるため、簡単にダウングレードすることはできません。しかし、DANE (DNS-based Authentication of Named Entities, RFC 6698) のようなプロトコルと組み合わせることで、アプリケーション層でのさらなるセキュリティ強化が図れます。
  • キー更新 (Key Rollover): DNSSECの鍵は定期的に更新(ロールオーバー)する必要があります。KSK (Key Signing Key) と ZSK (Zone Signing Key) の2種類があり、それぞれのロールオーバーには異なる手順と注意が必要です。不適切なキー更新は、ゾーンの解決不能(サービス停止)につながる可能性があるため、厳格な手順管理が求められます。
  • 0-RTTの再送リスク: DNSSEC自体にはアプリケーション層での0-RTTメカニズムは組み込まれていません。各クエリの検証は独立しており、トラストアンカーまでの検証チェーン全体が必要です。しかし、もしDNSSECがDoQ (RFC 9250) のような0-RTTをサポートするトランスポートプロトコル上で運用される場合、トランスポート層での0-RTTハンドシェイクにはリプレイ攻撃のリスクが存在します。DNSSECの署名有効期間は、このトランスポート層のリプレイリスクからアプリケーションデータを保護する一助となりますが、0-RTT利用時はトランスポート層の設計も重要となります。
  • NSEC/NSEC3のプライバシー: NSECレコードはゾーン内の全てのドメイン名を列挙可能というプライバシー上の課題がありました。NSEC3レコードは名前をハッシュ化することでこの課題を緩和しますが、ハッシュ値の総当たり攻撃のリスクは残ります。

実装メモ

DNSSECを実装・運用する上で、ネットワークエンジニアとして留意すべき点は多々あります。

  • MTU/Path MTU: DNSSEC応答はしばしばUDPのデフォルトMTU (512バイト) を超えます。EDNS(0)を用いてより大きなUDPバッファサイズ(例: 1232バイト、RFC 6891)を広告し、それでも足りない場合はTCPへのフォールバックが必要です。Path MTU Discovery (PMTUD) はTCP利用時に経路上のMTUを自動的に見つけるのに役立ちますが、UDPではアプリケーション層で対処する必要があります。
  • HOL blocking回避: 再帰リゾルバが複数のDNSSEC検証を同時に処理する場合、一つの遅延が他の処理をブロックする可能性があります (Head-of-Line blocking)。非同期I/Oや並行処理を適切に実装し、この問題を回避することが大切です。
  • キュー制御と優先度: 多数のクエリが集中する環境では、DNSSEC検証のオーバーヘッドによりリゾルバが遅延する可能性があります。重要なシステムからのクエリや、既にキャッシュにあるクエリの優先度を上げるなど、インテリジェントなキュー制御と優先度付けがパフォーマンス維持に貢献します。
  • パフォーマンスモニタリング: DNSSEC検証にはCPUリソースとネットワーク帯域を消費します。DNSSEC導入後は、リゾルバのCPU使用率、メモリ使用量、ネットワークトラフィック、そしてクエリの遅延時間を継続的にモニタリングし、ボトルネックを特定して対策を講じる必要があります。
  • 鍵管理の自動化: キーロールオーバーは手作業で行うとミスが生じやすいため、署名プロセスや鍵の更新を自動化するツール(例: OpenDNSSEC, BINDの dnssec-keymgr)の利用を検討すべきです。

まとめ

DNSSECは、DNSキャッシュポイズニングという長年の課題に対する強力な解決策を提供します。その仕組みは公開鍵暗号に基づく署名検証と信頼の連鎖の構築であり、DNS応答の真正性と完全性を保証します。実装と運用には、鍵管理、パフォーマンス、そして新しいプロトコルとの相互運用性など、複雑な側面が伴います。しかし、インターネット全体のセキュリティを向上させる上で、DNSSECは欠かせないピースです。

私たちがより安全にインターネットを利用するためには、技術の進化だけでなく、それらを正しく理解し、適切に運用するエンジニアの存在が不可欠です。DNSSECの完全な普及は道半ばですが、その価値を理解し、導入を推進していくことが、私たちの未来のインターネットを守る第一歩だと私は信じています。

ライセンス:本記事のテキスト/コードは特記なき限り CC BY 4.0 です。引用の際は出典URL(本ページ)を明記してください。
利用ポリシー もご参照ください。

コメント

タイトルとURLをコピーしました