HTTPの拡張CONNECTメソッド について復習する

HTTPにはCONNECTメソッドというものがあります、このメソッドを使ってProxyと接続しHTTPメッセージを中継してもらいます。

拡張CONNECTメソッドは、HTTPメッセージ以外のデータを中継してもらうのに使用します。特にHTTP/2やHTTP/3では特定のストリームを、データのトンネル用にするために、拡張CONNECTメソッドを使います。

例えば、WebTransport over HTTP/3なども拡張CONNECTメソッドを利用します。そのため、拡張CONNECTメソッドをサポートしてない単純なHTTP/3 ProxyとはWebTransport通信は行ったりは出来ません(Datagramらへんも絡む)。

今回は、その拡張CONNECTメソッド (Extended CONNECT Method) について見ていきます。

f:id:ASnoKaze:20220119010815p:plain

利用例

拡張CONNECTメソッドはもともと、WebSocket over HTTP/2の仕様で導入されました。

(HTTP/2でHTTPメッセージはストリームで管理するので、コネクションを切り替えるUpgradeは使えません。そこで拡張CONNECTを使うことになってます。標準化当時の議論 URL

その後、その他のプロトコルでも利用されるようになりました。例えば次のようなプロトコルです。

上記のように、HTTPリクエストを使ってサーバと通信したあとに、そのコネクション上でHTTPメッセージ以外のアプリケーションデータをやりとりできるようになります。もちろん、どのようなアプリケーションデータをやりとりするかはプロトコル次第ですが、HTTPレイヤではそのアプリケーションデータには関与しません (一般に、DATAフレームに格納され送信されます)。

UDP Proxying Support for HTTPは、Apple Private Relayでも利用されている技術であり、詳しくは以前の記事を参照ください
asnokaze.hatenablog.com

拡張CONNECTメソッド

拡張CONNECTメソッドはどのようなメッセージなのか具体例を以下に示します。これは、WebTransport over HTTP/3の接続リクエストの例です。

:method = CONNECT
:protocol = webtransport
:scheme = https
:path = /
:authority = server.example.com
origin: server.example.com

上記のように :protocol という疑似ヘッダを持つCONNECTメソッドが拡張CONNECTメソッドです。このリクエストに対して200番を返すことで該当のストリームは、:protocol疑似ヘッダで指定されたプロトコル用にデータをトンネルするようになります。ですので、レスポンスを返してもストリームはクローズしません。

先に上げたプロトコルでは、疑似ヘッダの値はこれらになります。

  • websocket
  • webtransport
  • connect-udp
  • connect-ip
疑似ヘッダ(pseudo-header)

疑似ヘッダについてはここで簡単に補足します。

HTTP/2やHTTP/3では、メソッド名やリクエストしたURLのスキームやパスは疑似ヘッダとして表現されます(これによりヘッダ圧縮が可能になります)。

疑似ヘッダはHTTP/2やHTTP/3の仕様で定義されていないものを送ってはなりません、受信した側はエラーとして扱う必要があります。ただし拡張CONNECTメソッドは拡張仕様であり、相手がこの拡張仕様に対応していれば :protocol疑似ヘッダを送信することが出来ます。

相手が :protocol 疑似ヘッダに対応しているかは、一般にSETTINGSパラメータで確認します。

SETTINGSパラメータ

HTTP/2やHTTP/3ではコネクションが確立したあとに、クライアントとサーバでSETTINGSパラメータを送り合い、通信に関するパラメータを交換します。その流れで、拡張CONNECTメソッドに対応しているかを確認します。

  • SETTINGS_ENABLE_CONNECT_PROTOCOL パラメータをセットして送ることで、相手に対応していることを通知します
  • もしくはWebTranportプロトコルの場合は、SETTINGS_ENABLE_WEBTRANSPORTパラメータを送ることで拡張CONNECTメソッドに対応していることを相手に通知します
その後

拡張CONNECTメソッドを用いてストリームをトンネル化したあと、どのようなデータをやりとりするかは、:protocol 疑似ヘッダで示されるプロトコルの仕様によります。