RFC 9458 Oblivious HTTP の仕組みについて

『Oblivious HTTP』はユーザのプライバシを向上するための技術であり、各ブラウザベンダーおよびCDNベンダーが実装を行っています。

取り組みについては、幾つかの記事があがっています

今回は仕様の観点で、プロトコルの中身に触れていく

背景と目的

通信観点のプライバシーについては、通信の暗号化によりほとんどが保護されています。しかし、幾つか懸念が残っています。

  • IPアドレスは、短期的に同一ユーザを識別するのに使用できる
  • コネクションは、一連の通信が同一ユーザであることを識別するのに使用できます(HTTP/2以降複数のHTTPリクエストにコネクションを再利用する)

例えばあるサービスで、ログアウトして別アカウントとして再ログインすると、サービス側には同じ人物であることが分かってしまいます。
このようなユーザを識別する情報をさらに隠すのが『Oblivious HTTP』の目的です。

(アプリケーションレイヤなど、通信以外のトラッキング手法についてはもちろん守備範囲に入っていません。)

概要

Oblivious HTTPの全体概要は次のとおりです

登場人物
  • Client: Oblivious HTTPの通信の開始者。Target Resourceにアクセスを行いたい者。
  • Relay Resource: Oblivious HTTPの中継者。ClientのIPアドレスは分かるが、HTTPリクエストの中身は分からない。
  • Gateway Resource: Oblivious HTTPの終端者、実際のHTTPリクエストの中身を取り出すことが出来る。ClientのIPアドレスは分からない。
  • Target Resource: Gateway Resourceから実際のHTTPリクエストを受け取り、処理をして、HTTPレスポンスを返す。

ここで、Relay ResourceとGateway Resourceは独立した別の組織によって運営されていることを前提としています。それにより、Oblivious HTTPの仕組みでユーザのプライバシーが保護されます。Relay Resourceは、先述の通りCDNベンダーなどが担っている例があります。

通信の流れ
  • Clientは、あるTarget Resource宛のHTTPリクエストを暗号化するために、別経路で事前にGateway Resourceの鍵情報を取得しておきます (RFC 9458では入手方法は定義されていないが、DNS HTTPSレコードをいる手法が別RFCになっている RFC 9540)
  • Clientは、Target Resource宛のHTTPリクエストをまずバイナリ表現にエンコードします。その方法は『RFC 9292 Binary Representation of HTTP Messages』で定義されています。その後、そのデータを暗号化して、Relay ResourceにPOSTします。
POST /request.example.net/proxy HTTP/1.1
Host: proxy.example.org
Content-Type: message/ohttp-req
Content-Length: 78

<content is the Encapsulated Request above>
  • Relay Resourceは、POSTのデータをそのままGateway ResourceにPOSTする。(Relay Resourceは転送するGateway Resourceが設定されている)
POST /oblivious/request HTTP/1.1
Host: example.com
Content-Type: message/ohttp-req
Content-Length: 78

<content is the Encapsulated Request above>
  • Gateway ResourceはClientからPOSTされたデータを復号し、バイナリ表現からデコードして通常のHTTPリクエストに戻します。それをTarget Resourceに転送します。
  • Target Resourceは、HTTPリクエストを受け取り、処理をして、HTTPレスポンスを返す。

(以下逆向きに処理をしてレスポンスがClientに返る。なおContent-Typeは『message/ohttp-res』になる)

その他のトピック

幾つか仕様内にかかれているトピックを紹介する

パフォーマンス

Oblivious HTTPでは暗号化及び遅延のオーバヘッドがあります。Relay Resourceをクライアントとサーバの間、特にサーバの近くに配置することでオーバヘッドを抑えられると述べている。

リプレイ攻撃対策

Relay ResourceはHTTPリクエストの中身は見えないものの、Gateway Resourceに対してリプレイ攻撃を行うことが出来ます。
カプセル化されたHTTPリクエストの暗号化にしようされたnonceを用いることで、リクエストを一意に識別する方法はあります。

また、カプセル化されたHTTPリクエストにDateヘッダフィールドを追加することが推奨されています。これにより時間を開けて再送信されたものを検知できるようになります。

Relay Resourceの転送先について

Relay Resourceが転送先のGateway Resourceをどう選択するかは、RFC中には書かれていません。
『Oblivious Relay リソースと Oblivious Gateway リソース間の固定の 1 対 1 マッピングを前提としています』とも書かれています。

クライアントやOblivious Relayは事前知識として送信先のURLを分かっている前提になっているのかなと思いました。

また、Oblivious Relayで複数のOblivious Gatewayへの転送をサポートするために、RFC 6570 URI Templateを使うように書かれていますが具体的な使用方法は書かれてなさそうです。

暗号化まわり

カプセル化されたHTTPリクエストの暗号化にはHPKEが使用されます。詳しくはRFCを参照のこと

Key Configuration

HPKE Symmetric Algorithms {
  HPKE KDF ID (16),
  HPKE AEAD ID (16),
}

Key Config {
  Key Identifier (8),
  HPKE KEM ID (16),
  HPKE Public Key (Npk * 8),
  HPKE Symmetric Algorithms Length (16) = 4..65532,
  HPKE Symmetric Algorithms (32) ...,
}

暗号化

hdr = concat(encode(1, key_id),
             encode(2, kem_id),
             encode(2, kdf_id),
             encode(2, aead_id))
info = concat(encode_str("message/bhttp request"),
              encode(1, 0),
              hdr)
enc, sctxt = SetupBaseS(pkR, info)
ct = sctxt.Seal("", request)
enc_request = concat(hdr, enc, ct)

HTTPSレコードの使用

DNS HTTPSレコードを介しOblivious HTTPサポートを示し、Key Config配布する方法については『
RFC 9523: A Secure Selection and Filtering Mechanism for the Network Time Protocol with Khronos』というRFCで記述されています。(このRFCでもRelay Resourceの検出及び設定はスコープ外)

HTTPSレコードの例

svc.example.com. 7200  IN HTTPS 1 . ( alpn=h2 ohttp )

また、Target Resourceは/.well-known/ohttp-gateway からKey Configを提供します