HTTP/3 と QUIC 入門 - なぜ HTTP は TCP を捨てて UDP に移ったのか

HTTP/3 と QUIC 入門 - なぜ HTTP は TCP を捨てて UDP に移ったのか

作成日:
読了:19
更新日:

Web ページを開くとき、ブラウザとサーバーの間では長らく HTTP over TCP が使われてきました。HTTP/1.1 も HTTP/2 も、下では TCP が動いています。ところが最新の HTTP/3 は、TCP をやめて UDP の上で動く QUIC(クイック)という新しいトランスポートに乗り換えました。「せっかく信頼性のある TCP があるのに、なぜわざわざ UDP に戻るのか」と不思議に思う人も多いはずです。

この記事では、その理由を一次ソースの RFC を軸に整理します。まず HTTP/2 が TCP の上で抱える Head-of-Line(HoL)ブロッキングという問題から出発し、QUIC がそれをどう解決するのか、ストリーム多重化・TLS 1.3 統合・0-RTT・コネクションマイグレーションといった仕組みを直感的に見ていきます。ネットワークの前提知識として DNS の名前解決公開鍵暗号・デジタル署名を知っておくと理解が深まります。

HTTP/2 までの復習

まず、これまでの HTTP がどう進化してきたかを整理します。

  • HTTP/1.1: 1本の TCP コネクション上でリクエストとレスポンスを1往復ずつ処理します。前のレスポンスが返るまで次を送れない(正確にはパイプライン化はあるが実用されない)ため、ブラウザはドメインごとに複数の TCP コネクションを張って並列化していました。
  • HTTP/2: RFC 7540(後継は RFC 9113)で標準化されました。1本の TCP コネクションの中をストリームという論理的な通り道に分割し、複数のリクエスト/レスポンスを多重化(マルチプレクシング)できるようにしました。ヘッダーは HPACK(RFC 7541)で圧縮されます。

HTTP/2 の多重化は大きな前進でした。1本の接続で数十のリソースを同時に取得でき、HTTP/1.1 時代のように接続をたくさん張る必要がなくなりました。

しかし、この「1本の TCP コネクションに全部まとめる」という設計こそが、次に説明する新たなボトルネックを生みます。ステータスコードの意味を復習したい場合は HTTP ステータスコード入門もあわせてどうぞ。

TCP のせいで詰まる - HoL ブロッキング

HTTP/2 のストリームは、アプリケーションから見れば独立しています。しかしその下の TCP から見ると、すべてのストリームのデータは1本の連続したバイト列にまとめられて流れています。

TCP は「送ったデータを、送った順番どおりに、欠けなく相手に届ける」ことを保証します。この「順番どおり」がくせ者です。途中のパケットが1つでも失われると、TCP はそのパケットが再送されて到着するまで、後続のすべてのデータをアプリケーションに渡しません。たとえ後続パケットが先に届いていても、順序を守るために待たされます。

これが Head-of-Line(HoL)ブロッキングです。HTTP/2 では、本来無関係な複数のストリームが1本の TCP に相乗りしているため、あるストリームのための1パケットが落ちただけで、無関係な他のストリームまで全部止まるのです。

HTTP/2 over TCP: 1パケットの欠落が全ストリームを止める
TCP の1本のバイト列(順序保証)
 ┌──────────────────────────────────────────┐
 │ ...A2 │ [B1: 欠落] │ A3 │ B2 │ C1 │ C2 ...│
 └──────────────────────────────────────────┘

        ここが届かないと、
        後ろの A3 / B2 / C1 / C2 が
        すでに届いていてもアプリに渡せない
        (= 全ストリームが待たされる)

重要なのは、これは HTTP/2 の実装が悪いのではなく、TCP という土台の性質だという点です。TCP はストリームの区別を知らないので、HTTP/2 がいくら論理的にストリームを分けても、TCP レイヤーの HoL ブロッキングは避けられません。HTTP/2 は「アプリケーション層の HoL ブロッキング」は解消しましたが、「トランスポート層の HoL ブロッキング」は TCP を使う限り残ってしまうのです。

パケットロスが起きやすいモバイル回線や遅延の大きい経路ほど、この影響は顕著になります。

QUIC とは - UDP の上に作り直したトランスポート

この根本問題を解くには、TCP そのものを置き換えるしかありません。そこで登場したのが QUIC です。

QUIC は RFC 9000「QUIC: A UDP-Based Multiplexed and Secure Transport」(2021年5月発行)で標準化された、UDP の上で動く新しいトランスポートプロトコルです。UDP はパケットを送るだけの最小限のプロトコルで、順序保証も再送もありません。QUIC はその上に、TCP が持っていた信頼性・順序制御・輻輳制御を、しかもストリームごとに独立させて再実装しています。

NOTE

なぜ TCP を改造せず UDP を選んだのか。TCP は OS カーネルに深く組み込まれ、ルーターやファイアウォールなどの中間装置(ミドルボックス)も TCP の中身を前提に動いています。TCP に新機能を足しても、世界中の機器が対応するまで何年もかかります。UDP の上にユーザー空間で実装すれば、アプリやブラウザの更新だけで新機能を配れます。QUIC はこの「デプロイのしやすさ」を重視して UDP を土台に選びました。

QUIC が提供する主な機能は、RFC 9000 の言葉を借りると「フロー制御されたストリーム」「低遅延なコネクション確立」「ネットワークパスのマイグレーション」です。さらに暗号化と認証がプロトコルに組み込まれています。QUIC はもともと Google が開発し、IETF で標準化される過程で TLS 1.3 ベースの設計に整理されました。

QUIC の主要な仕組み

QUIC の要点を4つに分けて見ていきます。

ストリーム多重化 - HoL ブロッキングの解消

QUIC では、各ストリームが独立した順序保証を持ちます。ストリーム A のパケットが失われても、QUIC はストリーム B・C のデータはそのままアプリケーションに渡せます。失われたのはあくまでストリーム A の一部だけなので、他のストリームを巻き込みません。

QUIC over UDP: ストリームごとに独立して順序保証
UDP 上の QUIC(ストリームは互いに独立)
 ┌───────────────┐ ┌───────────────┐ ┌───────────────┐
 │ Stream A      │ │ Stream B      │ │ Stream C      │
 │ A1 [欠落] A3  │ │ B1 B2 B3 ✔    │ │ C1 C2 ✔       │
 └───────────────┘ └───────────────┘ └───────────────┘
       ↑ ここだけ待つ    B と C はそのまま
                         アプリに渡せる

これが QUIC 最大のポイントです。TCP の HoL ブロッキングは「トランスポートが1本のバイト列」だから起きていました。QUIC はトランスポート自身がストリームを理解し、ストリーム単位で再送と順序制御を行うため、あるストリームのロスが他に波及しません。

TLS 1.3 の統合 - 暗号化が標準装備

QUIC は暗号化がオプションではなく必須です。その暗号は RFC 9001「Using TLS to Secure QUIC」(2021年5月発行)で定義され、TLS 1.3 を使います。

従来の HTTPS は「TCP でハンドシェイク(1往復)」してから「その上で TLS ハンドシェイク(TLS 1.3 なら1往復)」と、接続確立に段階を踏んでいました。QUIC は TLS 1.3 をトランスポートに融合させ、トランスポートのハンドシェイクと暗号のハンドシェイクを一体で行います。RFC 9001 の表現では、TLS のハンドシェイクメッセージは QUIC の CRYPTO フレームに載せて直接運ばれ、QUIC が TLS のレコード層の役割を引き受けます。

結果として、初回接続でも 1-RTT(1往復)で暗号化された通信を始められます。TLS の基礎を押さえたい方は 公開鍵暗号・デジタル署名入門を参照してください。

0-RTT - 再訪問なら往復ゼロでデータ送信

一度接続したことのあるサーバーへ再び接続する場合、QUIC は前回のセッション情報を再利用して 0-RTT(往復ゼロ)で最初のアプリケーションデータを送れます。ハンドシェイクの完了を待たずに、最初のパケットにリクエストを載せてしまうイメージです。

これは体感速度に大きく効きますが、注意点もあります。0-RTT で送るデータはリプレイ攻撃(攻撃者が同じパケットを再送する攻撃)に対して脆弱になり得るため、副作用のないべき等なリクエスト(GET など)に限定するのが原則です。べき等性については REST API 設計とべき等性もあわせてどうぞ。

接続確立にかかる往復数(概念図)
HTTP/2 (TCP+TLS1.3)  : TCP 1-RTT + TLS 1-RTT = 実質2往復
HTTP/3 初回 (QUIC)   : 1-RTT でハンドシェイク兼データ開始
HTTP/3 再訪 (QUIC)   : 0-RTT で最初のデータを即送信

コネクションマイグレーション - IP が変わっても切れない

TCP のコネクションは「送信元 IP・ポート・宛先 IP・ポート」の4つの組(4-tuple)で識別されます。そのため、Wi-Fi からモバイル回線に切り替わって IP アドレスが変わると、TCP コネクションは切れてしまい、TLS ハンドシェイクからやり直しになります。

QUIC は接続を IP アドレスではなく Connection ID という識別子で管理します。IP アドレスが変わっても Connection ID が同じなら、サーバーは同じ接続だと認識でき、通信を継続できます。これがコネクションマイグレーションです。スマホを持ってカフェの Wi-Fi から外に出た瞬間でも、ダウンロードや通話が途切れにくくなります。

損失検知と輻輳制御

QUIC の再送・輻輳制御は RFC 9002「QUIC Loss Detection and Congestion Control」(2021年5月発行)で定義されています。TCP の Fast Retransmit に相当する ACK ベースの損失検知や、テール損失に備える Probe Timeout、NewReno 相当の輻輳制御などが規定されています。QUIC はパケット番号が常に単調増加する(再送でも番号を使い回さない)ため、TCP のような再送のあいまいさがなく、損失検知が簡潔になっています。

HTTP/3 = QUIC の上の HTTP

ここまでの QUIC はあくまでトランスポートです。その上に HTTP のセマンティクス(メソッド・ヘッダー・ステータスコードなど)を載せたものが HTTP/3 で、RFC 9114「HTTP/3」(2022年6月発行)で標準化されています。

レイヤー構造の比較
HTTP/2                    HTTP/3
┌───────────────┐        ┌───────────────┐
│ HTTP semantics│        │ HTTP semantics│
├───────────────┤        ├───────────────┤
│ HTTP/2 frames │        │ HTTP/3 frames │
│ HPACK         │        │ QPACK         │
├───────────────┤        ├───────────────┤
│ TLS 1.2/1.3   │        │  QUIC         │
├───────────────┤        │  (TLS 1.3統合)│
│ TCP           │        ├───────────────┤
│               │        │  UDP          │
└───────────────┘        └───────────────┘

HTTP/3 では、ストリーム多重化・フロー制御・低遅延なコネクション確立といった機能をすべて QUIC に任せます。HTTP/3 自体は HTTP の意味づけとフレーミングに専念できるので、HTTP/2 よりも仕様がすっきりしています。

一点だけ、ヘッダー圧縮は作り直しが必要でした。HTTP/2 の HPACK は「全ストリームにまたがる完全な順序」を前提にしています。しかし QUIC はストリーム間で順不同の到着を許すため、HPACK をそのまま使うと再びヘッダー用の HoL ブロッキングが発生してしまいます。そこで HTTP/3 は RFC 9204「QPACK: Field Compression for HTTP/3」(2022年6月発行)で定義された QPACK を使い、順不同到着でも正しく動くように設計されています。

まとめると、HTTP/3 を支える主な RFC は次のとおりです。

RFCタイトル内容
RFC 9000QUIC: A UDP-Based Multiplexed and Secure TransportQUIC トランスポート本体
RFC 9001Using TLS to Secure QUICQUIC と TLS 1.3 の統合
RFC 9002QUIC Loss Detection and Congestion Control損失検知・輻輳制御
RFC 9114HTTP/3QUIC 上の HTTP マッピング
RFC 9204QPACK: Field Compression for HTTP/3HTTP/3 用ヘッダー圧縮

いま使えるのか - ブラウザ・サーバー・CDN の対応

HTTP/3 はすでに広く使える段階に入っています。

ブラウザ: Chromium 系(Chrome / Edge / Opera など)は2020年4月からデフォルトで HTTP/3 に対応しています。Firefox も 88 以降でデフォルト有効です。Safari は長らく実験的機能でしたが、Safari 16 以降で標準対応が進みました(各ブラウザの詳細バージョンは公式リリースノートで確認してください)。

CDN: Cloudflare をはじめとする主要 CDN は HTTP/3 に対応済みで、対応ドメインでは自動的に HTTP/3 が使われることが多いです。CDN のキャッシュ設計は CDN と Cache-Control / s-maxage 実践も参考にしてください。

サーバー: nginx は 1.25.0 以降で QUIC / HTTP/3 に対応しました(listenquic パラメータを追加)。ただし公式ドキュメント上は実験的(experimental)という位置づけで、ビルドには QUIC 対応の TLS ライブラリが必要です。本番導入時は、利用する nginx(またはフォークや他サーバー)のバージョンとステータスを必ず一次情報で確認してください。

普及状況: Cloudflare Radar などの計測では、HTTP/3 のトラフィックシェアはおおむね2割前後で推移しているとされます(時点・観測点により変動し、HTTP/2 が依然として最大勢力という報告もあります)。具体的な数値は観測元と時期に強く依存するため、参考値・概数として扱ってください(本記事では特定時点の断定は避けます)。

NOTE

HTTP/3 は「Alt-Svc」という仕組みで段階的に使われ始めます。多くのブラウザは最初 HTTP/2 で接続し、レスポンスの Alt-Svc ヘッダーでサーバーが HTTP/3 対応を告知すると、次回以降 QUIC 接続を試みます。つまり、初回アクセスがいきなり HTTP/3 になるとは限りません。

自分で確認してみる

自分のブラウザやサイトが HTTP/3 を使っているかは、いくつかの方法で確認できます。

ブラウザの DevTools: ネットワークタブを開き、列の設定で「Protocol」を表示させます。HTTP/3 で取得されたリクエストは h3 と表示されます(HTTP/2 なら h2、HTTP/1.1 なら http/1.1)。

Alt-Svc ヘッダー: レスポンスヘッダーに Alt-Svc: h3=":443" のような告知があれば、そのサーバーは HTTP/3 に対応しています。

curl: HTTP/3 対応ビルドの curl であれば --http3 オプションで試せます。ただし標準配布の curl には HTTP/3 が含まれないことが多く、QUIC 対応ライブラリと組み合わせた特別ビルドが必要です。

curl で HTTP/3 を確認する(HTTP/3 対応ビルドが前提)
# HTTP/3 を試し、ダメなら下位バージョンにフォールバック
curl --http3 -I https://example.com/
 
# HTTP/3 のみ(失敗したら通信させない・確認用に厳密)
curl --http3-only -I https://example.com/
 
# 応答ヘッダーで Alt-Svc(h3 告知)を確認
curl -sI https://example.com/ | grep -i alt-svc

HTTP/3 の注意点・トレードオフ

HTTP/3 は万能ではありません。導入・運用時に押さえておきたい点があります。

  • UDP がブロックされる環境がある: 一部の企業ネットワークやファイアウォールは UDP/443 を通しません。その場合ブラウザは HTTP/2(TCP)にフォールバックします。HTTP/3 は「速くする追加の選択肢」であり、TCP 経路がなくなるわけではありません。
  • CPU コストが高くなりがち: QUIC の暗号処理やパケット処理はユーザー空間で行われることが多く、TCP + カーネルの TLS オフロードに比べて CPU を食う傾向があります。高帯域・低損失な回線では、必ずしも HTTP/3 が HTTP/2 より速いとは限りません。
  • 0-RTT のリプレイリスク: 前述のとおり、0-RTT データは再送攻撃に注意が必要で、副作用のあるリクエストには使うべきではありません。
  • 運用ツールの成熟度: パケットキャプチャや解析、負荷分散などのツール群は、TCP に比べると QUIC 対応がまだ発展途上な部分があります。
  • デバッグの難しさ: 通信全体が暗号化されているため、中身を覗いての切り分けは TCP + 平文時代より難しくなります。

つまり HTTP/3 は「高遅延・高損失なモバイル/長距離回線で特に効く」プロトコルであり、環境によっては HTTP/2 のままで十分なケースもあります。導入は効果測定とセットで考えるのが現実的です。

まとめ

  • HTTP/2 はストリーム多重化を実現したが、土台の TCP が「1本の順序付きバイト列」であるため、トランスポート層の HoL ブロッキングを解消できなかった。
  • QUIC(RFC 9000)は UDP の上に、ストリームごとに独立した信頼性・順序制御・輻輳制御(RFC 9002)を実装し、この HoL ブロッキングを根本から解決する。
  • QUIC は TLS 1.3 を統合(RFC 9001)し、暗号化を必須にしつつ、初回 1-RTT・再訪 0-RTT の低遅延な接続確立を実現する。
  • Connection ID により IP が変わっても接続が切れないコネクションマイグレーションが可能。
  • HTTP/3(RFC 9114)は QUIC の上に HTTP を載せたもので、順不同到着に対応した QPACK(RFC 9204)でヘッダーを圧縮する。
  • ブラウザ・CDN の対応は進み、nginx なども対応済み(実験的)だが、UDP ブロックや CPU コスト、0-RTT リスクなどのトレードオフもあるため、効果測定とセットで導入するのがよい。

HTTP は、意味づけ(セマンティクス)を保ったまま、その土台を TCP から QUIC へと入れ替えました。「なぜ TCP を捨てて UDP に移ったのか」という問いの答えは、TCP の順序保証そのものが多重化のボトルネックだったからに尽きます。QUIC はその制約を、トランスポートを作り直すことで乗り越えたのです。

DNS の仕組み入門 - 名前解決・レコード種別・TTL とキャッシュを理解する

DNS の仕組み入門 - 名前解決・レコード種別・TTL とキャッシュを理解する

23

DNS(ドメインネームシステム)の名前解決の仕組みを、一次ソースである RFC を軸に整理します。ルート・TLD・権威サーバーの階層、再帰リゾルバとスタブリゾルバ、A/AAAA/CNAME/MX/NS/SOA/TXT/CAA/SRV/PTR などのレコード種別、再帰と反復の解決の流れ、TTL とキャッシュ、ネガティブキャッシュ(RFC 2308)、ポート53と UDP/TCP・EDNS0(RFC 6891)、DNSSEC(RFC 4033)、DoH(RFC 8484)/DoT(RFC 7858)まで、Web 開発者・インフラ担当者向けにまとめます。

Node.js が一気に塞いだ「TLSホスト名検証バイパス」4種 - 2026年6月の緊急アップデートを読み解く

Node.js が一気に塞いだ「TLSホスト名検証バイパス」4種 - 2026年6月の緊急アップデートを読み解く

12

2026年6月18日のNode.jsセキュリティリリースは、HIGH 2件を含む12件のCVEを全アクティブライン(22/24/26)で一斉修正しました。中でも目立つのは、ワイルドカード証明書を回避する CVE-2026-48618(Unicodeドット問題)を筆頭にしたTLSホスト名検証バイパスの集中修正です。なぜ「ホスト名を正しく比較する」だけのことがこれほど壊れやすいのか、各CVEの仕組みと、いま実務でやるべきことを整理します。

Astro 7 リリース - コンパイラもMarkdownもRust化、Vite 8でビルドが最大61%速く

Astro 7 リリース - コンパイラもMarkdownもRust化、Vite 8でビルドが最大61%速く

7

Astro 7 が2026年6月22日にリリースされました。.astro コンパイラを Go から Rust へ書き換え、Markdown/MDX 処理系に Rust 製の Sätteri を採用(デフォルト化)、バンドラは Vite 8(Rust 製 Rolldown)。ビルドは公式報告で15〜61%高速化。Queued Rendering の安定化、src/fetch.ts による高度ルーティング、Route Caching、AI エージェント検出付きのバックグラウンド開発サーバーなどの新機能と、HTML 厳格化や Sätteri デフォルト化(remark/rehype は明示オプトイン)といった6→7の破壊的変更を、Astro 公式を一次ソースに整理します。