QUICのバージョンネゴシエーションとダウングレード攻撃対策

QUIC Version 1がRFC 9000として標準化されました。IETF QUIC WGでは、QUICの次のバージョンを見据えて、バージョンネゴシエーションの仕組みについて検討を始めています。

その仕組は「Compatible Version Negotiation for QUIC」としてWG Draftとなっています。この仕様は、version 1に限定された仕組みではなく、将来標準化されるQUICバージョンにも適応できるバージョンネゴシエーションの仕組みを定義しています。

将来標準化されるQUICバージョンがどのようなハンドシェイクを行うかは具体的には未定である点に注意してください。例えば、QUICv1では、TLS1.3のハンドシェイクをInitialパケットで開始し鍵を共有していましたが、将来のQUICはそうであるとは限りません。

将来に渡ってQUICが持つ不変事項については、「RFC 8999: Version-Independent Properties of QUIC」を参照してください。特に「Appendix A. Incorrect Assumptions」には、具体的な正しくない不変事項が書かれているため、理解の助けとなります。

Compatible Versions

Compatible Version Negotiation for QUIC」では、「互換性のあるバージョン(Compatible Versions)」という概念を定義しています。

QUICの通信は、クライアントからのロングパケットで開始されますが、バージョンAとバージョンBのパケットが、ワイヤ及び動作が同じ場合に互換性があるとしています。互換性のあるバージョンでは、ハンドシェイクをそのまま進める事ができます。ハンドシェイク後の動作は異なるかもしれません。

バージョンBがバージョンAのスーパーセットな場合も考えられます。バージョンAはバージョンBのパケットとして処理できるが、逆は出来ない場合もある点に注意してください。

なお、各バージョンが互換性があるかはそのバージョンの仕様の中で言及されるものです。

互換性のあるバージョン間と、互換性のないバージョン間のハンドシェイクの流れについてそれぞれ「Compatible Version Negotiation for QUIC」の中で定義しています。

Compatible Version Negotiation

バージョンAとバージョンBが互換性のある場合、は一つのコネクションのなかでハンドシェイクが進行します。コネクションを確立するのに追加のラウンドトリップは発生しません。
Version Informationについては後述します。

f:id:ASnoKaze:20210913001607p:plain

Incompatible Version Negotiation

互換性がないバージョンAから、バージョンDに切り替えてハンドシェイクを行う場合です。クライアントからの最初のパケットに対して、RFC 8999で定義されているVersion Negotiationパケットを返します。この時、サーバがサポートしているバージョンの一覧をクライアントに通知します。この流れでは、追加のラウンドトリップが発生します。

クライアントは、サーバがサポートするバージョンのうち自身が対応しているものがあれば、そのバージョンでハンドシェイクを再試行します。このとき、このハンドシェイクは別のコネクションとなります。

f:id:ASnoKaze:20210913004154p:plain

Version Information

クライアント及びサーバ(群)が対応しているQUICバージョンを相手に通知する仕組みです。QUIC version 1ではトランスポートパラメータで送信されます。

Version Informationは次の情報が入ります

  • Chosen Version: 選択したバージョン。
  • Other Versions: サポートしているその他のバージョン。サーバ側から送る場合は、冗長性のために配置されているサーバ全てで使用できるバージョンが記述されます。また、グリスのために0x?a?a?a?aが含まれうる。

クライアントは、Version Negotiationパケットをトリガーしたバージョンが、Version Informationに含まれていた場合などは、ダウングレード攻撃対策としてVERSION_NEGOTIATION_ERRORエラーでコネクションをクローズします。

参考

2019年の記事ですが、参考にさせていただきました
qiita.com