#このページで確認できること

実装上の制約: Handshake・0-RTT・1-RTTパケットの内容を観測するには、通常SSLKEYLOGFILEによる復号設定が必要です。一方、Initialの鍵はパケット上で見える情報から導出できるため、WiresharkはキーログなしでもInitial内のClientHelloなどを解析できます。

#なぜ UDP の上に作るのか

#ハンドシェイクと 0-RTT

QUIC 初回接続 — 1 RTT
participants: Client, Server
Client -> Server: Initial packet (ClientHello) [UDP]
Server --> Client: Initial + Handshake (ServerHello, cert, finished)
Client -> Server: Handshake (finished)
note: 1 RTT で暗号化されたコネクション確立
Client <-> Server: 1-RTT packets (application data / streams)
再接続 — 0-RTT でデータを即送信
participants: Client, Server
note: 前回接続時のセッションチケットを保持している
Client -> Server: Initial (ClientHello + session ticket)
Client -> Server: 0-RTT packet (GET / を即座に送信)
Server --> Client: Handshake + 1-RTT (200 OK)
note: 0-RTT はリプレイされ得る。HTTPでは安全なメソッド等に利用を絞る
アドレス検証前の増幅対策: サーバーはクライアントアドレスを検証するまで、受信したバイト数の3倍を超えて送信できません。必要に応じてRetryでreturn routabilityを確認します。1200バイト以上に拡張する要件は、クライアントが送るInitial入りデータグラムと、サーバーが送るack-eliciting Initial入りデータグラムが対象です。このサイズ要件だけで増幅対策が完結するわけではありません。

#Connection ID と connection migration

TCPのコネクションは「送信元IP・ポート・宛先IP・ポート」の4タプルで識別されるため、一般にWi-Fi→モバイル回線の切替でIPが変わると同じコネクションは継続できません。QUICはConnection IDでコネクションを識別し、相手がmigrationを無効化していないなどの条件を満たせば、IPアドレスが変わっても同じコネクションを継続できます(connection migration)。

Connection migration — IPが変わっても継続
participants: Client, Server
Client -> Server: 1-RTT packets (Wi-Fi: 192.0.2.10)
note: クライアントがモバイル回線へ切替 — IPが変わる
Client -> Server: same connection ID (LTE: 203.0.113.55)
Server --> Client: PATH_CHALLENGE (新経路の検証)
Client -> Server: PATH_RESPONSE
note: migrationが許可され、新経路の検証に成功すれば継続する
NAT・ファイアウォール観点: connection migration はステートフルなファイアウォールやNATのセッション管理と相性が悪く、また5タプルでフローを追跡するネットワーク監視では「別フロー」に見えます。QUICのトラブルシュートでは connection ID 単位で追う必要があります。

#ストリームとフロー制御

#検証コマンド

curl / ブラウザ
# HTTP/3 経由で QUIC を使う(h3対応curlが必要)
$ curl -v --http3-only https://cloudflare-quic.com/ 2>&1 | head -30

# 実際のQUIC応答を使って疎通を確認する。失敗時は同時にパケットキャプチャする
$ curl -v --http3-only https://cloudflare-quic.com/ -o /dev/null
tcpdump — QUIC パケットのキャプチャ
$ sudo tcpdump -i en0 -n 'udp port 443'
# クライアント送信のInitial入りUDPデータグラムは、UDPペイロード1200バイト以上
# サーバー送信ではack-eliciting Initial入りが同じサイズ要件の対象

# Wireshark で復号したい場合はキーログを出してから起動
$ SSLKEYLOGFILE=$HOME/sslkeys.log /Applications/Google\ Chrome.app/Contents/MacOS/Google\ Chrome
# Wireshark: Preferences → Protocols → TLS → (Pre)-Master-Secret log filename に指定
Wireshark フィルタ
# QUIC パケット全体
quic

# Initial パケット(ハンドシェイク開始)のみ
quic.long.packet_type == 0

#観測ポイント

curl--http3-only の結果から、対象ホストがHTTP/3で応答できるかを確認。--http3 を使う場合は、HTTP/3失敗後の h2 / HTTP/1.1 へのフォールバックと区別する。
DevToolsProtocol 列 h3。Chromium系では chrome://net-export からネットワークログを取得できる。connection ID やmigration関連イベントが記録・表示されるかは実装とバージョンによる。
Proxy従来型HTTP CONNECTはTCPトンネルなのでQUICを運べない。この構成ではQUICが使われないことが多い。一方、MASQUE CONNECT-UDPに対応するプロキシならUDPをトンネルできる。
tcpdump / WiresharkUDP 443 のデータグラムサイズ、connection ID、Version、packet typeを確認する。クライアント送信のInitial入りデータグラムと、サーバー送信のack-eliciting Initial入りデータグラムはUDPペイロード≥1200Bが要件。Initialはキーログなしでも解析可能で、Handshake・1-RTTの詳細には通常キーログが必要。
TLS inspectionQUICの復号・ポリシー制御に対応しない装置では、UDP 443を遮断してTCP上のHTTPへフォールバックさせる構成がある。その場合は、クライアントがタイムアウト待ちで遅延しないかを観測する。

#関連

QUIC 上のHTTPについては HTTP/3 を参照。QUICが解決した課題の背景は HTTP/1.1HTTP/2 の流れで追うと理解しやすいです。