6. 接続処理 (Connection Handling)
6.1. 現在の慣行 (Current Practices)
[RFC1035] のセクション 4.2.2 には次のように記載されています:
-
サーバーは、クライアントが接続の終了を開始すると想定すべきであり、未解決のクライアント要求がすべて満たされるまで、接続の終了を遅らせるべきです。
-
リソースを再利用するために休止状態の接続を閉じる必要がある場合、サーバーは接続が 2 分程度の期間アイドル状態になるまで待機すべきです。特に、サーバーは、SOA および AXFR 要求シーケンス(リフレッシュ操作を開始する)を単一の接続で行えるようにすべきです。サーバーはいずれにせよクエリに答えることができないため、正常なクローズの代わりに一方的なクローズまたはリセットを使用してもよい。
その他のより現代的なプロトコル(例: HTTP/1.1 [RFC7230]、HTTP/2 [RFC7540])は、すべての要求に対してデフォルトで永続的な TCP 接続をサポートしています。その後、接続は通常、一方からの「接続クローズ」信号を介して閉じられます。
[RFC1035] の説明は、サーバーが接続を永続的であると見なすべきであることを明確にしていますが(特に SOA を受信した後)、残念ながら、SOA 以外のクエリに対するクライアントの動作を明確に解釈するのに十分な詳細は提供されていません。さらに、いくつか提案されていますが、DNS にはまだ接続のタイムアウトまたはクローズのためのシグナリングメカニズムがありません。
6.1.1. クライアント (Clients)
DNS クライアントがいつ TCP 接続を閉じるべきかについての明確なガイダンスは現在どの RFC にもなく、DNS クライアントのアイドルタイムアウトに関する具体的な推奨事項もありません。ただし、執筆時点では、クライアントが単一の要求を送信した後に TCP 接続を閉じることが一般的な慣行です(SOA/AXFR の場合を除く)。
6.1.2. サーバー (Servers)
多くの DNS サーバー実装は、長い固定アイドルタイムアウトを使用し、デフォルトで少数の TCP 接続に設定されています。また、TCP 接続管理オプションについてはほとんど提供していません。これには次のような欠点があります:
-
運用経験から、長いサーバータイムアウトは、高負荷時にリソースの枯渇や応答の悪化を容易に引き起こす可能性があることがわかっています。
-
意図的に多くの接続を開いてアイドル状態のままにすると、多くの DNS サーバーはアイドルタイムアウトやその他の接続管理ポリシーを変更してこれを防御する装備が不十分であるため、簡単に TCP サービス拒否 (DoS) 攻撃を引き起こす可能性があります。
-
ゼロ以外のアイドルタイムアウトを持つ永続的な接続を使用してそのようなサーバーに同時に接続しようとする少数のクライアントでも、意図せずに同じ DoS 問題を引き起こす可能性があります。
この DoS は TCP サービスに対してのみであることに注意してください。ただし、これらの場合、運用上の理由でクエリに TCP を使用したいクライアントだけでなく、TC=1 フラグを受信した後に UDP から TCP にフォールバックすることを選択したすべてのクライアントにも影響します。
6.2. 推奨事項 (Recommendations)
以下のセクションには、より一貫性がありスケーラブルな DNS-over-TCP の実装をもたらすことを目的とした推奨事項が含まれています。
6.2.1. 接続の再利用 (Connection Reuse)
DNS over TCP の認識されている欠点の 1 つは、通常 1 RTT に等しい接続セットアップ遅延の追加です。接続セットアップコストを償却するために、クライアントとサーバーの両方が、単一の永続的な TCP 接続を介して複数のクエリと応答を送信することにより、接続の再利用をサポートすべきである (SHOULD)。
TCP 接続を介して複数のクエリを送信する場合、クライアントは、メッセージ ID の衝突を避けるために、その接続上の進行中のクエリの DNS メッセージ ID を再利用してはなりません (MUST NOT)。これは、サーバーが順序外処理(セクション 7 を参照)を実行している可能性がある場合に特に重要です。
6.2.1.1. クエリパイプライニング (Query Pipelining)
歴史的に TCP は主にゾーン転送と切り詰められた応答に使用されてきたため、既存の RFC では TCP 接続を介した DNS クエリのパイプライニングのアイデアについては議論されていません。
UDP と同等のパフォーマンスを実現するために、DNS クライアントはクエリをパイプライン化すべきである (SHOULD)。DNS クライアントがサーバーに複数のクエリを送信する場合、次のクエリを送信する前に未解決の応答を待つべきではありません (SHOULD NOT)。クライアントは、特定のクエリを送信する時間を検討する際に、TCP と UDP を同等に扱うべきである (SHOULD)。
DNS サーバーは、UDP トランスポートで可能なレベルのパフォーマンスを提供するために、パイプライン化されたクエリを並行して処理し、TCP 経由で順序外の応答を送信する必要がある可能性があります。TCP パフォーマンスが重要な場合、クライアントはサーバー処理時間をサーバーおよびトランスポート選択アルゴリズムへの入力として使用すると便利であるとわかるかもしれません。
DNS サーバー(特に再帰)は、パイプライン化されたクエリを受信することを予期しなければなりません (MUST)。サーバーは、UDP の場合と同様に、TCP クエリを並行して処理すべきである (SHOULD)。サーバーは、パイプライン化されたクエリが短期間に連続して受信された場合でも、すべてに応答すべきである (SHOULD)。パイプライン化されたクエリへの応答の処理については、セクション 7 で説明します。
6.2.2. 同時接続 (Concurrent Connections)
意図しないサーバー過負荷のリスクを軽減するために、DNS クライアントは、個々のサーバーに対して行われる同時 TCP 接続の数を最小限に抑えるように注意しなければなりません (MUST)。特定のクライアント/サーバー相互作用については、通常のクエリ用に 1 つ、ゾーン転送用に 1 つ、および TCP の上で使用されている各プロトコル用に 1 つ(たとえば、リゾルバが TLS を使用している場合)以下の接続にすべきであることが推奨されます (RECOMMENDED)。ただし、多くのビジーなゾーンを持つ特定のプライマリ/セカンダリ構成では、運用上の理由から(たとえば、複数のゾーンの同時転送をサポートするため)、ゾーン転送に複数の TCP 接続を使用する必要がある場合があることに注意してください。
同様に、サーバーは、特定のクライアント IP アドレスまたはサブネットに対して処理される同時 TCP 接続の数に制限を設けてもよい (MAY)。これらの制限は、上記のクライアントガイドラインよりもはるかに緩くすべきである (SHOULD)。なぜなら、サーバーは、たとえばクライアント IP アドレスが単一のクライアントに属しているのか、単一のマシン上の複数のリゾルバなのか、それともネットワークアドレス変換 (NAT) を実行するデバイスの背後にある複数のクライアントなのかを知らないからです。
6.2.3. アイドルタイムアウト (Idle Timeouts)
意図しないサーバー過負荷のリスクを軽減するために、DNS クライアントは、個々のサーバーに対して確立された DNS-over-TCP セッションのアイドル時間を最小限に抑えるように注意しなければなりません (MUST)。DNS クライアントは、[edns-tcp-keepalive] などの他のシグナリングメカニズムを使用してアイドルタイムアウトが確立されていない限り、アイドルセッションの TCP 接続を閉じるべきである (SHOULD)。
意図しないサーバー過負荷のリスクを軽減するために、デフォルトのサーバーアプリケーションレベルのアイドル期間は数秒程度にすることが推奨されます (RECOMMENDED) が、特定の値は指定されていません。実際には、アイドル期間は動的に変化する可能性があり、サーバーはリソースが許す限り、アイドル接続をより長い期間開いたままにすることを許可してもよい (MAY)。[RFC1035] で最初に指定されたように、SOA および AXFR 要求シーケンスが単一の接続で行われることを期待するクライアントをサポートするために、通常運用では少なくとも数秒のタイムアウトが推奨されます。サーバーは、高負荷が発生している場合や攻撃を受けている場合に、ゼロタイムアウトを使用してもよい (MAY)。
TCP 経由で配信される DNS メッセージは、複数のセグメントで到着する可能性があります。単一のセグメントを受信した後にアイドルタイムアウトをリセットする DNS サーバーは、「スローリード攻撃」に対して脆弱である可能性があります。このため、サーバーは、DNS メッセージの一部を受信したときではなく、完全な DNS メッセージを受信したときにアイドルタイムアウトをリセットすべきである (SHOULD)。
6.2.4. ティアダウン (Teardown)
通常の運用では、DNS クライアントは通常、アイドル接続で接続の終了を開始します。ただし、ローカルポリシーによって設定されたアイドルタイムアウトを超えた場合、DNS サーバーは接続を閉じることができます。また、攻撃に対する防御やシステムの障害/再起動などの異常な状況下では、どちらかの端で接続を閉じることができます。
すべての未解決の応答を受信する前に接続が閉じた場合、DNS クライアントは未回答のクエリを再試行すべきである (SHOULD)。このドキュメントでは、具体的な再試行アルゴリズムは指定されていません。
すべての保留中の応答が送信される前に DNS クライアントが TCP セッションを閉じた(またはセッションがその他の方法で中断された)ことを DNS サーバーが発見した場合、サーバーはそれらの応答を送信しようとしてはなりません (MUST NOT)。もちろん、DNS サーバーはそれらの応答をキャッシュしてもよい (MAY)。