QUIC の成熟
Fastly が QUIC を大好きなのは誰もが知る事実です。より信頼度の高く、さらに優れたインターネットの構築に必要だと考えているからということもありますが、それだけでなく、当社には QUIC を実験段階からインターネット標準に移行するプロセスに 6 年以上も積極的に関与している者がいるということも理由です。
QUICは、機能の追加、実装、評価、そして継続的な精査に耐えられないことで必要な再調整や破棄、改良などIETFでの協調的で反復的なプロセスを経て進化を続けています。そうすることで、QUICは想像以上に成熟し、当初のものとは大きく異なり、実質的に優れたプロトコルを生み出しました。そこで、QUICがどのようにして初期の実験からインターネットを近代化するための標準となるまでに至ったのかをご紹介します。
Google の早期実験
Google の gQUIC 実験は、 HTTP/2のパフォーマンス向上をセキュリティとトランスポートレイヤーにまで拡張するための取り組みとして始まりま した。これは大胆かつ素晴らしい実験で、HTTP 配下のプロトコルを置き換えることがその目標でした。インターネット経由で Google サーバーと Chrome 間を最初の gQUIC のバイトが流れたのは2013 年のことです。Google は、さまざまな自社サービスからライブトラフィクを gQUIC 経由で Chrome クライアントに配信し、Google サービスが恩恵を受けるにつれて徐々に gQUICの利用を増やしました。
この初期の実験のデータは、QUIC の設計における今後の発展に非常に重要なものです。また、この初期の取り組みは文書化されていますが、ここでは早期 gQUIC の一部であり、その後反復を通じて大部分が削除された 2 つの重要な技術例に注目します。
前方誤り訂正 (Forward Error Correction、FEC) : この機能は 1 つのスキーム (パリティ) を使用し、他のスキームを実装できるだけの柔軟性がありませんでした。このパリティスキームは無効とみなされ、さらに重要なのは、この機能を維持するために必要なコード量はメリットをはるかに上回っていたということです。
ACK エントロピー: プロトコルのこの機能は、 ACK スプーフィング攻撃から送信者を保護するものです。全トラフィックが暗号化されるため、ACK はエンドポイントのいずれか 1 つから送信される必要があり、この機能は送信者を不正な受信者から保護します。ACK エントロピーが削除されたのは、保護対象の攻撃が特に影響が大きいものではないということと、少なくないコード量とプロトコルの複雑性が発生するためでした。
どちらの機能もプロトコルの最適化が早すぎた例です。プロトコルが進化するにつれて、こういった機能がメンテナンスにおける弱点となり、メンテナンスコストが潜在的なメリットを上回る場合、その機能は削除されます。
IETF プロトコルの誕生
2015 年、Google が IETF にてBar-BoF (非公式の「同じ興味を持つ人 (birds-of-a-feather)」による集まり) と呼ばれる初期の非公式な公開討論を開始し、gQUIC の実験について議論しました。コミュニテ ィからの関心は非常に高く、 Bar-BoF は翌年にかけて 2 つの重要な作業を促進しました。
第一に、いくつかの独立した gQUIC の実装が具体化し始め、コミュニティ内のチャットでは、IETF が QUIC の作業を開始するとすぐに多くの組織が実装を開始しようと躍起になっていることが明らかになりました。これは重要なことです。なぜならプロトコルの標準化は、複数の実装がある場合にのみ意味があるからです。このような大規模の標準を構築するには膨大な作業量が必要なので、一般的には、多くの実装者が明確な関心を持っていることが開始するための要件となります。こういった独立した実装により、QUICの標準化を模索する意欲があることが証明されました。
第二に、gQUIC がモノリスだったということです。トランスポートと暗号ハンドシェイクが融合し、汎用トランスポートとしてではなく HTTP と併用するためにプロトコルが構築されました。翌年にはコアトランスポート、暗号ハンドシェイク、トランスポート上にある HTTP マッピングしたものなどのパーツにこのモノリスは分割されました。この作業は Google やコミュニティで実施されましたが、その成果は最終的には正式なワーキンググループの作業の元となったインターネットドラフトの構造の中で目に見える形で現れました。こうした会話から、QUIC の活動の推進をサポートするコミュニティの参加者が浮かび上がってきました。
Bar-BoF 会議の翌年、gQUIC はより多くのトラフィックを配信し、結果として Google はより多くのデータを公開することになりました。このデータ、初期プロトコルドラフトや初回設立許可により、コミュニティは前進できるようになりました。(Google とコミュニティ全体のうち) 少数が 2016 年に IETF で正式な BoF 会議を開催し、HTTP 向けの新規トランスポートを構築するワーキンググループを作りました。これは IETF で最も参加者の多かった会議の 1 つです。400 名近い参加者が集まり、提案された設立許可でワーキンググループを作ることに明確な合意を取りました。
これは極めて重要な瞬間です。QUIC は事実上 IETF が所有しているため、プロトコルの開発はコンセンサスベースの IETF プロセス経由で進められます。
IETF における QUIC
新しいIETFトランスポートは歴史的に広く普及するのに苦労してきましたが、gQUIC の結果は主な業界ベンダーの関心を集めました。彼らは全員 IETF のワーキンググループに参加していたメンバーです。広範囲での採用は十分にあり得ることでした。QUIC のワーキンググループ参加者は、自分たちが参加者全員のニーズを満たす成熟したプロトコルを構築する必要があることを理解していました。また、gQUIC が実証した主な性能上の利点を損なうことなくこれを実現する必要がありました。
QUIC の開発が過去も現在も共同作業であることは注目に値します。このプロトコルは、さまざまな組織からのコントリビューターによって開発されており、すべてのインターネットユーザーが利用できるよう大規模なプロトコルを共に構築する必要がありました。自己中心的なやり方や障壁が蔓延る世界において、競合他社と自由に協力して誰にとってもより良いインターネットを構築するというこの稀な環境を可能にしているのは IETF の信念の証です。
このグループの作業は 2 つの明記されていない指針に沿っていました。
それは、QUIC を強力な機密性とプライバシー性を二者間プロトコルとすることと、将来的なプロトコルの順応性を保つために流動性を持たせることでした。これはつまり、できるだけ多くのプロトコルを強力に暗号化するということです。また、こういったパケットを転送するネットワークが QUIC のパケットヘッダーのほとんどの情報に関与しないということでもあります。
プロトコル機能は大規模にチェックされます。プロトコル機能や実装による複雑性がメリットを上回る場合、その機能は除外されます。メンテナンスは膨大な隠れたコストで、実装者は付随するメリットを生み出さないコードのメンテナンスを行うほど忍耐強くありません。シンプルであることが難しくさせますが、これがコアバリューでした。
プロトコル機能の進化
QUIC の開発には一丸となった協力が必要で、時には機能の再設計が必要になることもありました。この変更やプロセスがどういったものなのかを皆さんに少しわかってもらうため、ここからはプロトコルの進化において顕著な流れをご紹介します。
ハンドシェイク
当初からこのワーキンググループの大きなタスクの 1 つが、他のオープンスタンダードと暗号ハンドシェイクを調整することでした。gQUIC が採用したのは QUIC-Crypto と呼ばれる独自のハンドシェイクです。QUIC-Crypto は、TLS 1.3 より前から存在していて、0-RTT の暗号ハンドシェイクという概念を導入した注目すべきテクノロジーでした。TLS 1.3 は一部 QUIC-Crypto の影響を受けていて、QUIC-Crypto がもたらしたレイテンシの全メリットを持っています。多くの議論の後、主にgQUICとTLS 1.3の関係者の間で、QUICが独自のQUIC-Cryptoの代わりにTLS 1.3標準を採用することが合意されました。gQUIC がQUIC-Crypto との緊密な統合により得られるパフォーマンス上のメリットを失うことなく、TLS 1.3 を採用するには多少の労力がかかるということをグループは認識していました。
何度か設計を繰り返し行った中には、QUICハンドシェイクを効果的にDTLSハンドシェイクに置き換える代替案も含まれています。そしてワーキンググループはついに現在の設計にたどり着いたのですが、これは次のように理解することができます。TLS はハンドシェイクプロトコルとレコードレイヤーで構成された 2 層のプロトコルです。従来、このレイヤリングは TLS プロトコルの内部にあるものと考えられていました。ワーキンググループによる QUIC とTLS の統合にはユニークな部分があります。最終設計では TLS ハンドシェイクプロトコルを採用しましたが、レコードレイヤーは QUIC 独自のものを採用しているので、ハンド シェイクメッセージの転送は QUIC が管理するのです。TLS は Web 用のセキュリティプロトコルで、QUICの最初のアプリケーションとなる予定であったため、ワーキンググループは QUIC のバージョン 1 に TLS が必要であることに合意しました。ただし、他のアプリケーションがセキュリティに TLS を使用していないこともあるため、QUIC では別の暗号ハンドシェイクも使えるようになっています。トランスポートドラフトにはこういったプロトコルに必要な機能の概要が記されていて、研究者による最近の研究はこの可能性の存在証明を提供しています。
パケット番号の暗号化
QUIC ヘッダーの大部分が暗号化されました。しかし、パケット番号や主なフェーズビットといった一部のビットは平文のままです。これらも暗号化したかったのですが、技術的に行き詰まっているように見えました。この理由を簡潔に説明しますが、少々複雑なのでご了承ください。
QUIC のパケット番号は信頼性とパケット暗号化のためのノンス (使い捨ての値) として使用していました。そして損失の検出と圧縮の向上のため、パケット番号は単調に増え続けていました。接続 ID 同様、パケット番号はネットワーク間を移動する接続を関連付けることができるため、簡単にデコード可能なパケットが問題となっていました。当初のソリューションでは、クライアン トがネットワーク間を移動する際にランダムなパケット番号のジャンプを行えるようにする数々の戦略が含まれていました。しかし、こうした戦略は複雑さに満ちており、新たな弱点も繰り返し見つかりました。さらに、パケット番号の公開によってネットワークのミドルボックスによる固定化を招き、進化が制限される可能性がありました。
パケット番号の暗号化は明確なソリューションですが、これを実行するには別のノンスが必要です。このノンスはヘッダー内で通信される必要があり、パケットのヘッダーオーバーヘッドが増加します。2018 年 6 月にスウェーデンのキスタで開催された QUIC の中間会議で発せられた鋭い洞察が、信じがたいことを可能にしました。ワーキンググループは暗号化されたテキストが暗号的にランダムであり、そのためノンスとして利用できることに気付いたのです。つまり、パケットにはパケット番号の暗号化に使われていたノンスが既に含まれていたということです!この洞察は、パケット番号には他のパケットと同じような強度の保護が不要であるという認識とともに、2 段階の暗号化プロセスを作成することを可能にしました。それは、まずノンストしてのパケット番号を使ってパケットを暗号化し、それからノンスとして暗号化したパケット (と別のキー) の一部を使用してパケット番号を暗号化するというものです。この戦略を用いることで、QUIC はヘッダー内の大半のビットを暗号化できるようになりました。
ここで、Fastly の同僚の一人に感謝を表明したいと思います。Fastly の奥一穂が現在の設計 に繋がるハンドシェイクとパケット番号の暗号化に関する議論において重要な突破口を示してくれました。
パケットヘッダー
初期のヘッダー形式は徐々に進化し、最終的には多数のフィールドと制約を持つ扱いにくいヘッダになりました。グループが局面を打開したのは、ヘッダーフィールドを 2 つに分割できるということに気付いたときでした。接続の確立に使用するパケットは数ビットの情報と通信する必要がありますが、一旦接続が確立すれば、必要となるのはいくつかの主要ヘッダーのみです。結果として長短のヘッダー形式が作り出されました。長いヘッダーは、表現豊かで拡張性のある構造で、接続を確立しやすく今後の拡張に対応できるようになっています。短いヘッダーは、効果的となるよう設計されていますが、これは接続中のパケットの大半がこのヘッダーを転送する想定であるためです。接続の確立後にQUIC が使用するのは、4 バイトという小ささの短いパケットヘッダーです。
接続 ID
トランスポートプロトコルにおける長年の問題は、クライアントとサーバーの IP アドレスとポート番号という 4 つのタプルによって接続が識別されることです。たとえば TCP 接続の場合、クライアントの IP アドレスやポート番号に変更があると接続が途切れてしまいます。これはつまり、従来の接続には伝クライアントの移動や接続中にエンドポイントのポート番号を変更する可能性のあるミドルボックスに対する耐性がないことを意味します。努力にも関わらず、これまでのソリューションは広範囲の展開を避けていました。
QUIC ならこの問題を一度にすべて解決することができます。初期の QUIC の設計は、クライアントが選んだ 8 バイトの接続 IDを使用して接続を識別していました。これが IP アドレスとポート番号のタプルの代わりとして使用されていたのです。しかしながら、この設計には根本的な欠陥が 2 つありました。
それは、サーバーが接続 ID をコントロールできないこと、そしてサーバーのインフラストラクチャが接続したパケットを正しいサーバーにルーティングするのに必要な情報を ID に埋め込むことができない ということです。
接続 ID は、クライアント側で IP アドレスが変更されても保持されるので、クライアントが新たなネットワークポイントに移動しても (例えば、Wi-Fi ネットワークからモバイルネットワークに切り替えるなど) 接続が中断されずに継続できるようにしました。しかし、第三者のオブザーバーが同じ接続 ID が表示されているその他の無関係なネットワークに基づいてクライアントの動きを関連付けることができたので、これにより個人情報の漏えいになってしまいました。
数回の繰り返しの後、最終的にこの設計は、対応するエンドポイントによって選択された各方向に1つずつ、2つの可変長の接続IDを使用することに置き換えられました。グループは両方のエンドポイントにその接続 ID を接続中に変更する仕組みも構築しました。これによりクライアントが接続を失うことなくネットワーク間を移動することができ、プライバシー漏えいを回避するよう接続 ID を変更することも実現しました。しかし、この新たな設計では、特に接続 ID の通信や変更に関わるルーティングの安定保証についていくつかの課題も発生しましたが、最終的に解決されています。
接続の移行は QUIC の興味深い新機能です。Fastly はこの機能がアプリケーションで実際に使用されることを楽しみにしています。
HTTP マッピング
gQUIC はシンプルな方法で HTTP セマンティクスのトランスポートを提供していましたが、これにはヘッドオブラインブロッキング問題があり、HTTPトレーラを処理していませんでした。QUIC ワーキンググループは、他のアプリケーションが構築できるように QUIC の上に新規サーフェスを形成することで、HTTP と QUIC をきれいな分離を作りました。このサーフェス上にHTTP 用の新たなマッピングが作成されました。QUIC ストリームとストリーム ID のための新しいセマンティクスが作成され、HTTP Pushといった要件に対応するため単一方向のストリームが作成され、 HTTP トレーラーが搭載されました。
幾度となる議論を経て、QUIC と HTTPbis ワーキンググループのコンセンサスにより、このマッピングを HTTP/3 と呼ぶことで合意されました。
さらに、QPACK として知られる QUIC 経由の HTTP ヘッダー向けの新たなヘッダー圧縮方式は、 HTTP/2 の HPACK の代替として設計されました。QPACK は QUIC ストリームの並列性を採用して、ヘッドオブラインブロッキング問題を回避しています。
オペレーター問題
ネットワーク事業者は、ネットワーク管理性の問題を取り上げました。TCP では 、QUIC ネットワークでは見せていない接続情報が表示されていたのです。ワーキンググループの主な疑問は、ネットワーク仲介者に対してどの程度の情報を開示すべきかということでした。多数の議論と設計変更の結果、最終的な解決策となったのは Spin Bit でした。これは暗号化されていない (ただし、エンドポイントに認証されている) ヘッダー内の単一ビットで、これを使うとネットワーク仲介者がフローの往復時間の変化を測定することができます。このビットはエンドポイントが設定し、そしてここが重要なのですが、エンドポイントがプライバシー上の懸念があると判断した場合は、ビットの「スピニング」を一方的に無効化できるということで合意されました。これは、IETF が設計するその他のエンドツーエンドプロトコルにとって重要な出発点となりました。ネットワークデバイスは通常、エンドツーエンドのプロトコルヘッダーからフローに関する情報を取得します。しかし、QUIC では Spin Bit を使ってネットワークにこの情報を明示的に共有しているのです。
必要な複雑性
QUIC の最終設計が、必要以上に複雑になっていないかどうか振り返る必要があります。ワーキンググループは、できる限り多く暗号化することで、固定化しつつあるミドルボックスに直面しても、プロトコル設計者と実装者がプロトコルの将来の進化を制御できるようにすることに合意しました。パケット番号の暗号化は、プロトコルの固定化や情報漏えいの潜在的なリスクに対する過剰な仕組みであり、ネットワーク管理デバイスへのコストは小さくないという意見があるかもしれません。また、エンドポイントが有効にする要素が不明瞭だとして、 Spin Bit を不要な仕組みだとする人もいるでしょう。
QUIC の複雑性は、今日のインターネットにおけるエコシステムの相互作用を管理するのに必要なことを反映していると私たちは思っています。現代のインターネットにはさまざまなステークホルダーがおり、インターネットを進化させるという点において、皆別々の、時には対立する方向への長期的な関心を持っています。たとえば、プライバシーやプロトコルが進化できるかどうかは、ネットワーク管理のニーズと衝突する場合が多くあります。QUIC の設計にもこの葛藤が反映されています。
つまり、QUIC は現代インターネットの需要と同じくらいシンプルであるということです。そして、それは実際には非常に複雑なのです。
ワーキンググループが、すべてのトレードオフを正しく理解していなかった可能性も大いにあります。しかし、この新たなプロトコルにおける時間と経験が役に立つでしょう。プロトコルが進化し続ける限り、経験が未来のバージョンを形作り続けるのです。
さまざまな設計の決定につながった広く深い議論のすべてを取り上げることは不可能です。しかし、幸いなことに、これらの議論はすべて GitHub Issues やワーキンググループのメーリングリスト、ワーキンググループの会議の議事録に公開されています。
今後の展望
実装、デプロイ、数え切れないほどの議論を通じて、QUIC は独自のアイディアから IETF が開発した完成度の高いプロトコルへとゆっくりその道を歩んでいます。QUIC を広範囲に展開することで未検討もしくは重要とされていなかった問題が見つかり、新たな事例がきっと発生するでしょう。そして、プロトコルは進化し、新たな課題に対応すべく成熟し続けていきます。
IETF のワーキンググループは、QUIC の最初のバージョンをラップアップし、インターネット全体への展開の準備を整えようとしています。Fastly もお客様ができるだけ早く QUIC の恩恵を受けられるよう、QUIC の展開準備に取り組んでいます。また、Fastly 独自の QUIC 実装 quicly にも熱心に取り組んでいます。現在、本番環境への移行段階にあり、早期ベータ版のリリース準備をしています!引き続きブログをご覧になり、Fastly のQUIC 製品や QUIC における今後の展開をご確認ください。