QUICのコネクションマイグレーションについて

目次

概要

QUICはUDPを使っており、QUICレイヤにコネクションを管理するためのコネクションIDを持ちます。そのため、送信元IP・ポート番号、送信先IP・ポート番号が変わっても、コネクションが切断することなく通信を続けることができます。これをコネクションマイグレーションと呼びます(QUIC-TRANSPORTの仕様)。

もちろん、QUICをトランスポートプロトコルとして使用するHTTP/3でもこの恩恵に預かります。

GoogleではすでにQUICのコネクションマイグレーション機能を実験しており、ネットワーク起因のエラーの減少に一定の効果が得られているようです(IETF104での発表資料PDF)

コネクションのマイグレーションには主に2つあります

  • キャリア回線からWi-Fi回線への移行など、エンドポイントが意図して使用するネットワークを変更するケース
  • NATリバインディングなど、エンドポイントが意図せずポート番号などが変わるケース

前者は事前に移行先のネットワークが利用できることを検証してから切り替えますが、後者はそのようにはいきません。

いずれにせよ、このコネクションのマイグレーションは安全に行われる必要があります。通信を行っている二者は鍵を共有しており、コネクションのマイグレーションが起きたとしても、鍵を知らない第三者が通信に割り込んで解読するようなことはできません。

その他にも以下のような攻撃も対策されています。

  • アンプ攻撃
  • コネクションのトラッキング
  • 攻撃者自身を経由するようなPATHの構築

セキュリティ対策

アンプ攻撃

通信経路上の第三者がパケットの送信元IPを書き換え、エンドポイントの意図しないマイグレーションが発生したことを装います。そうすることで、送信元IPが書き換えられたパケットに対する応答として、そのIPアドレスにデータが送信されます。ここで、大量のデータが流れればアンプ攻撃となります。

QUICでは、マイグレーション時に関わらず、通信相手がそのIPアドレスの所持証明をできない場合は、送信できるデータ量が制限されます。コネクションのマイグレーション時も、後述するPath Validationを行い、そのIPアドレスが正しい通信相手であることを確認します。

コネクションのトラッキング

QUICでは、コネクションIDを識別子として用います。このコネクションIDはQUICパケットヘッダに平文で格納されます。

そのため経路上の第三者は、このコネクションIDを観測することができます。

もし、コネクションマイグレーション前後で同じコネクションIDを使用している場合は、通信者がどこからどこへ移動してるか観測者はトラッキングできます。会社のWi-Fi -> LTE ->自宅のWi-Fi というふうに、どういうふうに移動したかも追うことができます。

そのため、QUICでは事前に暗号化して送信されるNEW_CONNECTION_IDフレームにて、予備のコネクションIDを相手に通知しておきます。意図してコネクションのマイグレーションを行う場合は、この呼びのコネクションIDを用いることで第三者がコネクションマイグレーション前後の通信を関連付けられないようになっています。(お互い、新しい送信先コネクションIDを使用します)

もちろんNATリバインディングなど、意図せず起こるコネクションマイグレーション時は新しいコネクションIDを使用できませんが、時間をあけてから通信を行う場合は予防的に新しいコネクションIDを仕様することが推奨されています。

予備のコネクションIDを消費した場合は、NEW_CONNECTION_IDで相手から新しく予備のコネクションIDをもらえます。

攻撃者自身を経由するようなPATHの構築

パケットを観測できる通信経路外の攻撃者は、パケットをコピーし、本来のパケットが到着するよりも先に攻撃者のパケットを届けることで、攻撃者自身を経由する経路へとコネクションマイグレーションさせることができます。

この場合、攻撃者は届いたパケットを正しく二者に配送することでPath Validationは成功します。しかし、仮に成功したとしても、マイグレーション前の経路の方が高速であれば、もとの経路に戻すことも選択できるしょう。また、コピーされたパケットが重複して届くことに対して、ヒューリスティックな対応も考えられます。

コネクションマイグレーションの手順

QUICのハンドシェイクが終わったあとであれば、コネクションマイグレーションを行うことができます。ただし、トランスポートパラーメタとしてdisable_active_migrationが設定されている場合は除きます。

エンドポイントが意図して能動的に行うコネクションマイグレーションの場合で流れを説明をします(共通部分もあります)。

事前にコネクションマイグレーションをする前に、マイグレーション先のPATHで正しく通信できるか検証を行います。これをPath Validationと呼びます。

Path validation

8バイトのランダムな値を含むPATH_CHALLENGEフレームを送信します。このPATH_CHALLENGEフレームを受け取ったエンドポイントは、同じ値を持つPATH_RESPONSEフレームでお繰り返します。

f:id:ASnoKaze:20190916013416p:plain

このやり取りも、二者間で共有されている鍵を使っているため、第三者が正しく応答することはできません。

なお、PATH_CHALLENGEフレームとともにNEW_CONNECTION_IDフレームも送ることで、相手も必ず新しいPATHで新しいコネクションIDが使用できます。

もしタイムアウトした場合はPath validationは失敗となり、もともと使用していたPATHを使用します。

コネクションマイグレーションの開始

PATH_CHALLENGE、 PATH_RESPONSE、 NEW_CONNECTION_ID、 PADDINGフレームはプロービングレームと呼ばれ、実際の利用するコネクションのマイグレーションはまだ引き起こしません。

それ以外のフレーム(非プロービングフレーム)を新しいPATHで送信することで、コネクションのマイグレーションが行われ、新しいPATHでデータを送信し始めます。

コネクションマイグレーションへの対応

一方、通信相手の方は新しいアドレスから非プロービングフレームが届いたときに、相手がコネクションをマイグレーションしたことを知ります。

これを契機に、新しいPATHで応答を開始し、こちらからもPath Validationを行います。こちらでも相手がそのIPアドレスを所持している正しい通信相手であることを確認する必要があります。

f:id:ASnoKaze:20190916020450p:plain

NATリバインディングのように、エンドポイントが意図せずIPやポートが変わった場合は、事前の手続きはなくこの処理が行われます。

コネクションのマイグレーションが終わると、エンドポイントは古いPATHを破棄できます。

輻輳制御とECN

新しいPATHでは、RTTや帯域が異なるため、輻輳コントローラを初期値にセットしなければなりません。

また、ECNをサポートしているかもわからないため、その確認作業も再度行う必要があります。