通常のHTTPプロキシ経由でssl::stream<tcp::socket>を使う場合は、宛先へのTLSを要求する前に生のトランスポートを使います:

auto& transport = tlsStream.next_layer();
  1. そのトランスポートをプロキシのホストとポートに接続します。プロキシ資格情報を設定していない、許可された公開HTTPS宛先では、HTTPプロキシ一覧が候補のエンドポイントを提供します。候補が要求したトンネルを許可するか確認してください。
  2. 宛先のauthorityを指定してCONNECTを送信し、api.example:443のようにし、生のトランスポート上で応答ヘッダー全体を解析します。成功した2xxはトンネルを開きます。拒否はHTTPプロキシの応答のままです。
  3. 宛先のホスト名、必要なSNI、信頼ルート、ピア検証を設定し、tlsStreamでクライアントハンドシェイクを開始します。
  4. TLSが成功したら、アプリケーションにはSSLストリームの読み書きを使います。その時点で次の層を直接読むとTLS処理を迂回します。

HTTPパーサーの残りがあれば次の段階へ持ち越します。Asioにはバッファ付きハンドシェイクのオーバーロードがあり、パーサーが保持する末尾を捨てるとソケットから既に読んだバイトを失うことがあります。

この単純な型では、next_layerとlowest_layerのどちらもTCPに到達します。ラッパーが増えると両者は異なりうるため、プロキシの実際のワイヤプロトコルを運ぶインターフェースを選びます。HTTPSプロキシはTLS段をさらに一つ追加し、この平文CONNECTの手順の外にあります。

関連記事