GoogleのQUICプロトコル:TCPからUDPへWebを移行する

QUIC(Quick UDP Internet Connections)プロトコルは、TCPではなくUDPをベースとして開発された、全く新しいWeb向けのプロトコルです。

(冗談で)TCP/2と呼ぶ人までいます。

私がQUICについて知ったのは数週間前のことです。SysCast Podcastのcurlとlibcurlについてのエピソードを聞いていた時でした。

QUICプロトコルの本当に面白い点は、UDPへの移行というところだと思います。

現在、Webの伝送プロトコルは、信頼性を確保するため、TCP上に構築されています。このTCP接続を開始するためには、3wayハンドシェイクが行われています。つまりこれは、接続を開始するたびにラウンドトリップ(ネットワークパケットの往復)が追加されるということであり、新たな接続先に対し大幅な遅延を生じさせているのです。

tcp_3_way_handshake

(出典:UDPを介した次世代多重トランスポート(PDF)

それに加えて、暗号化された安全なHTTP接続を行うために、TLSとのネゴシエーションも必要ということになると、さらに多くのパケットをネットワーク間でやり取りしなければなりません。

tcp_3_way_handshake_with_tls

(出典:UDPを介した次世代多重トランスポート(PDF)

TCP Fast Openのような革新はTCPの状況を改善するとは思いますが、これはまだ広く普及しているわけではありません。

一方、UDPはFire and Forget(撃ちっ放しの)プロトコルだと言えます。メッセージがUDPで送信されると、後は宛先に到達するものだと想定されています。これの利点は、ネットワークでパケットを検証するために費やされる時間が少ないということです。欠点は、信頼性を確保するには、パケットのデリバリ確認ができるよう、UDPの上に何かを構築しなければいけないということです。

そこで、GoogleのQUICプロトコルが登場します。

QUICプロトコルは、接続を開始すると、全てのTLS(HTTPS)パラメータを1つか2つのパケットでネゴシエートすることができます(パケット数は、接続先が初めて接続する新しいサーバか、既に接続したことのあるホストかによります)。

udp_quic_with_tls

(出典:UDPを介した次世代多重トランスポート(PDF)

これにより、最初の接続とページの読み込みに大きな差が出ることになります。

なぜQUICが必要なのか?

QUICプロトコル開発チームがやろうとしていることは、それはもう衝撃的なことです。チームは、UDPプロトコルの持つ速さと発展性に、TCPプロトコルの持つ信頼性を組み合わせた新しいプロトコルを開発しようとしています。

これについてはWikipediaがうまく説明しています。

Googleは、TCPの改善を長期的な目標とし、まずはQUICを独立したTCP接続と同等のものにすることを目標としている。ただし、QUICはできるだけレイテンシが少なく、ストリームの多重化通信ができる改良型SPDY的なプロトコルにすることを目指す。

QUICの機能が有効なものだと判明すれば、そうした機能をTCPとTLS(とりわけデプロイサイクルが長い)の後継バージョンに移行することができる。

QUIC

上記の中で強調したい部分があります。「QUICの機能が有効なものだと判明すれば、そうした機能をTCPとTLS(とりわけデプロイサイクルが長い)の後継バージョンに移行することができる」というところです。

今やTCPプロトコルは非常に高度に統制されています。WindowsやLinuxカーネルばかりでなく、個々のスマートフォンのOSにも実装されています。あらゆる低レベルデバイスでも、ほとんど実装されているのです。TCPがうまく機能しているところでそれを改善しようとすれば、TCPが実装されている先述のデバイスもそれに対応しなければならないわけですから、険しい道のりになります。

一方、UDPは設計においては比較的シンプルです。GoogleがTCPについて考えている理論のいくつかを証明するには、UDPの上に新しいプロトコルを実装する方が速く進められるのです。そうしてネットワークの輻輳や、ストリームのブロックなどについて、理論を実証できれば、後はQUICの利点をTCPプロトコルへ移行することについて検討できるようになります。

とは言え、TCPスタックを変更するとなると、それぞれのTCPスタックをアップデートするために、LinuxカーネルやWindows、仲介するミドルボックス、ユーザなどによる作業も必要になります。UDPでも同じことを行うのは、プロトコル開発者にとってはもっと難しいものにはなりますが、ただ開発者は工程の繰り返しをずっと高速に行うことができ、数年、数十年とかかるわけではなく、数カ月で、こうした理論を実装することができます。

QUICの位置付けは?

現代のHTTPS接続を構成する層で言うと、QUICはTLSスタックとHTTP/2の一部を置き換えることになります。

QUICプロトコルは、既存のTLS 1.2を使わないため、独自の暗号化層を実装しています。

tcp_udp_quic_http2_compared

TCPの位置にはUDPが置き換わり、QUICの上にはリモートサーバとの通信に使われる、より小さなHTTP/2 APIが置かれています。より小さい理由は、多重化および接続管理はQUICで処理されるためです。後は、HTTPプロトコルの解釈です。

TCPのヘッドオブラインブロッキング

SPDYとHTTP/2では現在、ページのアセットそれぞれに対し複数の接続を確立するのではなく、サーバに接続する1つのTCP接続だけを確立しています。その1つのTCP接続は独立してリソースを要求して受け取ることができます。

spdy_multiplexed_assets

(出典:QUIC:UDPを介した次世代多重トランスポート

全てがその1つのTCP接続に依存しているため、ある欠点が生じています。それがヘッドオブラインブロッキング(Head-of-Line Blocking、HOLブロッキング)です。

TCPでは、パケットは正しい順序で到達する処理される必要があります。パケットがサーバに、あるいはサーバから送られる途中でパケットロスが生じた場合、それは再送されなければなりません。TCP接続では、TCPパケットが処理される順序が重要であるため、残りのパケットの処理を続けるのではなく、ロスが起きたTCPパケットを待つ(または”ブロックする”)必要があるのです。

spdy_multiplexed_assets_head_of_line_blocked

(出典:QUIC:UDPを介した次世代多重トランスポート

QUICでは、もはやTCPを利用しないことにより、この問題は解決されます。

UDPはパケットを受信する順序に左右されることはありません。パケットの送信中にロスが生じる可能性はありますが、それは(1つのCSS/JSファイルに含まれているような)個々のリソースに影響を及ぼすだけでしょうし、接続全体をブロックすることはありません。

quic_multiplexing

(出典:QUIC:UDPを介した次世代多重トランスポート

QUICの本質は、ブロッキングを行わないトランスポート層プロトコルの上に構築した、SPDYとHTTP2(多重化)のいいとこ取りをしたプロトコルだと言えます。

なぜパケットを減らすことが重要なのか?

あなたが幸運にも高速インターネットを使っているのなら、あなたとリモートサーバ間のレイテンシは10~50msの範囲です。あなたがネットワーク経由で送信する全てのパケットが受信されるには、そのくらいの時間がかかっています。

レイテンシが50ms未満では、利点はすぐには分からないかもしれません。

しかし、例えば別の大陸にあるサーバや、あるいはEdgeや3G/4G/LTEを使うモバイルキャリアを介して、あるサーバにアクセスするときには、レイテンシは見過ごせないものになります。ヨーロッパからアメリカのサーバにアクセスするには、大西洋を横断しなければなりません。行き来しなければならない物理的な距離があるため、それだけですぐさま100ms以上のレイテンシが加わるという不利益を受けることになります。

network_round_trip_europe_london

(出典:QUIC:UDPを介した次世代多重トランスポート

同種のレイテンシはモバイルネットワークにもあります。接続が低速な場合、電波と経由するネットワークだけが原因で携帯電話とリモートサーバの間のレイテンシが100~150msになることは、なくもありません。4G/LTEなら、50msほどのレイテンシになります。

モバイルデバイスを使った長距離ネットワークの場合は、4つのパケット(TCPとTLSの場合)を送受信するのと1つのパケット(QUICの場合)を送受信するのとでは、初期の接続のために省ける時間が最大300msも違うことがあるのです。

前方誤り訂正:エラーを防ぐ

QUICで巧みな機能は、前方誤り訂正(FEC)です。再送信しなくても欠落したパケットを復元できるよう、送信された全てのパケットにも他のパケットの十分なデータが含まれています。

これは本質的に、ネットワークレベルのRAID 5です。

そのため、トレードオフも発生します。このように、より簡単に復元できるよう、欠落パケットのポテンシャルが付加されるので、各UDPパケットには厳密に必要となる以上のペイロードが含まれるのです。

現行の割合は10パケットぐらいでしょう。つまり、10個のUDPパケットが送信されるたびに、欠落したパケットを再現するために十分なデータが用意されるということです。言ってみれば10%のオーバーヘッドです。

FECを、ロスしたパケットの再送を不要にするために生じる、”UDPパケット1個当たりのデータ“という形の犠牲と見なすとよいでしょう。ロスしたパケットを再送する方が、ずっと時間がかかるからです(受信側は欠落したパケットを確認し、再要求し、応答を待つ必要があるため)

セッション再利用と並列ダウンロード

UDPへの切り替えでは、もう一つの素晴らしいメリットがもたらされます。接続の送信元IPに依存しなくなるということです。

TCPでは、接続が成立するためには4つのパラメータが必要です。いわゆる四つ組です。

新たなTCP接続を開始するには、送信元IP、送信元ポート、宛先IP、宛先ポートの情報が必要です。Linuxサーバでは、この四つ組をnetstatコマンドで確認できます。

$ netstat -anlp | grep ':443'
...
tcp6       0      0 2a03:a800:a1:1952::f:443 2604:a580:2:1::7:57940  TIME_WAIT   -
tcp        0      0 31.193.180.217:443       81.82.98.95:59355       TIME_WAIT   -
...

パラメータ(送信元IP、送信元ポート、宛先IP、宛先ポート)のいずれかが変わった場合は、新たなTCP接続が必要となります。

そういう訳で、モバイル端末では、WiFiと3G/LTEを絶えず切り替える可能性があることから、安定した接続を維持するのが非常に難しいのです。

quic_parking_lot_problem

(出典:QUIC:UDPを介した次世代多重トランスポート

QUICはUDPを使用しますので、四つ組がありません。

QUICは、一意の接続に対する独自の識別子「Connection UUID」を実装しています。WiFiからLTEに切り替えてもConnection UUIDを維持することができるので、接続やTLSを再ネゴシエートする必要がありません。前回の接続は引き続き有効です。

これはMosh Shellと同様の仕組みです。Mosh Shellは、ローミングとモバイルエクスペリエンスを向上させるために、UDP上でSSH接続を維持します。

またこの仕組みのおかげで、複数の送信元からコンテンツを取得する可能性が生まれます。Connection UUIDがWiFiおよびセルラー接続を越えて共有できるのなら、理論上は、コンテンツのダウンロードに両方の媒体を使うことが可能です。利用可能なあらゆるインターフェースを使って、コンテンツのストリーミングやダウンロードを事実上並列で実行できるということです。

理論上の段階ではあるものの、UDPを使えば、そうした新たなことが可能になるのです。

QUICプロトコルを使う

Chromeブラウザは、2014年からQUICを(試験的に)サポートしています。QUICを試してみたい方は、Chromeでこのプロトコルを有効にすることができます。QUICプロトコルをテストできるのは実際上、Googleのサービスに限られています。

Googleの最大の強みは、ブラウザサーバの両方で市場シェアを持っていることです。QUICをクライアント(Chrome)とサーバ(YouTubeやGoogle.comといったGoogleサービス)の両方で有効にすることで、Googleは新しいプロトコルの大規模な試験を本番環境で実施できるのです。

HTTP/2とQUICプロトコルをブラウザ内のアイコンとして表示する、便利なChromeプラグインがあります。HTTP/2 and SPDY indicatorです。

chrome://net-internals/#quicタブを開くと、QUICの現在の使用状況を確認することができます(前述したConnection UUIDも表示されます)。

quic_net_internals_sessions

下位レベルの詳細に興味があれば、chrome://net-internals/#events&q=type:QUIC_SESSION%20is:activeで全てのライブ接続を表示し、個々のパケットごとのキャプチャを見ることも可能です。

quic_debug_packets_chrome

SPDY接続やHTTP/2接続の内部を見る手順と似ています。

ファイアウォールとの関連は?

この記事はTCPではなくUDPを使うQUICがテーマですので、システム管理者やネットワークエンジニアの方は、冒頭でちょっと肩をすくめたことでしょう。それももっともだろうと思います。

例えば、私たちNucleus Hostingでは、Webサーバのファイアウォールを設定する際、以下のようなルールを適用しています。

firewall_http_https_incoming_allow

プロトコルの列に「TCP」とあることに注目してください。

当社のファイアウォールは、他の大勢のシステム管理者が運用しているものとさほど変わりません。現時点では、Webサーバで80/TCP443/TCP以外を許可する理由がないのです。つまりTCPのみであり、UDPは使用していません。

そしてQUICプロトコルを許可するには、443/UDPも許可する必要が出てきます。

サーバとしては、Webサーバで外からの443/UDPを通すことになります。クライアントとしては、インターネットで内からの443/UDPを許可することになります。

このことは、大企業では問題となりそうです。通常TCPのみを使っているポートでUDPを許可するためにセキュリティを通過させるというのは、疑わしい感じがするからです。

接続性に関して、私はこの点が最大の問題になると思ったのですが、Googleが行った実験では、そうではないという結果が出ています。

quic_connection_statistics

(出典:GoogleにおけるQUICデプロイ実験
注釈
QUICが動作:93%
UDPのレートが制限されている:0.3%
UDPがASに対してブロックされている:0.2%
UDPがユーザに対してブロックされている:4.5%
Chromeが使われていない:2%

上記の数字は、スウェーデンで最近開催されたHTTP関連のワークショップで示されたものです。ここでいくつか重要な点があります。

  • QUICは現在のところGoogleのサービスでしかサポートされていないので、サーバ側でのファイアウォール設定はおそらく問題ない。
  • 上記の数字はクライアント側のみのものである。UDPの443番ポートが許可されているクライアントの数を示している。
  • コンプライアンスのため、QUICはChrome上で無効にすることができる。QUICによる接続を試みることさえできないように、QUICを無効にしている企業はたくさんあると思われる。

QUICはTLS相当の働きもしますので、心配する必要があるのはUDPの443番ポートだけです。UDPの80番ポートが近々用いられるようになるとは考えにくいところです。

暗号化された通信だけを行うのが有利な理由は、ディープ・パケット・インスペクションのミドルウェア(侵入防止システムとも呼ばれます)がTLSトラフィックを復号してプロトコルを修正することはできず、バイナリデータをファイアウォール越しに参照し(願わくは)単に通過させるということにあります。

サーバ側でQUICを実行する

現在、QUICが利用できるWebサーバはバージョン0.9以降のCaddyのみです。

しかし、クライアント側とサーバ側のサポートはいずれも試験的なものとされていますので、実行は自己責任となります。

QUICサポートがデフォルトで有効になっているクライアントはないので、QUICを実行して自分のブラウザでQUICを有効にしても今のところ安全上の問題はないでしょう。
追記:Chrome 52以降では、ホワイトリストに掲載されていないドメインに対しても、QUICはデフォルトで有効になっています

QUICのデバッグを進めるために、curlがQUICを早く実装してほしいものですが、curlがQUICに関心を持っていることは間違いありません

QUICの性能上の利点

Googleは2015年のブログ記事で、QUICの実装結果をいくつか公開しています。

結果、QUICはネットワーク状態が不良な条件下でTCPよりも優れており、Googleの検索ページをロードする時間は、接続の中で最も遅い1%については丸1秒短縮されました。

これらの利点は、YouTubeのような動画サービスでより顕著になります。QUICを介して動画を見た時には、リバッファが30%減少したと報告されています。
Googleの実験的トランスポートQUICに関する最新情報(2015年)

YouTubeの統計値は特に興味深い結果です。このような改善が可能なのであれば、Vimeoや”成人向け動画配信サービス”などの動画配信サービスに採用される日も近いでしょう。

まとめ

QUICプロトコルは本当に魅力的だと思います。

QUICに多大な労力がつぎ込まれていること、そして最大のWebサイトで既に動いていて効果を挙げているということに衝撃を受けています。

QUICの仕様が固まって、他のブラウザやWebサーバで実装されるようになる日が待ち遠しい限りです。

追記:QUICの設計者Jim Roskindからのコメント

Jim Roskindがこの記事にコメントを寄せてくれましたので(こちらを参照)、ぜひ紹介させてください。

QUICの研究、設計、デプロイに長年携わってきた経験から、いくつか補足させてください。UDPポートがブロックされている背景については、QUICの(UDP上での)実行可能性を検証している際に、私も全く同じ推測をしていました(詳細な設計やアーキテクチャに取り掛かる以前)。私は、到達可能性がわずか93%となる理由は、顧客企業が一般的にUDP(おそらくDNSに必要なもの以外)をブロックしているからだと考えていました。

過去を振り返ってみると、顧客企業は”社員がネットサーフィンで時間を浪費するのを防ぐため”にTCPの80番ポートを通常ブロックしていました。その次には、ご存じのように、過度に保守的なセキュリティが台頭しています(そしてユーザビリティが変化をもたらしていますね)。外への通信に対してUDPの443番ポートを許可すればユーザエクスペリエンスが向上する(つまり社員の業務スピードが速まり、浪費される帯域幅は減少する)ことが共通認識となったので、ユーザビリティがセキュリティを再び凌駕すること、そしてUDPの443番ポートが大部分の企業で開放されるようになることを期待しています。

また、この記事の見出しに「TCP/2」という言葉が使われていることは、個人的には的確だと思います。QUICにおける輻輳回避の進化速度を考えると、QUICはインターネットの進歩(新しいハードウェアデプロイや、新しい携帯電話基地局向けプロトコルなどでしょうか)を、TCPよりもずっと速く追いかけていくのではないかと予想しています。

その結果QUICは、TCPの大部分を置き換えると同時に、TCPに組み込まれるべき技術の一部または全てを提示することになると期待しています。TCPは通常、カーネルに実装されるので、進化のステップは5~15年です(ミドルボックスとの争いはもちろん、市場への浸透を含めて)。一方、QUICは何週間や何カ月の間に進化する可能性があるのです。

— Jim(QUICアーキテクト)

Jim、コメントをいただきありがとうございます。QUICプロトコルの開発者から感想を聞くことができて大変うれしいです。

参考資料

さらに詳しく知りたい方は、以下の資料をご参照ください。

この取り組みを進めているGoogleに感謝しています。