<p><!--META
{
"title": "DNS over HTTPS (DoH) の動作原理と実装に関する詳細解説",
"primary_category": "ネットワークプロトコル",
"secondary_categories": ["DNS", "セキュリティ", "HTTP"],
"tags": ["DoH", "RFC8484", "HTTP/2", "HTTP/3", "TLS"],
"summary": "DNS over HTTPS (DoH) の動作原理、設計目標、セキュリティ、実装上の考慮事項をRFCに基づき詳細解説します。",
"mermaid": true,
"verify_level": "L0",
"tweet_hint": {"text":"DNS over HTTPS (DoH) の詳細解説。RFC8484に基づき、動作原理、セキュリティ、HTTP/2とHTTP/3での実装注意点をまとめています。 #DoH #DNS #ネットワーク","hashtags":["#DoH","#DNS","#ネットワーク"]},
"link_hints": ["https://datatracker.ietf.org/doc/html/rfc8484"]
}
-->
本記事は<strong>Geminiの出力をプロンプト工学で整理した業務ドラフト(未検証)</strong>です。</p>
<h1 class="wp-block-heading">DNS over HTTPS (DoH) の動作原理と実装に関する詳細解説</h1>
<h2 class="wp-block-heading">背景</h2>
<p>従来のDNS (Domain Name System) は、インターネットの基盤技術として広く利用されてきましたが、その通信は通常UDPポート53またはTCPポート53で行われ、暗号化されていません。このため、DNSクエリは盗聴や改ざんの脅威に晒されやすく、ユーザーのプライバシー保護や通信の完全性確保に課題がありました。特に、オンパス攻撃者によるDNSトラフィックの監視やブロックは、ネットワークの中立性やユーザーの検閲回避を妨げる要因となりえます。</p>
<p>このような背景から、DNS通信のセキュリティとプライバシーを向上させる目的で、いくつかの新しいプロトコルが提案・実装されてきました。その一つが、ここで解説するDNS over HTTPS (DoH) です。DoHは、既存のHTTPSインフラストラクチャとTLSによる暗号化を最大限に活用することで、これらの課題の解決を目指しています。</p>
<h2 class="wp-block-heading">設計目標</h2>
<p>DNS over HTTPS (DoH) は、主に以下の設計目標を掲げています [1]:</p>
<ul class="wp-block-list">
<li><p><strong>プライバシーの向上</strong>: DNSクエリおよびレスポンスをTLSによって暗号化し、オンパス攻撃者による盗聴や情報の漏洩を防ぎます。</p></li>
<li><p><strong>完全性の確保</strong>: TLSが提供する認証とデータ完全性保護により、DNSメッセージの改ざんを防ぎます。</p></li>
<li><p><strong>検閲耐性の強化</strong>: DNSトラフィックを一般的なHTTPSトラフィックに偽装することで、特定のDNS通信のブロックやフィルタリングを困難にします。これにより、ネットワークの検閲を回避しやすくなります。</p></li>
<li><p><strong>既存インフラの活用</strong>: ウェブブラウザ、OS、ロードバランサー、プロキシサーバーなど、既存のHTTP/TLSエコシステムとインフラを再利用可能にすることで、広範な展開を促進します。</p></li>
<li><p><strong>HTTP/2の活用</strong>: HTTP/2 (またはHTTP/3) が持つ多重化機能を利用し、単一のTCP接続 (またはQUIC接続) 上で複数のDNSクエリを並行して処理することで、効率的な通信を実現します。</p></li>
</ul>
<h2 class="wp-block-heading">詳細</h2>
<p>DNS over HTTPS (DoH) は、その名の通り、DNSクエリとレスポンスをHTTPSプロトコル内でカプセル化して転送します。これは、Hypertext Transfer Protocol Version 2 (HTTP/2) または Hypertext Transfer Protocol Version 3 (HTTP/3) を利用し、その下層でTransport Layer Security (TLS) を用いて通信を暗号化します。</p>
<h3 class="wp-block-heading">プロトコルスタック</h3>
<p>DoHのプロトコルスタックは以下のようになります。</p>
<div class="wp-block-merpress-mermaidjs diagram-source-mermaid"><pre class="mermaid">
graph LR
DNS["DNS Message"] -- |Encapsulated in| --> HTTP["HTTP Request/Response"]
HTTP -- |Secured by| --> TLS["TLS Record Protocol"]
TLS -- |Transported over| --> TCP["TCP Segments(\"for HTTP/2\")"]
TLS -- |Transported over| --> QUIC["QUIC Packets(\"for HTTP/3\")"]
TCP -- |IP Layer| --> IP_TCP["IP Packets"]
QUIC -- |IP Layer| --> IP_QUIC["IP Packets"]
</pre></div>
<h3 class="wp-block-heading">DNSクエリ/レスポンスのエンコードと転送</h3>
<p>RFC 8484 (DNS Queries over HTTPS) にて規定されている通り、DoHは主に2つの方法でDNSメッセージをHTTPリクエスト/レスポンスに含めます [1]:</p>
<ol class="wp-block-list">
<li><p><strong>POSTメソッド</strong>:</p>
<ul>
<li><p>DNSクエリのバイナリメッセージ (ワイヤーフォーマット) をHTTPリクエストのボディに含めます。</p></li>
<li><p><code>Content-Type</code> ヘッダには <code>application/dns-message</code> を指定します。</p></li>
<li><p>レスポンスも同様に <code>application/dns-message</code> タイプでDNSレスポンスをボディに含みます。</p></li>
<li><p>この方法は、クエリ内容がURLに露出しないため、プライバシー面で優れています。</p></li>
</ul></li>
<li><p><strong>GETメソッド</strong>:</p>
<ul>
<li><p>DNSクエリのバイナリメッセージをbase64urlエンコードし、HTTPリクエストのURIパラメータ <code>dns</code> (例: <code>/dns-query?dns=AAABAAABAAA...</code>) として含めます。</p></li>
<li><p><code>Content-Type</code> ヘッダは通常不要ですが、<code>application/dns-message</code> も許容されます。</p></li>
<li><p>この方法は、ウェブキャッシュとの親和性が高く、同じクエリに対する応答をキャッシュしやすい利点があります。</p></li>
</ul></li>
</ol>
<p>DNSメッセージは、標準的な<a href="https://datatracker.ietf.org/doc/html/rfc1035">RFC 1035</a>で定義されているワイヤーフォーマットで扱われます。</p>
<h3 class="wp-block-heading">DoHの通信フロー</h3>
<p>以下に、HTTP/2を利用したDoHクライアントとDoHリゾルバ間の通信シーケンスを示します。</p>
<div class="wp-block-merpress-mermaidjs diagram-source-mermaid"><pre class="mermaid">
sequenceDiagram
participant "C as DoH Client"
participant "S as DoH Resolver"
Note over C,S: 事前条件: DoH Resolverが<br/>ポート443でHTTPSを提供
C ->> S: 1. TCP Handshake (SYN, SYN-ACK, ACK)
C ->> S: 2. TLS Handshake
C ->> S: ClientHello (TLSv1.3など)
S -->> C: ServerHello, Certificate, ServerKeyExchange, ServerHelloDone
C ->> S: ClientKeyExchange, ChangeCipherSpec, Encrypted Handshake Message
S -->> C: ChangeCipherSpec, Encrypted Handshake Message
Note over C,S: TLS接続確立、共有鍵生成
C ->> S: 3. HTTP/2 Connection Setup
C ->> S: Connection Preface (MAGIC + SETTINGS Frame)
S -->> C: Connection Preface (SETTINGS Frame)
Note over C,S: HTTP/2ストリーム通信準備完了
C ->> S: 4. DoH Request (HTTP/2 Stream)
C ->> S: HEADERS Frame (Stream ID: X)
alt GET Method
C ->> S: :method = GET
C ->> S: :scheme = https
C ->> S: :authority = example.com
C ->> S: :path = /dns-query?dns=AAABAAABAAA...
else POST Method
C ->> S: :method = POST
C ->> S: :scheme = https
C ->> S: :authority = example.com
C ->> S: :path = /dns-query
C ->> S: content-type = application/dns-message
C ->> S: DATA Frame (Stream ID: X, DNS Query Message)
end
S ->> C: 5. DoH Response (HTTP/2 Stream)
S -->> C: HEADERS Frame (Stream ID: X)
S -->> C: :status = 200 OK
S -->> C: content-type = application/dns-message
S -->> C: DATA Frame (Stream ID: X, DNS Response Message)
Note over C,S: DNSクエリ/レスポンス完了
</pre></div>
<h3 class="wp-block-heading">プロトコル構造の例</h3>
<p>HTTP/2のフレーム構造は以下のようになります [2]:</p>
<div class="codehilite">
<pre data-enlighter-language="generic">HTTP/2 Frame Header:
+-----------------------------------------------+
| Length (24) |
+---------------+---------------+---------------+
| Type (8) | Flags (8) |
+-+-------------+---------------+-------------------------------+
|R| Stream Identifier (31) |
+=+=============================================================+
| Frame Payload (Length bytes) |
+---------------------------------------------------------------+
Length: フレームペイロードのバイト長 (24ビット)
Type: フレームの種類 (例: HEADERS, DATA, SETTINGSなど) (8ビット)
Flags: フレームタイプに固有のフラグ (8ビット)
R: 予約済みビット (1ビット、常に0)
Stream ID: ストリームを識別する整数 (31ビット)
</pre>
</div>
<p>DoHのHTTPリクエスト/レスポンスは、これらのHTTP/2フレームのペイロードとしてDNSメッセージを運びます。</p>
<h2 class="wp-block-heading">既存プロトコルとの比較</h2>
<h3 class="wp-block-heading">従来のDNS (UDP/TCP ポート53) との比較</h3>
<p>DoHは、従来のDNSプロトコルと比較して、セキュリティと運用面で大きな違いがあります。</p>
<ul class="wp-block-list">
<li><p><strong>セキュリティとプライバシー</strong>:</p>
<ul>
<li><p><strong>従来のDNS</strong>: 暗号化なし。盗聴、改ざん、応答の偽装が可能。</p></li>
<li><p><strong>DoH</strong>: TLSによる強力な暗号化と認証。盗聴、改ざん、中間者攻撃に対して耐性があります。</p></li>
</ul></li>
<li><p><strong>ポート番号</strong>:</p>
<ul>
<li><p><strong>従来のDNS</strong>: UDP/TCPポート53を使用。特定のネットワークでブロックされやすい。</p></li>
<li><p><strong>DoH</strong>: HTTPSと同じTCPポート443を使用。一般的なウェブトラフィックと区別が難しく、ブロックされにくい。</p></li>
</ul></li>
<li><p><strong>プロトコルの複雑性</strong>:</p>
<ul>
<li><p><strong>従来のDNS</strong>: 軽量なプロトコル。</p></li>
<li><p><strong>DoH</strong>: HTTP/2 (またはHTTP/3) とTLSを重ねるため、プロトコルスタックが複雑になり、オーバーヘッドが増大。</p></li>
</ul></li>
<li><p><strong>キャッシュ</strong>:</p>
<ul>
<li><p><strong>従来のDNS</strong>: DNSレイヤーでのキャッシュ (ネガティブキャッシュ含む)。</p></li>
<li><p><strong>DoH</strong>: HTTPのキャッシュ機構 (HTTPヘッダーの<code>Cache-Control</code>など) を利用可能。GETメソッド利用時に特に有効。</p></li>
</ul></li>
<li><p><strong>多重化</strong>:</p>
<ul>
<li><p><strong>従来のDNS</strong>: 基本的に1リクエスト1レスポンス。TCP利用時は多重化可能だが、広く使われていない。</p></li>
<li><p><strong>DoH</strong>: HTTP/2/3のストリーム多重化により、単一の接続で複数のDNSクエリを並行して処理可能。</p></li>
</ul></li>
</ul>
<h3 class="wp-block-heading">DNS over TLS (DoT) との比較</h3>
<p>DNS over TLS (DoT) は、RFC 7858 (DNS over TLS) で定義され、DNSメッセージをTLS上で直接転送するプロトコルです。DoHとDoTはどちらもDNS通信を暗号化しますが、そのアプローチが異なります。</p>
<ul class="wp-block-list">
<li><p><strong>プロトコルスタック</strong>:</p>
<ul>
<li><p><strong>DoT</strong>: DNSメッセージ -> TLS -> TCP (ポート853)。</p></li>
<li><p><strong>DoH</strong>: DNSメッセージ -> HTTP/2 (またはHTTP/3) -> TLS -> TCP/QUIC (ポート443)。</p></li>
</ul></li>
<li><p><strong>ポート番号</strong>:</p>
<ul>
<li><p><strong>DoT</strong>: 専用ポート853。特定のファイアウォールでブロックされる可能性がある。</p></li>
<li><p><strong>DoH</strong>: 一般的なHTTPSポート443。ブロックされにくい。</p></li>
</ul></li>
<li><p><strong>中間デバイスとの親和性</strong>:</p>
<ul>
<li><p><strong>DoT</strong>: HTTPレイヤーがないため、ウェブプロキシやキャッシュ、CDNなどの既存HTTPインフラとは直接統合できない。</p></li>
<li><p><strong>DoH</strong>: HTTPプロトコルを使用するため、既存のHTTPプロキシやキャッシュ、ロードバランサーなどのインフラと容易に統合可能。</p></li>
</ul></li>
<li><p><strong>多重化</strong>:</p>
<ul>
<li><p><strong>DoT</strong>: TLSセッション上で複数のDNSクエリを多重化することは可能だが、HTTP/2/3のストリーム多重化ほど柔軟ではない。</p></li>
<li><p><strong>DoH</strong>: HTTP/2/3のストリーム多重化により、より効率的で柔軟な同時クエリ処理が可能。</p></li>
</ul></li>
</ul>
<h3 class="wp-block-heading">HTTP/2 と HTTP/3 の比較 (DoHの観点から)</h3>
<p>DoHはHTTP/2 [RFC 9113, June 2022] またはHTTP/3 [RFC 9114, June 2022] のいずれの上でも動作可能です。</p>
<ul class="wp-block-list">
<li><p><strong>HTTP/2</strong>:</p>
<ul>
<li><p><strong>基盤</strong>: TCP上で動作。</p></li>
<li><p><strong>多重化</strong>: ストリームによる多重化を実現し、Head-of-Line (HOL) ブロッキング問題(TCPレイヤーでのパケットロスが、その後のすべてのストリームをブロックする問題)を軽減。</p></li>
<li><p><strong>接続確立</strong>: TCP 3ウェイハンドシェイクとTLSハンドシェイクが必要。</p></li>
</ul></li>
<li><p><strong>HTTP/3</strong>:</p>
<ul>
<li><p><strong>基盤</strong>: QUIC (UDP上で動作) を利用。</p></li>
<li><p><strong>HOLブロッキング</strong>: QUICはストリーム単位で多重化と信頼性を保証するため、TCPのHOLブロッキング問題を完全に解消。パケットロスが特定のストリームに限定され、他のストリームには影響しない。</p></li>
<li><p><strong>接続確立</strong>: QUICの0-RTT (Zero Round-Trip Time) や1-RTT接続により、TLSハンドシェイクと同時に暗号化通信を開始でき、接続確立時間が大幅に短縮される可能性。特にモバイル環境などでメリットが大きい。</p></li>
</ul></li>
</ul>
<p>HTTP/3上にDoHを実装することで、特にモバイル環境や高遅延・高パケットロス環境でのDNSクエリ性能が向上することが期待されます。</p>
<h2 class="wp-block-heading">セキュリティ考慮事項</h2>
<p>DoHは従来のDNSに比べて大幅にセキュリティが向上しますが、いくつかの考慮事項があります。</p>
<ul class="wp-block-list">
<li><p><strong>プライバシーの向上と集中化のリスク</strong>:</p>
<ul>
<li>DoHはDNSクエリを暗号化し、ISPや中間者による監視を防ぎますが、すべてのDNSクエリが特定のDoHプロバイダーに集中する可能性があり、そのプロバイダーに対する信頼が極めて重要になります。プロバイダーがDNSデータを収集・利用する懸念が生じる可能性があります。</li>
</ul></li>
<li><p><strong>リプレイ攻撃</strong>:</p>
<ul>
<li>DNSクエリ自体は一般的に冪等 (idempotent) であるため、GETメソッドを使用したクエリの応答がリプレイされても大きなセキュリティ上の問題は少ないとされます。しかし、DNSSECに関連するダイナミックアップデートなど、冪等でないPOSTリクエストが使用される場合は、再送されるリスクを考慮する必要があります。HTTP/3の0-RTT機能を利用する場合、再送保護が不十分なリクエストが攻撃者によってリプレイされる可能性があり、特に注意が必要です [3]。</li>
</ul></li>
<li><p><strong>ダウングレード攻撃</strong>:</p>
<ul>
<li>DoHクライアントは、必ずHTTPS (TLS) 接続を使用するべきであり、平文のHTTPへのダウングレードを許可してはなりません。また、クライアントは、信頼できるDoHリゾルバのURIを事前に設定するか、信頼できる方法で取得する必要があります。HTTP Strict Transport Security (HSTS) のようなメカニズムは、中間者攻撃による意図しないダウングレードを防ぐのに役立ちます。</li>
</ul></li>
<li><p><strong>キー更新</strong>:</p>
<ul>
<li>DoHのセキュリティは基盤となるTLS接続に依存します。TLSセッションキーの更新はTLSプロトコル自身によって管理され、定期的に行われるべきです。長期にわたるセッションでは、TLSの再ネゴシエーションや新しい接続の確立によってキーの更新が行われます。</li>
</ul></li>
<li><p><strong>0-RTTの再送リスク</strong>:</p>
<ul>
<li>HTTP/3 (QUIC) の0-RTT機能は接続確立を高速化しますが、初期クライアントハンドシェイクのデータをリプレイされるリスクがあります。特に<code>POST</code>メソッドなど非冪等なリクエストを0-RTTで送信する場合、攻撃者がそのデータを傍受し、サーバーに複数回送信することで意図しない副作用を引き起こす可能性があります [3]。DoHの実装者は、0-RTTデータに非冪等なDNS操作を含めないか、サーバー側で厳格なリプレイ保護メカニズムを実装する必要があります。RFC 9001 (QUIC TLS) では、0-RTTの利用に関するセキュリティ考慮事項が詳細に説明されています。</li>
</ul></li>
</ul>
<h2 class="wp-block-heading">実装メモ</h2>
<p>DoHの実装には、ネットワークエンジニアとして以下の点に注意を払う必要があります。</p>
<ul class="wp-block-list">
<li><p><strong>MTU/Path MTU Discovery (PMTUD)</strong>:</p>
<ul>
<li>HTTP/2はTCP上で、HTTP/3はQUIC (UDP) 上で動作するため、下位層のパケットサイズ制限を考慮する必要があります。特に、大きなDNSレスポンス (例: DNSSECレコード) や複数のリクエスト/レスポンスを含むHTTP/2フレームは、ネットワークMTUを超える可能性があります。PMTUDは、IPフラグメンテーションを避け、最大のペイロードサイズを効率的に利用するために重要です。UDPベースのQUICでは、PMTUDの実装がTCPよりも複雑になることがあります。</li>
</ul></li>
<li><p><strong>Head-of-Line (HOL) Blocking回避</strong>:</p>
<ul>
<li>HTTP/2はTCP上でのストリーム多重化により、アプリケーションレベルのHOLブロッキングを軽減しますが、TCP自体のHOLブロッキングは残ります。HTTP/3 (QUIC) は、UDP上で個別のストリームを多重化するため、トランスポート層でのHOLブロッキングを完全に解消し、パケットロス耐性を向上させます。実装は、HTTP/2/3の多重化機能を適切に活用し、HOLブロッキングによる遅延を最小限に抑えるべきです。</li>
</ul></li>
<li><p><strong>キュー制御と流量制御</strong>:</p>
<ul>
<li>DoHクライアントは、多数の同時DNSクエリを処理するために、適切なキュー制御と流量制御メカニズムを実装する必要があります。HTTP/2のウィンドウ制御やQUICのストリーム/接続フロー制御を適切に利用し、DoHリゾルバへの負荷を管理しつつ、効率的な通信を維持することが重要です。</li>
</ul></li>
<li><p><strong>優先度制御</strong>:</p>
<ul>
<li>HTTP/2はストリームの優先度付け機能を提供します。DoHクライアントは、ウェブページのレンダリングに必要なDNSクエリなど、優先度の高いDNSクエリを低優先度のクエリよりも先に処理するようにシグナルを送ることができます。これにより、ユーザー体験が向上します。HTTP/3も同様の優先度付けメカニズムをサポートしています。</li>
</ul></li>
<li><p><strong>エラーハンドリングと再試行</strong>:</p>
<ul>
<li>TLS接続の確立失敗、HTTPエラーコード (例: 5xxサーバーエラー)、DNSエラーコード (RCODE) など、様々なエラーケースに対応した堅牢なエラーハンドリングと再試行ロジックが必要です。特に、ネットワークの一時的な問題やリゾルバの負荷によるエラーの場合、適切な指数バックオフ戦略を用いた再試行が重要です。</li>
</ul></li>
</ul>
<h2 class="wp-block-heading">まとめ</h2>
<p>DNS over HTTPS (DoH) は、従来のDNSプロトコルが抱えるプライバシーとセキュリティの問題に対処するために、Hypertext Transfer Protocol Version 2 (HTTP/2) または Version 3 (HTTP/3) とTransport Layer Security (TLS) を活用して設計された重要なプロトコルです。RFC 8484で標準化され、ポート443を使用することで既存のウェブインフラとの親和性を高め、検閲耐性も向上させます。</p>
<p>DoHは、TLSによる強力な暗号化と認証により、DNSクエリの盗聴や改ざんを防ぎ、ユーザーのプライバシー保護に貢献します。また、HTTP/2/3のストリーム多重化機能により、効率的な同時クエリ処理が可能です。DoTや従来のDNSと比較して、運用の容易さや既存システムとの連携において優位性がありますが、一方でプロトコルスタックの複雑化や0-RTT利用時のセキュリティリスク、特定のDoHプロバイダーへの集中によるプライバシー懸念といった側面も存在します。</p>
<p>実装においては、MTU/PMTUD、HOLブロッキングの回避、キュー制御、優先度付け、そして堅牢なエラーハンドリングが、高性能で信頼性の高いDoHサービスを提供する上で不可欠です。ネットワークエンジニアとしては、これらの特性を理解し、適切な設計と実装を行うことで、より安全でレジリエントなインターネット環境の構築に貢献できます。</p>
<hr/>
<p><strong>参考文献</strong></p>
<ul class="wp-block-list">
<li><p>[1] RFC 8484 – DNS Queries over HTTPS (DoH). IETF. (October 2018). Available at: <code>https://datatracker.ietf.org/doc/html/rfc8484</code></p></li>
<li><p>[2] RFC 9113 – HTTP/2. IETF. (June 2022). Available at: <code>https://datatracker.ietf.org/doc/html/rfc9113</code></p></li>
<li><p>[3] RFC 9001 – Using TLS to Secure QUIC. IETF. (May 2021). Available at: <code>https://datatracker.ietf.org/doc/html/rfc9001</code></p></li>
</ul>
本記事はGeminiの出力をプロンプト工学で整理した業務ドラフト(未検証)です。
DNS over HTTPS (DoH) の動作原理と実装に関する詳細解説
背景
従来のDNS (Domain Name System) は、インターネットの基盤技術として広く利用されてきましたが、その通信は通常UDPポート53またはTCPポート53で行われ、暗号化されていません。このため、DNSクエリは盗聴や改ざんの脅威に晒されやすく、ユーザーのプライバシー保護や通信の完全性確保に課題がありました。特に、オンパス攻撃者によるDNSトラフィックの監視やブロックは、ネットワークの中立性やユーザーの検閲回避を妨げる要因となりえます。
このような背景から、DNS通信のセキュリティとプライバシーを向上させる目的で、いくつかの新しいプロトコルが提案・実装されてきました。その一つが、ここで解説するDNS over HTTPS (DoH) です。DoHは、既存のHTTPSインフラストラクチャとTLSによる暗号化を最大限に活用することで、これらの課題の解決を目指しています。
設計目標
DNS over HTTPS (DoH) は、主に以下の設計目標を掲げています [1]:
プライバシーの向上: DNSクエリおよびレスポンスをTLSによって暗号化し、オンパス攻撃者による盗聴や情報の漏洩を防ぎます。
完全性の確保: TLSが提供する認証とデータ完全性保護により、DNSメッセージの改ざんを防ぎます。
検閲耐性の強化: DNSトラフィックを一般的なHTTPSトラフィックに偽装することで、特定のDNS通信のブロックやフィルタリングを困難にします。これにより、ネットワークの検閲を回避しやすくなります。
既存インフラの活用: ウェブブラウザ、OS、ロードバランサー、プロキシサーバーなど、既存のHTTP/TLSエコシステムとインフラを再利用可能にすることで、広範な展開を促進します。
HTTP/2の活用: HTTP/2 (またはHTTP/3) が持つ多重化機能を利用し、単一のTCP接続 (またはQUIC接続) 上で複数のDNSクエリを並行して処理することで、効率的な通信を実現します。
詳細
DNS over HTTPS (DoH) は、その名の通り、DNSクエリとレスポンスをHTTPSプロトコル内でカプセル化して転送します。これは、Hypertext Transfer Protocol Version 2 (HTTP/2) または Hypertext Transfer Protocol Version 3 (HTTP/3) を利用し、その下層でTransport Layer Security (TLS) を用いて通信を暗号化します。
プロトコルスタック
DoHのプロトコルスタックは以下のようになります。
graph LR
DNS["DNS Message"] -- |Encapsulated in| --> HTTP["HTTP Request/Response"]
HTTP -- |Secured by| --> TLS["TLS Record Protocol"]
TLS -- |Transported over| --> TCP["TCP Segments(\"for HTTP/2\")"]
TLS -- |Transported over| --> QUIC["QUIC Packets(\"for HTTP/3\")"]
TCP -- |IP Layer| --> IP_TCP["IP Packets"]
QUIC -- |IP Layer| --> IP_QUIC["IP Packets"]
DNSクエリ/レスポンスのエンコードと転送
RFC 8484 (DNS Queries over HTTPS) にて規定されている通り、DoHは主に2つの方法でDNSメッセージをHTTPリクエスト/レスポンスに含めます [1]:
POSTメソッド:
DNSクエリのバイナリメッセージ (ワイヤーフォーマット) をHTTPリクエストのボディに含めます。
Content-Type ヘッダには application/dns-message を指定します。
レスポンスも同様に application/dns-message タイプでDNSレスポンスをボディに含みます。
この方法は、クエリ内容がURLに露出しないため、プライバシー面で優れています。
GETメソッド:
DNSクエリのバイナリメッセージをbase64urlエンコードし、HTTPリクエストのURIパラメータ dns (例: /dns-query?dns=AAABAAABAAA...) として含めます。
Content-Type ヘッダは通常不要ですが、application/dns-message も許容されます。
この方法は、ウェブキャッシュとの親和性が高く、同じクエリに対する応答をキャッシュしやすい利点があります。
DNSメッセージは、標準的なRFC 1035で定義されているワイヤーフォーマットで扱われます。
DoHの通信フロー
以下に、HTTP/2を利用したDoHクライアントとDoHリゾルバ間の通信シーケンスを示します。
sequenceDiagram
participant "C as DoH Client"
participant "S as DoH Resolver"
Note over C,S: 事前条件: DoH Resolverが
ポート443でHTTPSを提供
C ->> S: 1. TCP Handshake (SYN, SYN-ACK, ACK)
C ->> S: 2. TLS Handshake
C ->> S: ClientHello (TLSv1.3など)
S -->> C: ServerHello, Certificate, ServerKeyExchange, ServerHelloDone
C ->> S: ClientKeyExchange, ChangeCipherSpec, Encrypted Handshake Message
S -->> C: ChangeCipherSpec, Encrypted Handshake Message
Note over C,S: TLS接続確立、共有鍵生成
C ->> S: 3. HTTP/2 Connection Setup
C ->> S: Connection Preface (MAGIC + SETTINGS Frame)
S -->> C: Connection Preface (SETTINGS Frame)
Note over C,S: HTTP/2ストリーム通信準備完了
C ->> S: 4. DoH Request (HTTP/2 Stream)
C ->> S: HEADERS Frame (Stream ID: X)
alt GET Method
C ->> S: :method = GET
C ->> S: :scheme = https
C ->> S: :authority = example.com
C ->> S: :path = /dns-query?dns=AAABAAABAAA...
else POST Method
C ->> S: :method = POST
C ->> S: :scheme = https
C ->> S: :authority = example.com
C ->> S: :path = /dns-query
C ->> S: content-type = application/dns-message
C ->> S: DATA Frame (Stream ID: X, DNS Query Message)
end
S ->> C: 5. DoH Response (HTTP/2 Stream)
S -->> C: HEADERS Frame (Stream ID: X)
S -->> C: :status = 200 OK
S -->> C: content-type = application/dns-message
S -->> C: DATA Frame (Stream ID: X, DNS Response Message)
Note over C,S: DNSクエリ/レスポンス完了
プロトコル構造の例
HTTP/2のフレーム構造は以下のようになります [2]:
HTTP/2 Frame Header:
+-----------------------------------------------+
| Length (24) |
+---------------+---------------+---------------+
| Type (8) | Flags (8) |
+-+-------------+---------------+-------------------------------+
|R| Stream Identifier (31) |
+=+=============================================================+
| Frame Payload (Length bytes) |
+---------------------------------------------------------------+
Length: フレームペイロードのバイト長 (24ビット)
Type: フレームの種類 (例: HEADERS, DATA, SETTINGSなど) (8ビット)
Flags: フレームタイプに固有のフラグ (8ビット)
R: 予約済みビット (1ビット、常に0)
Stream ID: ストリームを識別する整数 (31ビット)
DoHのHTTPリクエスト/レスポンスは、これらのHTTP/2フレームのペイロードとしてDNSメッセージを運びます。
既存プロトコルとの比較
従来のDNS (UDP/TCP ポート53) との比較
DoHは、従来のDNSプロトコルと比較して、セキュリティと運用面で大きな違いがあります。
セキュリティとプライバシー:
ポート番号:
プロトコルの複雑性:
キャッシュ:
多重化:
DNS over TLS (DoT) との比較
DNS over TLS (DoT) は、RFC 7858 (DNS over TLS) で定義され、DNSメッセージをTLS上で直接転送するプロトコルです。DoHとDoTはどちらもDNS通信を暗号化しますが、そのアプローチが異なります。
プロトコルスタック:
ポート番号:
中間デバイスとの親和性:
多重化:
HTTP/2 と HTTP/3 の比較 (DoHの観点から)
DoHはHTTP/2 [RFC 9113, June 2022] またはHTTP/3 [RFC 9114, June 2022] のいずれの上でも動作可能です。
HTTP/2:
HTTP/3:
基盤: QUIC (UDP上で動作) を利用。
HOLブロッキング: QUICはストリーム単位で多重化と信頼性を保証するため、TCPのHOLブロッキング問題を完全に解消。パケットロスが特定のストリームに限定され、他のストリームには影響しない。
接続確立: QUICの0-RTT (Zero Round-Trip Time) や1-RTT接続により、TLSハンドシェイクと同時に暗号化通信を開始でき、接続確立時間が大幅に短縮される可能性。特にモバイル環境などでメリットが大きい。
HTTP/3上にDoHを実装することで、特にモバイル環境や高遅延・高パケットロス環境でのDNSクエリ性能が向上することが期待されます。
セキュリティ考慮事項
DoHは従来のDNSに比べて大幅にセキュリティが向上しますが、いくつかの考慮事項があります。
プライバシーの向上と集中化のリスク:
- DoHはDNSクエリを暗号化し、ISPや中間者による監視を防ぎますが、すべてのDNSクエリが特定のDoHプロバイダーに集中する可能性があり、そのプロバイダーに対する信頼が極めて重要になります。プロバイダーがDNSデータを収集・利用する懸念が生じる可能性があります。
リプレイ攻撃:
- DNSクエリ自体は一般的に冪等 (idempotent) であるため、GETメソッドを使用したクエリの応答がリプレイされても大きなセキュリティ上の問題は少ないとされます。しかし、DNSSECに関連するダイナミックアップデートなど、冪等でないPOSTリクエストが使用される場合は、再送されるリスクを考慮する必要があります。HTTP/3の0-RTT機能を利用する場合、再送保護が不十分なリクエストが攻撃者によってリプレイされる可能性があり、特に注意が必要です [3]。
ダウングレード攻撃:
- DoHクライアントは、必ずHTTPS (TLS) 接続を使用するべきであり、平文のHTTPへのダウングレードを許可してはなりません。また、クライアントは、信頼できるDoHリゾルバのURIを事前に設定するか、信頼できる方法で取得する必要があります。HTTP Strict Transport Security (HSTS) のようなメカニズムは、中間者攻撃による意図しないダウングレードを防ぐのに役立ちます。
キー更新:
- DoHのセキュリティは基盤となるTLS接続に依存します。TLSセッションキーの更新はTLSプロトコル自身によって管理され、定期的に行われるべきです。長期にわたるセッションでは、TLSの再ネゴシエーションや新しい接続の確立によってキーの更新が行われます。
0-RTTの再送リスク:
- HTTP/3 (QUIC) の0-RTT機能は接続確立を高速化しますが、初期クライアントハンドシェイクのデータをリプレイされるリスクがあります。特に
POSTメソッドなど非冪等なリクエストを0-RTTで送信する場合、攻撃者がそのデータを傍受し、サーバーに複数回送信することで意図しない副作用を引き起こす可能性があります [3]。DoHの実装者は、0-RTTデータに非冪等なDNS操作を含めないか、サーバー側で厳格なリプレイ保護メカニズムを実装する必要があります。RFC 9001 (QUIC TLS) では、0-RTTの利用に関するセキュリティ考慮事項が詳細に説明されています。
実装メモ
DoHの実装には、ネットワークエンジニアとして以下の点に注意を払う必要があります。
まとめ
DNS over HTTPS (DoH) は、従来のDNSプロトコルが抱えるプライバシーとセキュリティの問題に対処するために、Hypertext Transfer Protocol Version 2 (HTTP/2) または Version 3 (HTTP/3) とTransport Layer Security (TLS) を活用して設計された重要なプロトコルです。RFC 8484で標準化され、ポート443を使用することで既存のウェブインフラとの親和性を高め、検閲耐性も向上させます。
DoHは、TLSによる強力な暗号化と認証により、DNSクエリの盗聴や改ざんを防ぎ、ユーザーのプライバシー保護に貢献します。また、HTTP/2/3のストリーム多重化機能により、効率的な同時クエリ処理が可能です。DoTや従来のDNSと比較して、運用の容易さや既存システムとの連携において優位性がありますが、一方でプロトコルスタックの複雑化や0-RTT利用時のセキュリティリスク、特定のDoHプロバイダーへの集中によるプライバシー懸念といった側面も存在します。
実装においては、MTU/PMTUD、HOLブロッキングの回避、キュー制御、優先度付け、そして堅牢なエラーハンドリングが、高性能で信頼性の高いDoHサービスを提供する上で不可欠です。ネットワークエンジニアとしては、これらの特性を理解し、適切な設計と実装を行うことで、より安全でレジリエントなインターネット環境の構築に貢献できます。
参考文献
[1] RFC 8484 – DNS Queries over HTTPS (DoH). IETF. (October 2018). Available at: https://datatracker.ietf.org/doc/html/rfc8484
[2] RFC 9113 – HTTP/2. IETF. (June 2022). Available at: https://datatracker.ietf.org/doc/html/rfc9113
[3] RFC 9001 – Using TLS to Secure QUIC. IETF. (May 2021). Available at: https://datatracker.ietf.org/doc/html/rfc9001
コメント