はじめに: DNS のセキュリティの脅威と緩和策
ドメイン ネーム システムのオープンな分散設計と User Datagram Protocol(UDP)の使用のため、DNS はさまざまな形式の攻撃に対して脆弱です。パブリックまたは「オープン」な再帰 DNS リゾルバは、受信パケットを許可されたソース IP アドレスのセットに制限しないため、特にリスクがあります。当社では、主に次の 2 種類の攻撃について懸念しています。
- DNS のキャッシュ ポイズニングにつながるなりすまし攻撃。さまざまなタイプの DNS スプーフィングや偽造攻撃が悪用され、正当なサイトから悪意のあるウェブサイトにユーザーをリダイレクトしようとします。これには攻撃者による Kaminsky 攻撃があり、攻撃者は DNS ゾーン全体を権威に制御します。
- サービス拒否(DoS)攻撃。攻撃者は、リゾルバ自体に対して DDoS 攻撃を開始するか、他のリゾルバをハイジャックして他のシステムへの DoS 攻撃を開始します。DNS サーバーを使用して、大規模な DNS レコード / レスポンス サイズを利用して他のシステムに DoS 攻撃を仕掛ける攻撃は、「アンプ攻撃」と呼ばれます。
攻撃の各クラスについては、以下で詳しく説明します。
キャッシュ ポイズニング攻撃
DNS スプーフィング攻撃にはいくつかのバリアントがあり、キャッシュが汚染される可能性がありますが、一般的なシナリオは以下の通りです。
- 攻撃者は、権威 DNS リゾルバを、ドメイン名がクエリであり、そのサーバーが権威でなく、サーバーのキャッシュにある可能性が低いことを問い合わせます。
- リゾルバは、他のネームサーバー(攻撃者が予測できる IP アドレス)にリクエストを送信します。
- その間、攻撃者は、委任されたネームサーバーから発信されたように見える偽造レスポンスで被害者サーバーに殺到します。レスポンスには、攻撃者が制御する IP アドレスに最終的にリクエストされたドメインを解決するレコードが含まれています。これらには解決された名前の応答レコードが含まれていることがあり、悪化した場合、攻撃者が所有しているネームサーバーに権限を委任して、ゾーン全体を制御できるようになる可能性があります。
- 偽造されたレスポンスの 1 つがリゾルバのリクエスト(クエリ名、タイプ、ID、リゾルバのソースポートなど)と一致し、正規のネームサーバーからのレスポンスより前に受信された場合、リゾルバは偽造されたレスポンスを受け入れてキャッシュに保存し、正規のレスポンスを破棄します。
- 不正使用されたドメインやゾーンに対する今後のクエリは、キャッシュから偽の DNS 解決によって解決されます。攻撃者が偽造レスポンスに非常に長い有効期間を指定している場合、偽造レコードは更新されずに、できる限り長くキャッシュに残ります。
Kaminsky 攻撃の詳細については、Kaminsky DNS の脆弱性に関するイラスト付きのガイドをご覧ください。
DoS 攻撃と増幅攻撃
DNS リゾルバは、ネットワーク システムに課せられる通常の DoS 脅威の影響を受けます。ただし、DNS リゾルバはリゾルバを悪用する攻撃者にとって魅力的な攻撃となるため、増幅攻撃が特に問題になります。リクエストとそれに対するサイズが大きいため、追加の帯域幅が確保されます。EDNS0(DNS の拡張メカニズム)をサポートするリゾルバは、返されるパケットサイズがかなり大きいため、特に脆弱になります。
増幅シナリオでは、攻撃が続行されます。
- 攻撃者は、偽の送信元 IP アドレスを使用して、被害者の DNS サーバークエリを送信します。クエリは、同じ偽装された IP アドレスを使用して、単一のシステムまたはシステムのネットワークから送信された可能性があります。クエリとは、攻撃者が元のクエリのサイズを最大数十回1 獲得できることをわかっていたレコードに対するクエリです(したがって、「増幅」という名称です)。
- 被害者のサーバーは、偽装されたリクエストで渡された送信元 IP アドレスにサイズの大きいレスポンスを送信し、システムに負担をかけ、DoS を引き起こします。
リスクの軽減
DNS の脆弱性に対するシステム全体の標準的なソリューションは、DNSSEC です。ただし、これが広く実装されるまで、オープン DNS リゾルバでは、既知の脅威を軽減するために、いくつかの対策を単独で行う必要があります。多くの手法が提案されています。そのほとんどの概要については、IETF RFC 5452: 偽造された回答に対する DNS の復元力を高める対策をご覧ください。Google Public DNS では、次の方法を実装して推奨しています。
- バッファ オーバーフローに対するコードの保護(特に、DNS メッセージの解析とシリアル化を行うコード)。
- マシンリソースのオーバープロビジョニングにより、リゾルバに直接の DoS 攻撃から保護します。攻撃者は IP アドレスを偽造するのが容易なため、IP アドレスやサブネットに基づいてクエリをブロックすることは不可能です。このような攻撃に対処する唯一の効果的な方法は、負荷を吸収することです。
- 単純なキャッシュのポイズニングから保護するために、レスポンス パケットとネームサーバーの信頼性の基本的な妥当性チェックを実装します。これらは、標準に準拠したキャッシュ リゾルバが実行する、標準的なメカニズムとサニテ�� チェックです。
- メッセージにエントロピーを追加する。Kaminsky 攻撃など、高度なスプーフィング/キャッシュ ポイズニング攻撃が行われる可能性を減らすため、エントロピーを追加するための多くの推奨手法があります。以下では、これらの手法のメリット、制限、課題の概要と Google Public DNS での実装方法について説明します。
- 重複するクエリを削除して、「誕生日攻撃」の確率を抑える。
- DoS や増幅攻撃を防ぐためのレート制限リクエスト。
- 帯域幅を最大限に使用してクライアント IP のサービスをモニタリングし、レスポンスとリクエストの最大サイズ比を確認します。
DNSSEC
Domain Name Security Extensions(DNSSEC)標準は、いくつかの IETF RFC(4033、4034、4035、5155)で指定されています。
DNSSEC カウンタ キャッシュ ポイズニング攻撃を実装するリゾルバ。ネームサーバーから受信したレスポンスの真正性を検証します。各 DNS ゾーンは一連の秘密鍵と公開鍵のペアを保持し、DNS レコードごとに一意のデジタル署名が生成され、秘密鍵を使用して暗号化されます。対応する公開鍵は、親ゾーンに属する鍵によって信頼チェーンによって認証されます。DNSSEC 準拠のリゾルバは、正しい署名を含まないレスポンスを拒否します。実際には、秘密鍵にアクセスせずに署名を偽装することはほぼ不可能であるため、DNSSEC によってレスポンスの改ざんを効果的に防止できます。
2013 年 1 月の時点で、Google Public DNS は DNSSEC を完全にサポートしています。DNSSEC 形式のメッセージを受け入れて転送し、レスポンスを検証して正しい認証を行います。他のリゾルバでも同様にすることをおすすめします。
また、IETF RFC 8198: DNSSEC 検証によるキャッシュの積極的な使用で指定されているとおり、NSEC レスポンスもキャッシュに保存されます。これにより、DNSSEC を実装し、NSEC を使用して否定的な回答を返すネームサーバーへの NXDOMAIN クエリを削減できます。
クライアントサイド暗号化トランスポート
Google Public DNS は、暗号化された転送プロトコル、HTTPS over HTTPS、DNS over TLS をサポートしています。これらのプロトコルにより、改ざん、傍受、なりすまし、防止が行われ、クライアントと Google Public DNS 間のプライバシーとセキュリティが大幅に強化されます。DNSSEC を補完し、エンドツーエンドで認証された DNS ルックアップを提供します。
基本的な有効性チェックの実装
一部の DNS キャッシュの破損は、意図的では���く、必ずしも悪質ではなく、リクエストとレスポンスの不一致が原因である場合があります(ネームサーバーの構成ミス、DNS ソフトウェアのバグなど)。少なくとも、DNS リゾルバは、ネームサーバーの応答の信頼性と関連性を検証する必要があります。次の保護策をすべて導入することをおすすめします。
- 送信リクエストに再帰ビットを設定せず、常に委任チェーンを明示的に指定します。再帰ビットを無効にすると、リゾルバは「イテレーション」モードで動作し、別のネームサーバーがユーザーに代わってこれらのクエリを実行することを許可せずに、委任チェーン内の各ネームサーバーを明示的にクエリします。
- 不審なレスポンス メッセージを拒否する。 「不審な」とみなす方法の詳細については、以下をご覧ください。
- 以前のリクエストからキャッシュに保存されたグルーレコードに基づいて、A レコードをクライアントに返さないでください。たとえば、ns1.example.com のクライアント クエリを受け取った場合は、.com TLD ネームサーバーから返されたキャッシュグルーレコードに基づいて A レコードを送信するのではなく、アドレスを再解決する必要があります。
要件を満たしていない返信を拒否する
Google Public DNS は、以下のものをすべて拒否します。
- 解析できないレスポンス、またはレスポンスの形式が正しくない。
- キーフィールドが、リクエスト内の対応するフィールドと一致しないレスポンス。これには、クエリ ID、送信元 IP、送信元ポート、宛先 IP、クエリ名が含まれます。DNS スプーフィング動作の詳細については、RFC 5452 のセクション 3 をご覧ください。
- リクエストに関係のないレコード。
- CNAME チェーンを再構築できないレコードに応答する。
- 回答のネームサーバーが信用できないレコード(回答、権限、または追加セクション)。ネームサーバーの信頼性は、特定のドメインの委任チェーン内の場所によって決定されます。Google Public DNS は委任チェーン情報をキャッシュに保存し、キャッシュに保存された情報に対する各受信レスポンスを検証して、特定のリクエストに対するレスポンスのネームサーバーの信頼性を判断します。
リクエストへのエントロピーの追加
リゾルバが基本的なサニティ チェックを行うと、攻撃者は正当なネームサーバーが行う前に、元のリクエストのクエリ ID、UDP ポート、(レスポンスの)IP アドレス、およびクエリ名に一致するように、被害者のリゾルバにレスポンスを渡す必要があります。
クエリ ID を一意に識別するフィールドの長さは 16 ビットしかないため、残念ながらこれは簡単に達成できません(正しく識別できる確率が 1/65,536 です)。他のフィールドも範囲が限られているため、一意の組み合わせの合計数は比較的少数になります。関連する組み合わせの問題については、RFC 5452 のセクション 7 を���覧ください。
そのため、DNS メッセージの標準形式でリクエスト パケットにできるだけエントロピーを追加して、攻撃者が機会の範囲内で有効なフィールドの組み合わせを正常に照合できるようにする必要があります。次のセクションで説明する手法をすべて使用することをおすすめします。
2022 年 7 月に開催された DNS OARC 38 会議で、ここで紹介した手法の最新のレビューを公開しました。このプレゼンテーションには、ネームサーバー オペレータに関する推奨事項も含まれています。
送信元ポートのランダム化
基本的な手順として、送信リクエスト パケットにデフォルトの UDP ポート 53 の使用を許可したり、複数のポートの割り当てに予測可能なアルゴリズム(単純なインクリメントなど)を使用したりしないでください。1,024 から 65535 までの範囲でシステムで使用できる範囲のポートを使用し、信頼性の高い乱数ジェネレータを使用してポートを割り当てます。たとえば、Google Public DNS は約 15 ビットを使用し、約 32,000 個の異なるポート番号を許可します。
ファイアウォールやロードバランサ、またはネットワーク アドレス変換(NAT)を行うその他のデバイスにサーバーがデプロイされている場合、それらのデバイスで送信パケットのポートがランダム化されないことがあります。NAT デバイスが、ポートの非ランダム化を無効にするように設定されていることを確認してください。
ネームサーバーの選択をランダム化
一部のリゾルバは、ルート、TLD、またはその他のネームサーバーにリクエストを送信する場合、最短距離(レイテンシ)に基づいてネームサーバーの IP アドレスを選択します。宛先 IP アドレスをランダム化して、送信リクエストにエントロピーを追加することをおすすめします。Google Public DNS では、単に、各ゾーンに構成されたネームサーバーの中からランダムにネームサーバーを選び、高速で信頼できるネームサーバーを優先します。
レイテンシが気になる場合は、ラウンドトリップ時間(RTT)バンディングを使用できます。これは、特定のレイテンシしきい値(30 ms、300 ms など)を下回るアドレス範囲内でランダム化することで構成されます。
DNS Cookie
RFC 7873 では、DNS メッセージに 64 ビットの Cookie を追加するための EDNS0 オプションが定義されています。DNS Cookie サポート クライアントには、リクエストに 64 ビットのランダムな Cookie と、必要に応じてサーバー Cookie が含まれます(既知の場合)。サポートしているサーバーが、Cookie オプションを��クエスト��有効����ると検出した場合は、レスポンスにクライアント Cookie と正しいサーバー Cookie が反映されます。サポート クライアントは、レスポンス内のクライアント Cookie を確認することにより、想定されたサーバーからのレスポンスを確認できます。
ネームサーバーが DNS Cookie をサポートしていない場合は、次の 2 つのオプションを使用してエントロピーを追加できます。
クエリ名のケースをランダム化
DNS 標準では、ネームサーバーは名前を大文字と小文字を区別せずに扱う必要があります。たとえば、example.com
と EXAMPLE.COM
の名前は同じ IP アドレスに解決されます2。さらに、少数のネームサーバーを除くすべてが、リクエストに表示されたレスポンスに名前をエコーバックし、元のケースを保持します。
したがって、リクエストにエントロピーを追加するもう一つの方法は、ドメイン名に含まれる文字の大文字と小文字をランダムに変えることです。この手法は「0x20」とも呼ばれます。ビット 0x20 は US-ASCII 文字の大文字表記に使用されているため、IETF のインターネット ドラフトである DNS ラベルのビット 0x20 を使用してトランザクション ID を改善するとして最初に提案されました。この手法では、ネームサーバー レスポンスはクエリ名だけでなく、名前文字列の各文字の大文字と小文字を一致させる必要があります(例: wWw.eXaMpLe.CoM
、WwW.ExamPLe.COm
)。これにより、トップレベル ドメインやルートドメインのクエリにエントロピーがほとんど、またはまったくなくなる可能性がありますが、ほとんどのホスト名で効果的です。
この手法を実装する際に明らかになった重要な課題の 1 つは、想定されるレスポンス動作に従わないネームサーバーがいくつかあることです。
- 一部のネームサーバーは完全な大文字と小文字の区別なしで応答します。リクエストの大文字と小文字にかかわらず、同じ結果を正しく返しますが、レスポンスはリクエスト内の名前の大文字と小文字が完全に一致するわけではありません。
- 他のネームサーバーは DNS 規格に違反し、完全な大文字と小文字を区別して応答します。リクエストの大文字と小文字の違いに応じてまったく同じ名前を処理するか、まったくレスポンスのない NXDOMAIN レスポンス(リクエストの名前の大文字と小文字が完全に一致する)を返します。
- 一部のネームサーバーは、
arpa
ゾーン内の PTR クエリを除いて正常に動作します。
どちらのタイプのネームサーバーでもクエリ名の大文字と小文字を変更すると、望ましくない結果が生じます。最初のグループでは、レスポンスは偽のレスポンスと区別がつきません。2 番目のグループでは、レスポンスは(もしあれば)まったく間違っている可能性があります。
この問題に対する現在の解決策は、標準を正しく適用することがわかっているネームサーバーに対してのみ、ケースのランダム化を使用することです。 また、ログの分析に基づいて、それぞれに適した例外サブドメインをリストします。これらのサーバーからのレスポンスに正しいケースが含まれていない場合、レスポンスは拒否されます。有効なネームサーバーは、送信トラフィックの 70% 以上を処理します。
クエリ名の前にノンス ラベルを追加する
リゾルバがキャッシュから名前を直接解決できない場合、または権威ネームサーバーに直接クエリできない場合は、ルートネームサーバーまたは TLD ネームサーバーの参照に従う必要があります。ほとんどの場合、ルートまたは TLD ネームサーバーへのリクエストは、名前を IP アドレスに解決しようとするのではなく、別のネームサーバーを参照するようになります。このようなリクエストでは、クエリ エントロピーを増やすためにランダムなラベルをクエリ名に貼りつけながら、存在しない名前を解決できないリスクは回避する必要があります。つまり、ノンスのラベルが付いた名前(entriih-f10r3.www.google.com
など)の参照ソース サーバーにリクエストを送信すると、www.google.com
のリクエストと同じ結果が返されます。
実際には、このようなリクエストは送信リクエストの 3% 未満に過ぎませんが、通常のトラフィック(ほとんどのクエリはキャッシュから直接応答するか、単一のクエリによって応答できるため)を想定すると、これらはリゾルバが強制的にリゾルバに発行しようとするリクエストのタイプになります。したがって、この手法は Kaminsky スタイルの悪用を防ぐうえで非常に効果的です。
この手法を実装するには、参照が保証されるリクエスト(Answers セクションのレコードを含まないレスポンス)に対してのみ、ノンスラベルを使用する必要があります。しかしながら、このようなリクエストのセットを定義しようとすると、次のような課題が発生しました。
- 一部の国コード TLD(ccTLD)ネームサーバーは、実際には他の第 2 レベルの TLD(2LD)で信頼できる権限を持っています。2 つのラベルがありますが、2LD は TLD と同じように動作するため、多くの場合、ccTLD ネームサーバーによって処理されます。たとえば、
.uk
ネームサーバーは、mod.uk
ゾーン、nic.uk
ゾーン、したがってwww.nic.uk
、www.mod.uk
などのゾーンに含まれるホスト名についても権威です。つまり、cc ホスト名ネームサーバーにそのようなホスト名の解決をリクエストしても、参照ではなく、信頼できる回答になります。そのようなホスト名にノンスラベルを追加すると、名前が解決できなくなります。 - ジェネリック TLD(gTLD)ネームサーバーは、ネームサーバーに対する権威でないレスポンスを返すことがあります。つまり、ネームサーバーのホスト名が、ドメインのゾーンではなく gTLD ゾーンに存在する場合があります。gTLD は、参照を返すのではなく、データベースに含まれる任意のグルーレコードを使用して、これらのホスト名に対する非権威的な回答を返します。
たとえば、ネームサーバー
ns3.indexonlineserver.com
は、以前はindexonlineserver.com
ゾーンではなく、.COM
gTLD ゾーンにありました。n3.indexonlineserver.com
の gTLD サーバーにリクエストを送信したときに、参照ではなく、IP アドレスを取得しました。ノンスラベルを追加した場合、indexonlineserver.com
への参照を受け取りましたが、ホスト名を解決できませんでした。したがって、gTLD サーバーからの解決が必要なネームサーバーに、ノンスラベルを追加することはできません。 - ゾーンとホスト名の認証局は、時間とともに変化します。これにより、委任チェーンが変更されると、以前は解決済みだった非追加ホスト名が解決できなくなります。
このような課題に対処するため、ノンスラベルを追加できないホスト名の例外を構成しました。Google のサーバーログによると、TLD ネームサーバーが参照以外のレスポンスを返すホスト名です。Google は例外リストを継続的に審査し、将来にわたって有効な状態を維持できるようにしています。
重複するクエリを削除する
DNS リゾルバは、生年月日による攻撃に対して脆弱です。これは、大量の入力を必要としない数学的な「誕生日のパラドックス」を活用しているためです。誕生日攻撃では、被害者のサーバーに偽造レスポンスだけでなく、初期クエリも殺到し、リゾルバが単一の名前解決のための複数のリクエストを発行するように要求します。発行された送信リクエストの数が増えるほど、攻撃者はこれらのリクエストのいずれかと偽造レスポンスを照合する可能性が高くなります。攻撃者は、偽造レスポンスとの照合で 50% の成功率を達成するには、300 の処理中リクエストのみを必要とし、100% 近くで成功すると 700 リクエストが必要になります。
この攻撃手法を防ぐには、送信キューから重複するクエリをすべて破棄する必要があります。たとえば、Google Public DNS では、同じクエリ名、クエリタイプ、宛先 IP アドレスに対して未処理のリクエストを複数許可することはできません。
レート制限クエリ
サービス拒否攻撃の防止は、オープンな再帰 DNS リゾルバに特定の課題をもたらします。
- オープン再帰リゾルバは、増幅攻撃を開始するための魅力的なターゲットです。大容量で信頼性の高いサーバーであり、典型的な権威ネームサーバーよりも大きなレスポンスを生成できます(特に、攻撃者がサイズの大きいレスポンスをキャッシュに挿入できる場合)。オープン DNS サービスのデベロッパーにとっては、サーバーを使用して他のシステムへの攻撃を開始するのを防ぐ義務があります。
- 増幅攻撃は、発生中に検出するのは難しい場合があります。攻撃者は、何千ものオープン リゾルバを介して攻撃を仕掛けることができるため、各リゾルバは全体的なクエリ量のごく一部しか見えず、侵害されたという明確なシグナルを抽出できません。
- 悪意のあるトラフィックは、通常のユーザーに対する DNS サービスの中断や低下を発生させずにブロックする必要があります。DNS は重要なネットワーク サービスであるため、攻撃を遮断してサーバーをシャットダウンするオプションはありません。また、特定のクライアント IP に対��るサービスを長時間にわたって拒否することはできません。リゾルバは、攻撃が開始されるとすぐに攻撃をブロックし、攻撃が終了するとすぐに完全に運用可能なサービスを復元できる必要があります。
DoS 攻撃に対処する最善の方法は、レート制限や「スロットル」の仕組みを講じることです。Google Public DNS は、次の 2 種類のレート管理を実装しています。
- 他のネームサーバーへの送信リクエストのレート管理。リゾルバ サーバーから起動できる DoS 攻撃から他の DNS ネームサーバーを保護するため、Google Public DNS は各ネームサーバーからの送信 IP アドレスに対して、各サービング クラスタからの QPS 上限を適用します。
クライアントへの発信レスポンスのレート制御。リゾルバ サーバーから発生する可能性のある増幅や従来の分散型 DoS(ボットネット)攻撃から他のシステムを保護するため、Google Public DNS はクライアント クエリに対して 2 種類のレート制限を行います。
- 従来のボリューム ベースの攻撃から保護するために、各サーバーではクライアント IP ごとの QPS と平均帯域幅上限が課されます。
- 小規模なクエリへの大きなレスポンスが悪用される増幅攻撃を防ぐために、各サーバーはクライアント IP ごとの最大平均増幅係数を適用します。平均増幅率は、クエリに対するサイズのレスポンスの構成可能な比率であり、サーバーログで観測された過去のトラフィック パターンから決定されます。
1 つの送信元 IP アドレスからの DNS クエリが最大 QPS レートを超えると、超過したクエリは破棄されます。1 つの送信元 IP アドレスからの UDP に対する DNS クエリが平均的な帯域幅または増幅の上限を一貫して超える場合(不定期に大きなレスポンスが渡される場合)、クエリが削除されるか、小規模なレスポンスのみが送信されます。小さいレスポンスは、エラー レスポンスの場合もあれば、切り捨てビットが設定された空のレスポンスの場合もあります。この場合、正当なクエリの多くは TCP で再試行され、成功します。すべてのシステムやプログラムが TCP を介して再試行するわけではありません。クライアントサイドのファイアウォールによって TCP over DNS がブロックされることもあるため、応答が切り捨てられると一部のアプリケーションが正常に動作しなくなる場合があります。ただし、切り捨てにより、ほとんどの場合、RFC 準拠のクライアントは正常に動作します。
-
ドメイン名には大文字と小文字を使用できますが、大文字と小文字は区別されません。つまり、スペルが同じで大文字と小文字が異なる 2 つの名前は、同一のものとして扱われます。