もしあなたがプライバシーを重視するアプリケーションやサービスをインターネット上で運営している場合、ユーザーのプライバシーを確実に保護するための選択肢は限られています。ログやデータ収集を最小限にすることはできますが、それでもネットワークレベルでは、すべてのHTTPリクエストは_どこから_か来る必要があります。HTTPリクエストによって生成される情報、たとえばユーザーのIPアドレスやTLSフィンガープリントは、特にアプリケーションデータと組み合わせると機密となり得ます。
ユーザーのプライバシーを守るためには、クライアントのデバイスからアプリケーションのロジックを実行するサーバーへのHTTPリクエストの送信方法を変更する必要があります。Privacy Gatewayは、暗号化されたHTTPリクエストとレスポンスを、クライアントとアプリケーションサーバーの間で中継するサービスです。Privacy Gatewayを用いることで、Cloudflareはリクエストの送信元を把握することはできますが、その内容はわかりません。また、アプリケーションはリクエストの内容はわかりますが、その送信元はわかりません。**Cloudflareもアプリケーションサーバーも全貌を把握することはできず、**エンドユーザーのプライバシーを向上させます。
最近、女性の健康に関する業界を主導するアプリを提供するFlo Health Incは、匿名化モードを導入することを目的としてPrivacy Gatewayをデプロイしました。Privacy Gatewayをデプロイすることで、匿名化モードユーザーのリクエストデータは、アプリユーザーとFloの間で暗号化され、Floから利用者のIPアドレス、Cloudflareからリクエストデータの内容を見ることができなくなりました。
Privacy Gatewayを導入することで、他にもいくつかのプライバシーを重視したアプリケーションの展開が可能になります。
ブラウザの開発者は、プライバシーを尊重した方法でユーザーのテレメトリデータを遠隔で収集することができます。例えば、データから個人の識別情報(IPアドレス)となる可能性のある情報を削除しながら、どのような拡張機能がインストールされているか、ユーザーがどのようなデフォルトを変更したかなどのデータを収集できます。
ユーザーは、ヘルスケアサイトにアクセスして新型コロナへの暴露を報告する際に、自分のIPアドレスや位置を追跡される心配がありません。
DNSリゾルバーは、DNSクエリを、誰がリクエストしたのか、どのWebサイトを訪問しているのかを関連付けずに提供することができます。これは、Oblivious DNSで私たちが実装したパターンです。Privacy Gatewayは、新たなIETF標準であるOblivious HTTP(OHTTP)に基づいており、標準のハイブリッドパブリックキー暗号化で構築されています。
その仕組みは?
Oblivious HTTP標準の主な革新点は、基本的なプロキシサービスを超えて、これらのメッセージが_アプリケーションサーバーへの_送信の際に暗号化されるということです。Privacy Gatewayは、各メッセージの送信元と送信先以外のアプリケーションデータについて何も知ることができません。
Privacy Gatewayは、アプリケーションの開発者やプラットフォーム、特にプライバシーを強く要求する人々が、「Mixnet」で、ネットワーク上のメッセージの送信元と宛先を難読化するアプローチに酷似したものを構築できるようにします。そのために、Privacy Gatewayは3つの主要なコンポーネントから構成されています。
**クライアント:**ユーザーのデバイス、またはPrivacy Gatewayにリクエストを転送するように設定されているクライアント。
**Privacy Gateway:**Cloudflareが運営するサービス。クライアントとゲートウェイ間のリクエストを中継し、中のコンテンツを見ることができないように設計されています。
**アプリケーションサーバー:**オリジンまたはアプリケーションWebサーバーであり、クライアントからのリクエストを復号化し、レスポンスを暗号化して返す責任を負います。
リクエストデータを封筒(手紙)とIPアドレスの内容、リクエストメタデータを外部のアドレスと考えた場合、Privacy Gatewayを使用することで、Cloudflareは封筒のアドレスを確認し、内部を見ることなく安全に宛先に転送することができます。
Privacy Gatewayを利用したOblivious HTTPトランザクション
もう少し詳しく説明すると、データの流れは次のようになります。
クライアントは、HTTPリクエストをアプリケーションサーバーのパブリックキーでカプセル化し、HTTPS接続でPrivacy Gatewayに送信します。
Privacy Gatewayは、リクエストをサーバーに転送する際に、独自に構築したアプリケーションサーバーとの個別のHTTPS接続を使用します。
アプリケーションサーバーはリクエストをカプセル化し、レスポンスを生成できるターゲットサーバに転送します。
アプリケーションサーバーは、カプセル化されたレスポンスをPrivacy Gatewayに返し、その結果をクライアントに転送します。プロトコルで指定されているように、クライアントからサーバーへのリクエストは、パブリックキー暗号化の最新の標準であるHPKEを使用して暗号化されます。詳しくはこちらをご覧ください。OHTTPのHPKEの使用が安全であることを保証するために、私たちはさらに対策を講じ、プロトコルの正式な分析を実施しています。今後数週間のうちに、より深い分析結果を発表する予定です。
Privacy Gatewayがエンドユーザーのプライバシーを向上させる仕組み
このインタラクションは2種類のプライバシーを提供し、私たちは非公式に_リクエストプライバシー_および_クライアントプライバシー_と呼んでいます。
リクエストプライバシーとは、IPアドレス、ジオロケーション、TLSおよびHTTPSフィンガープリントなど、HTTPリクエストによって明らかになる情報を、アプリケーションサーバーが学習しないことを意味します。Privacy Gatewayは、アプリケーションサーバーとの間で別のHTTPS接続を使用しているため、アプリケーションサーバーに公開されるこのリクエストごとの情報は、すべてPrivacy Gatewayのものであり、クライアントのものではありません。ただし、開発者はリクエストの内容に個人を特定できる情報を送信しないように注意する必要があります。例えば、リクエストにユーザーのメールアドレス、電話番号、クレジットカード情報などが含まれている場合、Privacy Gatewayはプライバシーを有意に改善することはできません。
クライアントプライバシーは、より強い概念です。Cloudflareとアプリケーションサーバーは連携して個々のユーザーのデータを共有しているわけではないので、サーバーから見れば、個々のトランザクションはPrivacy Gatewayの背後にある未知のクライアントから来たものです。つまり、適切に設定されたPrivacy Gatewayの導入は、アプリケーションが2つのリクエストを同じクライアントにリンクさせることができないことを意味します。特に、Privacy Gatewayを用いることで、企業はプライバシーを愛することになるでしょう。Privacy Gatewayを利用するエンドユーザーが1人しかいない場合、リクエストプライバシーのみが提供されます(ゲートウェイからは、クライアントIPアドレスが見えないため)。サーバーは、各リクエストが同じ単一のクライアントに対応していることを知ることになるので、クライアントプライバシーは提供されません。クライアントプライバシーは、システムのユーザーが多数いることが前提なので、アプリケーションサーバーがこの決定を行うことはできません。
リクエストとクライアントのプライバシーをよりよく理解するために、クライアントとサーバー間の次のようなHTTPリクエストを考えてみましょう。
サイズ1のクライアント匿名化セットを使用した通常のHTTP設定
クライアントがサーバー(OHTTP用語では「ゲートウェイ」といいます)に直接接続する場合、サーバーはクライアントに関する情報(IPアドレス、使用されたTLS暗号、そのIPアドレスに基づくある程度の位置情報など)を把握できます。
ここには、エンドユーザーならではの機密情報がたくさん詰まっているかもしれません。つまり、この接続は、リクエストプライバシーもクライアントプライバシーも提供しません。
- ipAddress: 192.0.2.33 # the client’s real IP address
- ASN: 7922
- AS Organization: Comcast Cable
- tlsCipher: AEAD-CHACHA20-POLY1305-SHA256 # potentially unique
- tlsVersion: TLSv1.3
- Country: US
- Region: California
- City: Campbell
Privacy Gatewayでは、クライアントがアプリケーションサーバー自体に直接接続することはありません。その代わり、Privacy Gatewayに接続し、そのゲートウェイがサーバーに接続します。つまり、サーバーはPrivacy Gatewayからの接続のみを観察し、クライアントからの個別の接続は観察しないため、異なる見解が得られます。
サイズkのクライアント匿名化セットによるPrivacy Gatewayの構成
- ipAddress: 104.16.5.5 # a Cloudflare IP
- ASN: 13335
- AS Organization: Cloudflare
- tlsCipher: ECDHE-ECDSA-AES128-GCM-SHA256 # shared across several clients
- tlsVersion: TLSv1.3
- Country: US
- Region: California
- City: Los Angeles
これはリクエストプライバシーです。クライアントの位置と識別情報に関するすべての情報は、アプリケーションサーバーから隠されています。また、Privacy Gatewayでは、アプリケーションデータに関する詳細な情報はすべて隠されています。機密性の高いアプリケーションやDNSのようなプロトコルの場合、このメタデータをアプリケーションデータから分離しておくことは、エンドユーザーのプライバシーを向上させる重要なステップとなります。
さらに、アプリケーションは、個々のリクエストにおいて、クライアントごとの機密情報を明らかにしないように注意する必要があります。Privacy Gatewayは、平文のアプリケーションデータを観察することができないため、アプリケーションがリクエストボディにメールアドレス、氏名などの識別情報を送信しないことを保証することはできません。リクエストの中でユーザーを特定する情報を公開するアプリケーションは、リクエストのプライバシーを侵害する可能性がありますが、リクエストプライバシーを侵害することはありません。このため、当社の完全なアプリケーションレベルのプライバシープロキシ製品とは異なり、Privacy Gatewayは任意のアプリケーションやトラフィックに対する汎用プロキシベースプロトコルとして使用することを目的として_いません_。DNS(Oblivious DNS-over-HTTPSで裏付けられているように)、テレメトリデータ、または前述の汎用API呼び出しなど、機密性の高いアプリケーションのための特別な目的を持ったプロトコルとなることを意図しています。
Privacy Gatewayをアプリケーションに組み込む
Privacy Gatewayとの連携には、OHTTPプロトコルのクライアント側とサーバー側をアプリケーションで実装する必要があります。その内容を順を追って説明しましょう。
サーバーインテグレーション
プロトコルのサーバー側では、2つの基本的なタスクを担当します。
リクエストのカプセル化のためのパブリックキーを発行する
カプセル化されたクライアントリクエストを復号化し、結果のリクエストを処理し、対応するレスポンスを暗号化する
カプセル化パブリックキーは、「鍵構成」と呼ばれ、鍵識別子(サーバーがローテーションのために一度に複数の鍵をサポートできるように)、暗号化および復号化のための暗号アルゴリズム識別子、パブリックキーからなります。
クライアントはパブリックキーがリクエストの作成のために必要で、その方法はたくさんあります。サーバーがパブリックキーを修正し、それを自分のアプリケーションに焼き付けることもできますが、その場合、キーをローテーションさせるためのソフトウェアのアップデートが必要になります。あるいは、クライアントが他の方法でパブリックキーを取得することも可能です。詳細については、この文書を参照してください。まず、シンプルな方法として、APIを使用してサーバーから直接パブリックキーを取得することができます。以下は、私たちのオープンソースのOHTTPサーバーが提供するAPIのスニペットです。
HPKE Symmetric Algorithms {
HPKE KDF ID (16),
HPKE AEAD ID (16),
}
OHTTP Key Config {
Key Identifier (8),
HPKE KEM ID (16),
HPKE Public Key (Npk * 8),
HPKE Symmetric Algorithms Length (16),
HPKE Symmetric Algorithms (32..262140),
}
パブリックキーの生成と配布が解決されると、次にサーバーはクライアントからのカプセル化されたリクエストを処理する必要があります。各リクエストに対して、サーバーはリクエストを復号化し、平文を解決可能な対応するHTTPリクエストに変換し、その結果のレスポンスを暗号化してクライアントに返す必要があります。
func (s *GatewayResource) configHandler(w http.ResponseWriter, r *http.Request) {
config, err := s.Gateway.Config(s.keyID)
if err != nil {
http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError)
return
}
w.Write(config.Marshal())
}
オープンソースのOHTTPライブラリは通常、リクエストの復号化およびレスポンスの暗号化の関数を提供し、バイナリHTTPからの平文変換は、HTTPリクエストと別に処理されます。例えば、オープンソースのサーバーでは、Go HTTPリクエストがメモリ上でどのように表現されるかに応じて、この変換を別のライブラリに委ねます。特に、平文リクエストからGo HTTPリクエストに変換する関数は、次のシグネチャを持つ関数で行われます。
逆に、Go HTTPレスポンスを平文のバイナリHTTPレスポンスメッセージに変換するには、以下のシグネチャを持つ関数を使用します。
func UnmarshalBinaryRequest(data []byte) (*http.Request, error) {
...
}
OHTTPサーバーを実装するために使用できるオープンソースライブラリはいくつかありますが、私たちはそのすべてをオープンソースサーバー実装としてパッケージ化しました。こちらから入手できます。このパッケージには、ビルド、テスト、デプロイの手順が記載されているので、簡単に始めることができます。
type BinaryResponse http.Response
func (r *BinaryResponse) Marshal() ([]byte, error) {
...
}
クライアント統合
当然ながら、OHTTPのクライアント側の動作は、サーバーの動作を反映したものです。特に、クライアントは以下を行う必要があります。
サーバーパブリックキーの発見または取得
HTTPリクエストをエンコード・暗号化してPrivacy Gatewayに送信し、HTTPレスポンスを復号化・デコードします。
サーバーのパブリックキーの発見は、サーバーが選択したデプロイメントモデルに依存します。例えば、パブリックキーがAPIで利用できる場合、クライアントはそれを直接取得することができます。
エンコード、暗号化、復号化、およびデコードは、利用できる場合はOHTTPライブラリで処理するのが最適です。これらの関数が利用できれば、クライアントサポートの構築はかなり簡単です。上記でリンクしたライブラリ関数を使用したGo クライアントの簡単な例を以下に示します。
$ curl https://server.example/ohttp-configs > config.bin
このようなスタンドアロン型のクライアントは、既存のアプリケーションをお持ちの方にとってはあまり便利ではないかもしれません。そこで、既存のアプリケーションとの統合を支援するために、iOSやmacOSアプリと互換性のあるOHTTPのサンプルライブラリを作成しました。また、クライアント側、サーバー側、またはその両方において、統合を容易にするための言語やプラットフォームのサポートが必要な場合は、当社までご連絡ください。
configEnc := ... // encoded public key
config, err := ohttp.UnmarshalPublicConfig(configEnc)
if err != nil {
return err
}
request, err := http.NewRequest(http.MethodGet, "https://test.example/index.html", nil)
if err != nil {
return err
}
binaryRequest := ohttp.BinaryRequest(*request)
encodedRequest, err := binaryRequest.Marshal()
if err != nil {
return err
}
ohttpClient := ohttp.NewDefaultClient(config)
encapsulatedReq, reqContext, err := ohttpClient.EncapsulateRequest(encodedRequest)
relayRequest, err := http.NewRequest(http.MethodPost, "https://relay.example", bytes.NewReader(encapsulatedReq.Marshal()))
if err != nil {
return err
}
relayRequest.Header.Set("Content-Type", "message/ohttp-req")
client := http.Client{}
relayResponse, err := client.Do(relayRequest)
if err != nil {
return err
}
bodyBytes, err := ioutil.ReadAll(relayResponse.Body)
if err != nil {
return err
}
encapsulatedResp, err := ohttp.UnmarshalEncapsulatedResponse(bodyBytes)
if err != nil {
return err
}
receivedResp, err := reqContext.DecapsulateResponse(encapsulatedResp)
if err != nil {
return err
}
response, err := ohttp.UnmarshalBinaryResponse(receivedResp)
if err != nil {
return err
}
fmt.Println(response)
ご関心がおありですか?
Privacy Gatewayは現在、早期アクセス期間中で、プライバシーを重視する企業やパートナーに限定して提供されています。ご興味のあるお客様は、お問い合わせください。