QUICをゆっくり解説(1):QUICが標準化されました

2021年07月01日 木曜日


【この記事を書いた人】
山本 和彦

Haskellコミュニティでは、ネットワーク関連を担当。 4児の父であり、家庭では子供たちと、ジョギング、サッカー、スキー、釣り、クワガタ採集をして過ごす。

「QUICをゆっくり解説(1):QUICが標準化されました」のイメージ

不定期連載を始めます

IIJ-II 技術研究所 技術開発室の山本です。私はプログラミング言語HaskellでHTTP/2TLS 1.3を実装した後、もっぱらQUICを実装することに時間を費やしてきました。

ご存知の方もいらっしゃると思いますが、今年の5月にQUICの仕様がRFC9000として公開されました。このRFCは実によく書かれているので、読みこなせばQUICの全容が掴めるでしょう。

しかし仕様は膨大ですし、実際に実装してみて初めて腑に落ちることもあります。そこでこの機会に、実際にQUICを実装した経験者目線で、QUICの解説をしていきたいと思います。なんとなくTCP/IPを分かっている方が、ある程度QUICの理解ができることを目指します。

子育てが忙しいので、記事の公開は不定期となります。(寝付かない2歳児を僕の代わりに寝付かせてくださる方がいれば連載のペースが上がります。) あらかじめご了承ください。

プロトコル階層

QUICは、UDPを利用した新しいトランスポートプロトコルです。次のプロトコル階層の図をご覧ください。

左は、HTTP/2のプロトコル階層です。IP上にTCP、TLS 1.3、HTTP/2が乗っています。TCPは、信頼性、フロー制御、輻輳制御など、トランスポート層の機能を提供します。TLS 1.3はセキュリティ機能、HTTP/2は多重化されたHTTPの機能を提供します。

右は、HTTP/3のプロトコル階層です。IPの上にUDPが乗っています。UDPの役割はポート番号を提供することのみなので、本当に薄い層です。その上に、分厚いQUICが乗ります。QUICは、トランポート層の機能に加えて、TLS 1.3のセキュリティ機能が組み込まれています。また、HTTP/2に類似する多重化の機能も備えています。そのため、HTTP/2 を QUIC 上に実現したHTTP/3は、薄い層になっています。

特徴

QUICとTCPを比較することで、QUICの特徴を説明します。

組み込みのセキュリティ

TCPを使用する場合、TLSの利用は必須ではありません。たとえばHTTP/1.1では、歴史的には商用のサイトではTLSを利用し、それ以外ではTLSを利用してないことが一般的でした。最近では、政府などの大規模な組織による盗聴行為に対抗するために、TLSの利用を必須にしようという流れになってきています。また、メールのプロトコルであるSMTPに関して言えば、TLSを利用しているSMTPサーバは、それほど多くありません。

QUICを利用する場合、TLSのセキュリティが組み込まれているため、TLSの利用は必須となります。(細かい例外を除いて)サーバを構築する場合、たとえ実験であっても証明書(いわゆるオレオレ証明書でもOK)が必要です。これを安全になったと捉えるか、面倒だと捉えるかは、読者の判断に委ねたいと思います。

HoL (Head of Line) ブロッキングの解消

HoLブロッキングとは、行列の先頭の処理に時間がかかってしまい、先頭以外の仕事が待たされることです。HTTP/1.1では、1つの処理が終わらないと、次の処理が始められないというHoLブロッキングの問題が存在していました。HTTP/2では、TCPコネクションの中に、ストリームという単位を設けて処理を多重化/非同期化しました。HTTP/2サーバは、あるストリームの処理に時間がかかっても、別のストリームの応答を返せます。

しかしながら、TCP自体にもHoLブロッキングの問題が存在します。TCPセグメントを含むIPパケットが落ちた場合、それ以降のTCPセグメントが届いていたとしても、処理は進みません。HTTP/2で言えば、ストリームがちゃんと届けば、サーバはストリームを独立して処理できるが、どこか一部でも落ちてしまうと、全体の処理がとまってしまうということです。

QUICでは、IPパケットが落ちたとしても、影響を受けるのは関係するストリームのみで、他のストリームの処理は進められるように設計されています。

0-RTTの利用

RTTとは Round Trip Timeの略称で往復時間という意味です。RTTの前の数字は、クライアントから見てどれくらい時間が経過しているのかを示しています。以下のタイムラインを見てください。

  • 0-RTT: クライアントからサーバへの1回目のパケット送信
  • 0.5-RTT: サーバからクライアントへの1回目のパケット送信
  • 1-RTT:クライアントからサーバへの2回目のパケット送信
  • 1.5-RTT:サーバからクライアントへの2回目のパケット送信

クライアントのIPアドレスの詐称を防止したり、サーバを認証したりすることを考えると、通常のトランスポートプロトコルでアプリケーションのデータを送れるのは、1-RTTからです。0-RTTの機能とは、0-RTTの際にアプリケーションのデータが送信できることを意味します。1回目の通信で安全に通信したという証明情報を保存し、2回目の通信からは、その証明情報とアプリケーションデータを0-RTTの際に一緒に送信します。

TCPでは、0-RTTの機能を実現するTCP Fast Openが標準化されていますが、あまり利用されていないようです。また、TLS 1.3にも0-RTTの機能が提供されていますが、活用されているという話は聞いたことがありません。QUICで提供される0-RTTの機能も利用されなければ、絵に描いた餅ですが、後述のようにChromeの開発版が活用しており、普及に期待が持てます。

進化の速度

TCPは、一般的にOSのカーネル空間で実装されています。一方で、QUICはユーザ空間で実装されることがほとんどです。最近ではOSも頻繁に更新されるようになってきましたが、ブラウザといったアプリケーションの方が更新速度が早いと言えます。そのため、TCPよりもQUICの方が、すばやく進化していくことが期待できます。

ハードウェアの活用

TCPは長い歴史を持ち、その過程でハードウェアを利用した高速化が図られてきました。一方、QUICは策定されたばかりですので、ハードウェアを利用した高速化はこれからの課題です。

標準化の動向

RFC9000ばかりが話題になっていますが、現時点では以下の4つがRFCとなりました。

また、以下の2つの草稿がRFCになるのを待っています。

まだRFCとして発行されてない理由は、参考文献として参照されているHTTP Semanticsという草稿がRFCになっていないからです。

普及状況

もしみなさんが、最新のFirefoxやChromeをお使いでしたら、すでにQUICを利用しています。今回は https://www.google.com にアクセスして、確かめてみましょう。最初に通信するとき、ブラウザは HTTP/2を利用しますが、HTTPの Alt-Svc ヘッダを介して HTTP/3 が利用可能だと通知されます。そのため、2回目からの通信にはHTTP/3を使うようになります。

Firefoxの場合、「ツール」メニューから「ブラウザーツール」「ウェブ開発ツール」として開発ツールを表示さて、URLを入力します。「ネットワーク」で通信の一覧を表示し、www.google.com の通信のどれかを選択します。ここでHTTP/2と表示される場合は、ページをリロードしてみてください。(社内のネットワークなど、環境によってはリロードしてもうまくいかないことがあります。)

Chromeでは、QUIC Indicatorという拡張機能を入れておけば、QUICで通信をした際、URL右横のアイコンが緑色になります。

緑にならない場合は、リロードをお願いします。また、「表示」メニューから「開発/管理」「デベロッパー ツール」を選択して、URLを入力し、「ネットワーク」タブを選択することでも、確かめられます。

上記のスクリーンショットでは、草稿のバージョン29(h3-29)が利用されていると分かります。最後に、Chromeの開発版であるCanaryが google.com に通信したときのパケットダンプを Wireshark で表示してみましょう。

0-RTTが利用されてますね。

まとめ

QUICの仕様が策定され、一部がRFCとなりました。QUICはすでにみなさんの多くが利用しています。これから、ゆっくりQUICの解説をしていきます。

山本 和彦

2021年07月01日 木曜日

Haskellコミュニティでは、ネットワーク関連を担当。 4児の父であり、家庭では子供たちと、ジョギング、サッカー、スキー、釣り、クワガタ採集をして過ごす。

Related
関連記事