HTTP Datagram PING の拡張仕様についてのメモ

HTTP Datagram PING」という提案仕様をGoogleのBenjamin Schwartz氏がIETFに提出している。

これは、HTTP/3でのDATAGRAMフレームにおいて、PINGを送れるようにするものである。HTTP/3におけるDATAGRAMフレームの利用については以前紹介したとおりである。
asnokaze.hatenablog.com

目的

WebTransportやMASQUEでは、DATAGRAMフレームはプロキシを超えてEnd-to-Endでのやりとりに利用できるように設計されています。このHTTP Datagram PINGを使う目的は主に次のとおりである

  • End-to-Endにかけてコネクションが維持されており、通信が出来ることを確認する
  • End-to-Endで通信のレイテンシを確認する
  • End-to-EndでPath MTU Discoveryを行う

特に、3つめにあげたのが、この提案の主題でもあります。

もともとMASQUE WGでは、HTTPプロキシを超えたPath MTU Discoveryについてどのように行うか議論がありました。例えば、CONNECT-IPでは、MASQUE Proxy先のMTUを考慮してクライアントはDATAGRAMフレームを送信しなければなりません。その問題に対して一つの提案として出されたのがこの仕様です。


具体的には、トランスポートレイヤでのPath MTU Discoveryを説明した「RFC8899」で定義されている通り、DPLPMTUD Probeパケットの送信に使用できます。

なお、CONNECT-IPは以前紹介したとおりです。
asnokaze.hatenablog.com

(この仕様では、MASQUE Proxyを超えてはPath MTU Discovery出来ない?ちょっと、そこを理解できてない。)

HTTP Datagram PING

具体的なHTTP Datagram PINGの中身を確認します。

最新版の「Using Datagrams with HTTP」では、DATAGRAMフーレムに拡張性を持たせている。HTTP Datagram Format Typeとして、新しいFormat Typeを定義できる。

HTTP Datagram PING」では、新しいFormat TypeとしてPING Datagram Formatを定義している。

QUICのDATAGRAMフレーム及び、REGISTER_DATAGRAM_CONTEXT Capsule Formatも含め記述すると次のとおりである。
f:id:ASnoKaze:20210927010028p:plain

PING Datagram Formatは、シーケンス番号と任意のOpaqueデータを含みます。

PINGフレームを受け取ったエンドポイントは、同様にPINGフレームを応答する必要があります。

大体の位置情報を示すSec-CH-Geohashヘッダ

Private Relayをはじめ、Proxyを通してクライアントのIPアドレスをサーバに対して隠す技術が登場しています。

ところで、Webサービスはクライアントの位置情報によって出力する情報を変えたり、最適化を行う場合があります。JavaScriptのGeolocation APIから取得することもあるでしょうが、APIアクセスなどJavaScriptが利用できない場合もあるでしょう。その場合、IPアドレスから位置情報を類推する手段(GeoIPなど)があります。

IPアドレスから位置情報をある程度推測する手法は、IPアドレスが隠されると機能しなくなります。

Private Relayではユーザが望む場合は、Webサーバに対して大体の位置情報を提供するという観点について、IETF 111の発表で触れています。

f:id:ASnoKaze:20210922010718p:plain
(https://datatracker.ietf.org/meeting/111/materials/slides-111-pearg-private-relay-00)

以下の2つが上げられています

  • egress proxyを選択
  • Geohashを Client Hint で提供する

The Geohash HTTP Client Hint

大体の一を示すGeohash をヘッダでサーバに提出する方法「The Geohash HTTP Client Hint」の仕様が、Appleの方よりIETFに提出されています。(なお、この方法が、実際に使用されているかは定かではありません。)

Geohashは任意の精度で緯度経度を示す方法です。近い文字列は近い場所を示します。また、末尾から文字を削るほど精度が低くなります。
ja.wikipedia.org

HTTP Client Hintの仕組みに則り、Webサーバがサポートしている場合、クライアントが望めばSec-CH-GeohashヘッダでGeohashを提出します。

動作例
  • 1. まずクライアントはWebサーバにHTTPリクエストを送る
  • 2. サーバは、HTTPレスポンスヘッダのAccept-CHでSec-CH-Geohashをサポートしていることを伝える
  Accept-CH: Sec-CH-Geohash
  • 3. クライアントは、次のHTTPリクエストからSec-CH-Geohashでジオハッシュを送信する
Sec-CH-Geohash: "u4pruydqqvj"

u4pruydqqvjは、緯度経度(57.64911,10.40744)を示します。

RSAブラインド署名を用いたHTTP認証の提案仕様

The Privacy Token HTTP Authentication Scheme」という提案仕様が、AppleとCloudflareの方らによって提出されています。

これは、Proxy-Authorizationヘッダで指定できる新しいHTTP認証です。RSAブラインド署名を使います。クライアントを認証するサーバは、特定の鍵で署名されている事は分かるが、クライアントを識別できません。

RSAブラインド署名そのものについては、「RSA Blind Signatures」にて、署名や検証の方法が書かれている。

この仕様では、RSAブラインド署名データを含むPrivacy Tokenを規定する。しかし、クライアントがそれをどのように取得するかは規定されていない。

具体的なユースケースについては、今後出てくるものと思われる。

PrivacyToken 認証方式

このHTTP認証では下記のとおりである。Proxy-Authorizationヘッダで、認証方式としてPrivacyTokenを指定し、base64urlエンコードしたPrivacyTokenの中身が続く。

Proxy-Authorization: PrivacyToken token=abc...
PrivacyToken

PrivacyTokenは次のような構造を持ちます

struct {
    uint8_t version;
    uint8_t key_id[32];
    uint8_t message[32];
    uint8_t signature[Nk];
} Token;
  • version: この仕様では1です。
  • key_id: 署名を生成するのに使用した鍵のハッシュ値
  • message: 32オクテットのランダムな値。署名される
  • signature: messageへのRSAブラインド署名

クライアントはmessageに対してRSAブラインド署名をしてもらいます。署名者が何かしらの方法でクライアントを認証してたとしても、messageの中身を知ることは出来ないため、以後使用されるmessageの値をもってしてクライアントを識別することは出来ません。

(署名者と、PrivacyToken認証を行うサーバは同じ主体とは限りません)PrivacyToken認証を行うサーバは、署名者によって署名されている事は分かります。しかし、クライアントを特定することは出来ません。

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

Bootstrapping WebSockets with HTTP/3 の仕様

既存の仕様ではHTTP/3上でWebSocketは使うことができません。

そこで、HTTP/3でWebSocketを使えるようにする「Bootstrapping WebSockets with HTTP/3」という仕様が、GoogleのRyan Hamilton氏によって提案されています。

背景: HTTP/2とWebSocekt

もともと、HTTP/2でWebSocketを使うためにRFC 8441「Bootstrapping WebSockets with HTTP/2」という仕様があります。この仕様では、一つのストームをWebSocket通信として使うために、:protocol 疑似ヘッダやSETTINGSパラメータを導入しています。
asnokaze.hatenablog.com

Bootstrapping WebSockets with HTTP/3

この仕様自体は、RFC 8441「Bootstrapping WebSockets with HTTP/2」の仕組みを同様にHTTP/3に導入するものです。

この仕様は、RFC 8441で導入されたExtended CONNECTメソッドと、SETTINGSパラメータをHTTP/3に導入する単純な仕様になっています。

感想

WebSocket over HTTP/3では、単純にHTTP/3に乗せるだけでも、ストリームを超えたHoLBがなくなったり、コネクションマイグレーションに対応できるといったメリットがあるものと思います。

別の議論として、HTTP/3の利点を活かす、JavaScript APIの変更も含めたWebTransportという仕様が提案されています。このWebSocket over HTTP/3では、WebTransportが提供する単方向ストリームや再送を要求しないデータ通信(DATAGRAM)といった機能は使えません。一方で、既存のWebSocketのAPIを流用するため既存のアプリケーションでもそのまま動作するものと思います。

また、現在 WebTransportやMASQUEの文脈でHTTPセマンティクスにおける、CONNECT拡張について議論が行われている最中です。そこの部分整理があるかもしれません。

(あとは、Bootstrapping WebSockets with HTTP/2から単純にマップ出来ないところがありそうな気はしている。エラーコード周りとか。)

ホスト名の最後が数字なURLの扱いについて

WHATWG URL」の仕様で、ブラウザにおいて、ホスト名がIPv4でないが、数値で終わるURLは拒否されるように変更された。

github.com

例えば次のようなものです

  • foo.0
  • bar.0.09
  • 1.2.3.4.5

今まで、これらのホスト名は、その他のドメインと同じように、通常通り名前解決されます。Issueの起案者は、すでに具体的な攻撃があるわけではないとしつつも、紛らわしさや、eTLD+1 (same-site)の扱いの問題があるとのことです。

なお、次のようなものはIPv4アドレスにマッピングされアクセスできます。

Deprecate support for URLs with non-IPv4 hostnames ending in numbers

実際に、Chromeでは、そのような変更を入れる検討が始まっています。URL仕様の変更であり、http, https, ws, wss, fileなどで対象となるURLが拒否されます。拒否は、Google's URL parsing libraryのGURLで行われます。

Intent to Prototype: Deprecate support for URLs with non-IPv4 hostnames ending in numbers

なお、現状そのようなURLの名前解決が(0.0003%ほど)行われているようですが、多くのものが入力ミスなどと考察されています。hostsファイルを指定している可能性もありますが、詳細なデータはなさそうです。

動作確認

Chrome Canaryに変更が取り込まれたので動作確認する。
今までは名前解決が出来なかったというエラーだったが、URLパースエラーとなっていることがわかる。

f:id:ASnoKaze:20210827125848p:plain

URLバーに入力した場合は、URLとしてではなく、検索キーワードとして処理される模様

HTTP/3 DATAGRAMの優先度制御の提案仕様

HTTP/3 DATAGRAMの優先度制御方式を定義した「HTTP Datagram Prioritization」が提出されました。

これについて簡単に眺めていきます。

目次

背景: HTTP/3 DATAGRAMについて

下記の記事で書いた通り、HTTP/3の拡張仕様でパケロス時に再送を必要としないアプリケーションデータの送受信ができるようになっています。
asnokaze.hatenablog.com

特に、WebSocketの次世代版ともいわれるWebTransportや、HTTP/3コネクションをトンネルさせるMASQUEといった仕様で使われるものです。

このDATAGRAM拡張仕様では、優先度制御については具体的な方法を指定していません。

(なおDATAGRAMはHTTP/3のみに限定されず、HTTP/2でも使用されます)

補足: HTTP/3の優先度

HTTPでは、一つのコネクション上で複数のリクエストを並列的に送ります。そのときに、例えばWebページのレンダリングに必要なファイルの優先度をあげることで、結果としてWebページの表示を早くします。

通常のHTTPメッセージの送受信の優先度は、クライアントからサーバに対してレスポンスの優先度を通知します。

HTTPリクエストでpriorityヘッダで、u(urgency)で優先順位と、i(incremental)で並列処理出来るか示します。

   :method = GET
   :scheme = https
   :authority = example.net
   :path = /menu.png
   priority = u=5, i

また、通信中の優先度の変更はPRIORITY_UPDATEフレームを利用します。

この方法はHTTP/3以外でも利用できます。詳しくは以前書いた通り。
asnokaze.hatenablog.com

このHTTPの優先度制御では、DATAGRAM拡張の優先度制御については具体的な方法を指定していません。

DATAGRAM の優先度

本題です。「HTTP Datagram Prioritization」ではDATAGRAM通信の優先度制御方法を定義します。

HTTP/3のDATAGRAMは必ず関連付けられるHTTPリクエストがあります。そのリクエストで、通常のHTTPメッセージの優先度制御と同じように、DATAGRAMの優先度を制御します。意図的にシンプルな設計としているようです。

priorityヘッダでduを付けることで、DATAGRAMの優先度を指定できます。

   :method = GET
   :scheme = https
   :authority = example.net
   :path = /style.css
   priority = u=0, du=2

優先度の高いものから送信し、同じ優先度のものはラウンドロビンされます。

一つのHTTPリクエストに対して複数のDATAGRAMフローを指定できるのですが、各コンテキスト毎に優先度制御方式は指定しません。

また、優先度の更新は通常のHTTP優先度制御と同様、PRIORITY_UPDATEフレームで行います。

IETF 111の発表スライド

発表予定でしたが、時間が足りなかった模様。
内容はまとまってるので、おすすめ。
https://datatracker.ietf.org/meeting/111/materials/slides-111-masque-http-dgram-priorities-01

感想

WebTransportのServer initiatedなストリームとか、サーバ開始のDATAGRAMフレーム優先度制御とか、色々ユースケースに合わせて、柔軟性(複雑性)が上がっていきそうな気もする。

IETF 111で議論ができなかったため、MASQUE WGメーリングリストで引き続き議論。