QUICのPath MTU Discovery手法の論文を読んで

QUICに関するEPIQ 2021というワークショップで、「The search of the path MTU with QUIC」という発表がありました。

論文と発表スライドはEPIQ 2021のページより見ることができます。

簡単に内容に目を通していきたいと思います。

TL;DR 3行で

  • RFC 9000 QUICは1280バイト以上のIPパケットを送信する場合に、Path MTU Discoveryを行う必要がある
  • Path MTU Discoveryの方法としてRFC 8899 DPLPMTUDを使用するが、RFC 9000 QUICでは具体的な探索アルゴリズムを与えていない
  • 本論文では、7種の探索アルゴリズムに対して4種類の評価項目を評価及び、シミュレーションを行った。

前提

RFC 9000 QUICのPath MTU Discovery

1280バイトのIPパケットは通る事を想定し、QUICのRFC9000ではデータグラムのサイズは1200バイトを初期の上限に設定されます。Path MTU Discoveryを行うことでそれ以上のサイズのIPパケットを送信できるようになります。(IPv4を使う場合はDon't Fragmentフラグを設定しなければなりません)

ICMPを使ったPath MTU Discovery方式として、下記のRFCで定義されるとおりです

しかし、インターネット上の経路ではICMP (Packet Too Big)がフィードバックされない場合もあるため、上記の手段が使えない場合があります。

RFC 8899 Packetization Layer Path MTU Discovery for Datagram Transports」では、QUICのレイヤでプローブを送りPath MTU を探索します。

RFC 8899 DPLPMTUDとQUIC

RFC 8899 DPLPMTUDは次のようなフェーズを持ちます。
f:id:ASnoKaze:20211219235750p:plain

  • Base: 最初に基本的なサイズでプローブを送ります。QUICでは指定された1280バイトが通ることが前提となるので次のフェーズから始まります。
  • Search: プローブを送りながら、候補となるPath MTUを探索する。最良であろうPath MTUを検出すると次のフェーズに進みます。
  • Search Complete: 経路変更に伴いPath MTUが変わる可能性があるため、依然として最良か確認する

なお、プローブはQUIC PINGフレームとPADDINGフレームで構成されます。PINGフレームはack-elicitingフレームですので、受信側はAckを返す必要があります。

プローブには3つの結果があります

  • Acknowledgement: プローブ送信側はピアからのackを受信する。これにより、送ったプローブのパケットサイズが送信可能なことがわかります。
  • Loss: QUICのロス検出(RFC9002)により送ったプローブがドロップしたことがわかります。パケットロスはパケットサイズに関わらず発生するため、RFC8899の通りMAX_PROBES回試行後に送ったプローブのパケットサイズが送信できないことが分かります。
  • PTB: プローブパケットに対して、PTBにはPTBを送った側のMTUが含まれます。その値が可能なパケットサイズの最小値となります。

The search of the path MTU with QUIC

「The search of the path MTU with QUIC」の内容に触れていきます。

PMTU Candidates

本論文では、PMTU候補として 1280バイトから1500バイトまで4バイトおきの値を候補とします。

探索アルゴリズム

本論文では、7つの探索アルゴリズムを比較します。その7つについて説明します。

  • UP: 小さい方から順番に試行します
  • Down: 大きい方から順番に試行します
  • OptUp: 最初に最大値をためしてから、小さい方から順番に試行します
  • DownUp: 未試行の最大値・最小値を交互に試行します
  • Binary: 二分探索で試行します
  • OptBinary: 最初に最大値をためしてから、二分探索で試行します
  • Jump: 幅をもたせ大きい方から成功するまで試行し、そこから失敗するまで値を上げて試行しながら絞り込んでいく

f:id:ASnoKaze:20211220002721p:plain
(発表スライドより)

評価項目

7つの探索アルゴリズムの評価する上で4つの評価項目をあげています

  • Number of probed PMTU candidates: 送ったプローブの数
  • Network Load: 送信したデータ量
  • Time: かかった時間
  • Average PMTU Estimation: 探索中に利用できたPMTU

PTBが無い場合は、それぞれのアルゴリズムは次のように評価されています
f:id:ASnoKaze:20211220003130p:plain
(論文より)

論文では、Binary>OptBinary>Jumpの順で良いと述べています。

シミュレーション

本論文では、シミュレーションを行っています。次の通り構成しています。

f:id:ASnoKaze:20211220003555p:plain
(論文より)

f:id:ASnoKaze:20211220004918p:plain

シミュレーションで、一般に良い結果を示していたOptBinary, OptBinary でいくつかの実験を行っています。

  • Figure4: データ送信量がある状態で、Path MTU Discoveryにかかる時間
  • Figure5: パケットロスがある環境での、プローブ回数とかかる時間
結果

ココまでの結果を踏まえて、この論文では次の通り述べています

  • 一般にOptBinaryを使用することをお勧めします。ただし、現在一般的なPMTU候補の小さいがまだ正確なセットがわかっている場合、このセットを最初に使用するように構成されたJumpは、バイナリよりもパフォーマンスが優れている可能性があります。

また、PTBを引き起こすことはメリットが有るため、OptBinaryなど最初に大きなパケットを送ること評価しています。

今後の課題

また、論文では、今後の取組としては、次の課題をあげている

  • SearchCompleteフェーズでのPMTU推定の検証
  • プローブパケットの輻輳を制御

メディアタイプで複数サフィックスを許可する提案仕様

HTTPレスポンスでは、content-typeとしてメディアタイプ(MIME Type)が指定されます。
例えば次のようなものがあります。

  • content-type: text/html
  • content-type: text/javascript
  • content-type: image/svg+xml

メディアタイプは "+" でサフィックスをつけることが出来ます。
例えば次のようなものがあります。

RFC 6838ではサフィックスは一つのみが想定されています。
このサフィックスを複数つけられるようにする「Media Types with Multiple Suffixes」という提案仕様が出ています。

すでにW3Cの「Decentralized Identifiers(DID)」の仕様では、複数サフィックスのメディアタイプを利用しており、IETF側でもそれをサポートできるようにするという流れです。(なぜDIDで複数サフィックスを選んだかまでは追えてない...)

特に複雑な仕様ではなく、右側から解釈していきますよという話なようだ。

f:id:ASnoKaze:20211203005602p:plain
(IETF 112 mediaman WG スライド)

QUIC Version 2 の仕様 (RFC 9369)

(追記: 2023/06/01 RFC 9369になりました)

QUIC Version 2」という仕様が提案されています。これは、「RFC 9000」で標準化されたQUIC v1と機能上はまったく同じものです。

この提案仕様の目的は、主にふたつあります。

  • 硬直化(ossification)の問題を緩和し将来のQUICバージョンをインターネットでデプロイしやすくする
  • バージョンネゴシエーションを実行できるようにする

11月に実施されたIETF 112の後に、QUIC WGのメーリングリストで、この仕様にWGとして取り組んでいくコンセンサスが得られました。現在はWG Draftとなっています。

なお、Version 2はまだ2番目のバージョンということで便宜上そう呼んでいるようです。バージョン番号の正式なアサインは後に行われます。

硬直化(ossification)の問題の緩和

硬直化とは、新しいバージョンのプロトコルを使おうとしたときに、対応していないネットワーク機器やミドルウェアが不具合を起こし、通信が阻害されることを言います。TCP Fast Openや、TLS 1.3 などで、ハンドジェクは完了するが片方向で通信がブロックされるといった、おかしな挙動をするネットワーク機器が見つかり、問題になりました。

QUICも硬直化する可能性があります。将来デプロイされるQUICv2に対応してない実装が誤ってそのパケットを処理し、不具合が起き通信が阻害される可能性があります。Google QUICでの実験ではその問題がすでに起こっていたことを明らかにしています。もちろん、IETF QUICでは硬直化が起きないように対策されています。

QUICv1のパケットは、暗号化にバージョン固有のソルトを使用しています。将来のQUICでも同様にバージョン固有のソルトを使えば、そのバージョンに対応していない(=ソルトを知らない)実装は、暗号的に初期パケットを解読できません。ですので、間違えて処理をするという問題を軽減されています。

QUIC Version 2では、これらのバージョンに固有な暗号用のパラーメータが実装上正しく変えられるようになります。逆にQUIC Version 2に対応していない実装が、QUIC Version 1のロジックで復号しようとするネットワーク装置などの問題をあぶり出すことが出来ます。

暗号関連の変更点

QUIC Version 2で変更される暗号関係のパラメータは次のとおりです。

QUIC Version 2」では、initial_salt を次のように指定しています。

initial_salt = 0xa707c203a59b47184a1d62ca570406ea7ae3e5d3

またパケット保護に使う鍵の導出に使うラベルも変更されます

  • quic key => quicv2 key
  • quic iv => quicv2 iv
  • quic hp => quicv2 hp
  • quic ku => quicv2 ku

Retry Integrityタグに使う値は次に変更されます

secret = 0x3425c20cf88779df2ff71e8abfa78249891e763bbed2f13c048343d348c060e2
key = 0xba858dc7b43de5dbf87617ff4ab253db
nonce = 0x141b99c239b03e785d6a2e9f

バージョンネゴシエーション

QUICはクライアント・サーバ間で使用するQUICバージョンをネゴシエーションします。将来標準化されるQUICの登場を待ってその仕組を作るのではなく、すでに「https://www.ietf.org/id/draft-ietf-quic-version-negotiation-05.html」として標準化が進められています。この仕組を実際に使っていくことで、将来のQUICバージョンのデプロイをしやすく出来ます。バージョンネゴシエーションを行う選択肢として「QUIC Version 2」の標準化を行っているという意味もあります

バージョンネゴシエーションの仕組みは以前書いたとおりになります。
asnokaze.hatenablog.com

アプリケーションでの利用、拡張機能

QUIC Version 2は、機能上QUICv1と代わりありません。QUICv1を使うアプリケーションプロトコルは、ALPNの変更無くQUIC Version 2を使用出来ます。

また、QUICv1で機能する拡張は、QUIC Version 2でも使用できます。

その他

ふと、疑問が一点。
QUICv1で通信したことある、Version 2に対応しているクライアントとサーバがいたとする。次の通信で、QUICv1で0-RTTを投げたときにCompatible Version NegotiationしたときのEarly Dataの扱いは、実装依存なのかな?ハンドシェイク上はただのPSKという感じで?

なんだかややこしい...orz

新しいQUICのマルチパス拡張の仕様

Multipath-TCPのように、複数の経路を使用したQUIC通信を可能にする『Multipath Extension for QUIC』という提案仕様が出されています。これにより、例えばWi-Fiとキャリア回線を両方使った通信も行えるようになります。

QUICのマルチパス機能は、長らく議論されており、複数の提案仕様が出されていました。それらについては、去年書いた記事を御覧ください。
asnokaze.hatenablog.com

今回提出された、『Multipath Extension for QUIC』は、いままで出てきた提案仕様に共通するコア機能にフォーカスした仕様となっています。

f:id:ASnoKaze:20211114234421p:plain
(IETF 112 の発表スライド PDF)

なお、この提案はIETF 112でも議論になり、この仕様を元に議論を進めていくコンセンサスが得られそうです。

設計

Multipath Extension for QUIC』の基本的な設計は次のとおりです。

  • RFC 9000 QUICv1の仕組みを可能な限り再利用する。特に、コネクションマイグレーションのパス検証(path validation)の仕組みを利用する
  • パケットはQUICv1と同じパケットヘッダー形式を使用する
  • 輻輳制御、RTT測定、PMTU検出はパスごとに行う。(各パスの利用スケジューラについてドキュメントでは定義しない)
  • パスは送信元/送信先IP・送信元/送信先ポートの4タプルごとに一つとなる。なお、パスごとにコネクションIDは異なるものが使用される(QUICv1の通り)

複数パスの利用は、コネクションマイグレーションと同じ手順を踏みます。このときにコネクションをマイグレーションするのではなく、同時に利用できるようになるのが大きな違いです。

その他に大きな違いは、次のとおりです。

  • パスを破棄する PATH_ABANDONフレームの定義
  • シングルパケット番号空間/マルチパケット番号空間の定義

- マルチパケット番号空間利用時の、ACK_MPフレームの利用

順番に見ていきましょう。

(この提案仕様では、複数パス上でやりとりするパケットを管理するのに、シングルパケット番号空間/マルチパケット番号空間と2種類の方法を定義しています。どちらか一つになることを想定していますが、実際に試しながら議論を進めていくようです)

パケット番号空間

先述の通り、シングルパケット番号空間/マルチパケット番号と二種類の管理方法があります。

シングルパケット番号空間

f:id:ASnoKaze:20211115001127p:plain
(中間会議にスライド)

複数のパスで単一のパケット番号空間を利用します。このとき、QUICv1と同じACKフレームを利用します(どのパスで受け取ったパケットに対して、どのパスでもACKを返せます)

マルチパケット番号空間

f:id:ASnoKaze:20211115001906p:plain
(中間会議にスライド)

複数のパスごとに独立したパケット番号空間を持ちます。パスをしてしてACKを返すことが出来る、ACK_MPフレームを用います(ACK_MPを送るパスと、ACK_MPの対象となるパスは異なって良い)

f:id:ASnoKaze:20211115002510p:plain

通常のACKフレームとは異なり、パケット番号空間を示すPacket Number Space Identifierがある。Packet Number Space IdentifierはコネクションIDはによって指定される。

パケット暗号時の、ナンスがユニークになるように暗号処理にQUICv1から処理が少し変更される。

ネゴシエーション

クライアントとサーバはお互いにマルチパス拡張をサポートしているかまず確認します。そのために、QUICのハンドシェイク時にトランスポートパラメータとしてenable_multipathを送信します。

enable_multipathの値は

  • 0: サポートしていない
  • 1: シングルパケット番号空間のみサポート
  • 2: マルチパケット番号空間のみサポート
  • 3: シングルパケット番号空間/マルチパケット番号空間 両方をサポート

クライアントが両方サポートしている場合は、サーバ側がどちらを使うか選択します。

また、active_connection_id_limitパラメータを使うことで、同時に使用するパスの数も制限することが出来ます。


新しいパスの利用開始

新しいパスを利用するクライアントは、PATH_CHALLENGEおよびPATH_RESPONSEを利用しパス検証を行います。

検証が成功すると、非プローブの1-RTTパケットを送信できるようになります。

パスの利用終了

パスの利用を終了するのには、PATH_ABANDONフレームを送信する (終了するパスとはことなるパスで送信しても良い)
f:id:ASnoKaze:20211115002920p:plain

Path Identifierで終了するパスを指定する。指定は、コネクションIDで指定するか、送信しているパスが対象であることを伝える事ができる。

新しいHTTPメソッド、QUERYメソッドの仕様

新しいHTTPメソッドを定義する「The HTTP QUERY Method」という提案仕様が議論されています。

もともとは、SEARCHメソッドという呼び名が候補としてあげられていましたが、長い議論ののち、一旦QUERYと呼ぶ方向となっております。最終的なFixについては、この draft 02の公開とともに改めてコンセンサスを求めた後に行われます。

QUERYメソッド

「GETリクエストにボディを付けたいという」という質問は長らく有りました。しかし、GETやHEADリクエストでボディをつけることは非推奨となっています (参考URL)。

そのような要望のなかで、リクエストでボディを含められる冪等性の保証された新しいHTTPメソッドが検討されました。それがQUERYメソッドです。冪等性があるため、ブラウザやProxyは自動でリトライすることができます。(なお、POSTはセマンティクス上冪等ではない)

(脱線しますが、HTTPセマンティクスの用語としてはボディではなくコンテンツと呼ぶのが正しい。詳しくは「HTTPセマンティクス仕様の改訂版」参照)

また、GETでURLパラメータに含めるのと異なり、URLエンコードも不要ですし、実装によるURL長の制限に引っかかることも有りません。

キャッシュ

QUERYメソッドは通常のキャッシュする際に、ボディ(コンテンツ)をキャッシュのキーに加えます

リクエスト例

QUERY /contacts HTTP/1.1
Host: example.org
Content-Type: example/query
Accept: text/csv

select surname, givenname, email limit 10

レスポンス例

HTTP/1.1 200 OK
Content-Type: text/csv

surname, givenname, email
Smith, John, john.smith@example.org
Jones, Sally, sally.jones@example.com
Dubois, Camille, camille.dubois@example.net

0.0.0.0/8のIPアドレスなどを利用可能にする提案仕様

IPv4アドレスの枯渇すると言われ続けております。

The IPv4 unicast extensions project」では、予約されているIPアドレスなどをユニキャストアドレスとして利用可能にし、4億1900万ものIPアドレスを追加することを謳っています。

実際、IETFで予約済みアドレスをユニキャストアドレスとして使用できるようにする提案を提出しています。

単に提案するだけでなく、歴史的経緯の説明が書かれています。また、問題なく利用できるかの調査も行っており、例えば各種OSやネットワーク機器の実装の調査、クラウドサービスなどで内部的利用の調査も行っています。

IETF 112で発表があるようなので簡単に予習をしておく。

発表スライド(PDF)もあわせて参照ください。

なお、IETFへの提案は誰でも行うことが出来き、あくまで提案であるということに注意してください。ですので、すぐにIPアドレスの運用が変わるということはなく、オープンな場で議論が進められます。(ご意見のお持ちの方はもちろん参加できます)

240.0.0.0/4

240.0.0.0/4は、Class Eや実験用アドレスレンジとして予約されているIPアドレスです。このレンジをユニキャストアドレスとして使用できるようにします。

このIPアドレスを、Linux, Android, macOS, iOS といったOSではユニキャストアドレスとして使用できるようです。ただし、Windowsではブロックされると述べています。

GCPのドキュメント(URL)では、VPCのサブネットとしてこのレンジが利用できると書かれています。

0.0.0.0/8

0.0.0.0/8は、仕様上は、RFC 792で自動構成用に予約されていました。これはRFC 1122によって廃止され、今日まで何も予約されていません。DHCPでのみ0.0.0.0が利用されています。このレンジをユニキャストアドレスとして使用できるようにします。

ユニキャストアドレスとして使うことに関して、提案仕様の中でLinuxについては『この文書で指定されている動作は、2019年7月にリリースされたバージョン5.2以降のLinuxカーネルによって実装されています。』と書かれています。

127.1.0.0 ~ 127.255.255.255

IPv6ループバックアドレスは一つしかありませんが、IPv4では 16,777,216個も確保されています。127.0.0.0/16をループバックアドレス用に利用し、127.1.0.0 ~ 127.255.255.255をユニキャストアドレスとして使用できるようにします。

ユニキャストアドレスとして使うことに関して、提案仕様の中で『LinuxおよびFreeBSDカーネルへの小さなパッチが必要』と述べています。

IPアドレスホスト部が0のもの

例えば、93.184.216.0/24サブネットの中の93.184.216.0をユニキャストアドレスとして使用できるようにします。このアドレスは1980年代の古い実装との互換性のために使用されてこなかったと述べています。

現在では、LinuxFreeBSDではデフォルトでユニキャストアドレスとして扱うようです。

おわりに

冒頭にも書きましたが、IETFへの提案は誰でも行うことが出来き、これは議論の始まりに過ぎません。これによりすぐにIPアドレスの運用が変わるということはないかと思います。

一方で、実装やインターネット通信上で多くの懸念を持たれる方もいると思います。提案者はコメントを募集されておりますので、コンタクトを取られると良いと思います。議論は IETF int-area メーリングリストで行われます (URL)。

匿名かつ検証可能なPrivate Access Tokensの提案仕様 (プライベートアクセストークン)

Private Access Tokens」という提案仕様が、Google, Apple, Fastly, Cloudflareの方々らの共著でIETFに提出されています。なお、すでに実装が進められているそうです。

この「Private Access Tokens」の一つのモチベーションに次のようなものがあります。

昨今、プライバシー保護の要求は高まっており、ユーザのIPアドレスを秘匿する、iCloud Private RelayやOblivious HTTPといった技術が出てきています。いままではIPアドレスベースでアクセスレートリミットを行っていましたが、

そのような環境でも、アクセスのレートリミットを設けたいというというのが一つの目的です。

それを、追加のユーザインタラクション無しに、かつユーザをトラッキングできないような匿名なトークンで行うというのがPrivate Access Tokens」です。

IETF 112のSec Dispatch WGのセッションで発表(Agenda)があるようですが、簡単に予習しておきます。(追記: 発表資料スライド)

なお、RSAブラインド署名やHPKEなど、使われている暗号処理はまではまだ理解できてないので概要だけ。

仕様の内容

この仕様では、大きく分けて2つのことが書かれています。

  • Private Access Tokensの発行する手順 (Issuance Flow)
  • Private Access Tokensを使用する手順 (Challenge/Response Flow)

また、各手順に置いて、登場人物がどのようなやり取りをするのかが定義されてます。

登場人物

  • Client: IssuerにPrivate Access Tokensをリクエストし取得する。Originのサービスにアクセスするために、Private Access Tokensをオリジンに提示する。
  • Mediator: IPアドレスやアカウント名などの情報をも使用してClientを認証する。ClientをIssuerに対して匿名化し、匿名化されたClientとIssuerのやりとりを中継する。
  • Issuer: Originに代わって匿名化されたClientにPrivate Access Tokensを発行する。OriginをMediatorに対し匿名化し、Originのポリシーを適用する。
  • Origin: ClientをチャレンジでIssuerにリダイレクトする。そして、クライアントからのレスポンスとしてPrivate Access Tokensを受け取る。Clientにコンテンツやサービスを提供する。

IssuerはOriginによって選択されますが、MediatorはClientによって選択されます。

IssuerはOriginがClientに課したいポリシーを知っており、Originに代わりそれらを課します(ポリシーは、クライアントごとに10アクセスに制限すると言った例)。なお、IssuerへアクセスではClientの情報は匿名化されているため、本当のユーザはわかりません。

各登場人物は処理が必要な情報だけしか知りえません。共謀しないとい前提で、各登場人物がどのような情報を知りえるかは仕様の方を御覧ください。

大雑把な流れ

大雑把な流れは以下のとおりです。赤字がChallenge/Response Flowになります。

  • ClientがOriginにアクセスする
  • Originは、Challenge/Response Flowの一環としてOriginからIssuerにリダイレクトを行う。このとき、WWW-AuthenticateヘッダでTokenChallenge及び、Issuance Flowに必要な情報をClientに通知します
  • Clientは、TokenChallengeをブラインド処理し、Issuer固有の鍵で暗号化した上で、Mediatorを介してIssuerにPrivate Access Tokensを要求します。
  • Issuerは、復号を行い、各種検証を行った後、ポリシーの適応とPrivate Access Tokensの発行を行います。Mediatorを介してClientに渡されます。
  • ClientはChallenge/Response Flowの一環として、ResponseをOriginに送信します。

感想

Issuance Flowの細かいところ難しい...