HTTP・HTTPSプロキシ

HTTP・HTTPSプロキシ

HTTPプロキシは、ブラウザーやアプリのウェブリクエストを受け、代わりに接続先へ接続します。通常のHTTP通信に加え、CONNECTメソッドに対応すれば暗号化されたHTTPS通信も運べます。HTTPSプロキシは、アプリとプロキシ自体の間の接続も暗号化します。

アプリがプロキシにどう接続するかと、その先のサイトにどう通信するかは、別々の選択です。両方を理解すると適切な接続設定を選べます。プロトコル全般の比較はSOCKSとHTTPプロキシで説明しています。

HTTPプロキシがウェブリクエストを扱う方法

監視スクリプトがhttp://example.com/catalogを要求するとします。サイトへ直接接続せず、設定したプロキシに接続します。HTTP/1.1では完全な接続先URLを送るため、プロキシはどのサーバーとページにアクセスするか分かります。要求を転送し、サイトの応答をスクリプトへ返します。

この方式では、プロキシがHTTPメッセージを処理します。GETやPOSTなどのメソッド、要求アドレス、ヘッダー、送信データを読めます。対応する設定があれば、アクセス規則、リクエスト記録、対象応答のキャッシュを使えます。キャッシュは応答のキャッシュ規則に従う任意機能で、HTTPプロキシを購入しても全ページが保存されるわけではありません。

サイトはプロキシの出口IPから接続を受け取ります。HTTPという用語はIPの由来や割り当て期間を示しません。同じプロトコルを、データセンター、ISP、住宅用、モバイルのアドレスと、固定IPやローテーションプールの組み合わせで提供できます。

左では、アプリとHTTPプロキシ間のCONNECTをネットワーク上で読めます。右では、同じ要求がHTTPSプロキシへのTLS内に隠れます。サイトのHTTPSコンテンツは、どちらも暗号化されています。

HTTPプロキシでHTTPSサイトを開く方法

HTTPSサイトは、アプリとサイト間のやり取りをTLSで守ります。HTTPプロキシは、それを運ぶためにまずトンネルを作ります。https://example.com/catalogの要求は、次の順序です。

4段階:プロキシへのCONNECT、接続先接続とトンネルの確認、TLS証明書の検証、暗号化通信です。
  1. アプリがプロキシに接続し、example.com:443へのトンネルをCONNECTメソッドで要求します。指定するのはホストとポートで、ページのパスは含みません。
  2. プロキシは、必要な認証も含め、アクセスと接続先が許可されているか確認します。接続先への接続を開き、トンネルの準備完了を知らせます。
  3. アプリはトンネルを通してサイトとTLSハンドシェイクを行い、サイトの証明書を検証します。
  4. アプリはTLS接続内でウェブリクエストを送ります。プロキシは暗号化されたバイト列を双方向に中継します。

ページを届けるために、プロキシが読む必要はありません。サイトのTLS接続の両端はアプリとサイトのままです。CONNECTがトンネルを、TLSが暗号化と、検出されない改変からの保護を提供します。

このため、プロキシアドレスがhttp://で始まってもHTTPSサイトを開けます。サイトのHTTPS保護はトンネル内で動き、アプリとプロキシ間のTLSには依存しません。

HTTPSプロキシが追加するもの

HTTPSプロキシでは、まずアプリがプロキシとTLSを確立し、その証明書を検証します。その保護された接続内で、HTTP要求やトンネル用のCONNECTを送ります。アプリとプロキシの間の観測者は、それらを読めません。

HTTPS接続先では、アプリは2本の独立したTLS接続を維持します。1本はプロキシと、もう1本はトンネルを介してサイトとつながります。プロキシは自分宛ての外側の保護を外しますが、中のサイトデータは暗号化されたままです。それを復号できるサイトへ転送します。HTTP接続先では内側のTLSがなく、プロキシまでの接続だけが保護されます。

プロキシへの接続接続先暗号化されるもの
HTTPHTTPサイトどちらの接続もTLSを使わず、経路上で要求と応答を読めます。
HTTPHTTPSサイトサイトの通信はトンネル内で暗号化されます。プロキシへの接続では、CONNECTとプロキシ認証にTLS保護はありません。
HTTPSHTTPサイトTLSがプロキシまでを守ります。プロキシは要求を読め、TLSなしでHTTPサイトへ転送します。
HTTPSHTTPSサイトTLSがプロキシ宛ての要求を守り、別のTLSがトンネル内のサイト通信を守ります。

これは証明書検証を有効にし、HTTPS検査や別のVPNを使わない通常の転送の比較です。プロキシへの接続を暗号化しても、HTTPサイトがHTTPSに変わるわけではありません。

プロキシとサイトに見えるもの

HTTPS接続先では、転送プロキシはTLS内のページパス、クエリ、Cookie、フォームデータ、応答内容を読めません。ただし、接続したクライアントIP、CONNECTで要求されたホストとポート、通信時刻と量は分かります。プロキシへのTLSは、区間内の観測者からCONNECTを隠しますが、要求を実行するプロキシ自体からは隠しません。

プロキシ認証情報は、サイトのログインと別に送ります。Basic認証はユーザー名とパスワードをBase64で符号化しますが、秘密鍵なしで復元できます。通常のHTTPプロキシ接続では観測者から守れません。サイトのHTTPSはトンネル内で始まり、先に行ったプロキシログインは対象外です。プロキシへのTLSが、そのログインを転送中に保護します。

反対側では、サイトが出口IPから通信を受け、自分宛ての要求を読みます。アカウント、セッションCookie、アプリが送った情報を識別できます。HTTPSプロキシを選んでも、これらが消えたり、出口IPが自動的に受け入れられやすくなったりはしません。

HTTPS検査は、一部の管理ネットワークやデバッグツールで使う別の構成です。アプリが検査プロキシの管理する認証局を信頼すると、両側に別々のTLS接続を維持して内容を読めます。通常のCONNECT転送でその証明書の導入は不要です。HTTPSプロキシ自体の証明書を信頼することと、サイトのなりすましを許可することは別です。

アプリがCookie付きGET要求を作ります。プロキシは暗号化内容を読まずに中継し、CONNECTからホストとポートを知ります。サイトは復号し、パスとCookieを読みます。傍受のない通常のHTTPS転送です。

接続設定の読み方

プロキシ設定には、アドレス、ポート、接続プロトコル、必要な認証が要ります。プロキシURLのプロトコルはプロキシ、接続先URLのプロトコルはサイトに適用されます。

以下のcurlコマンドは、異なる2種類のプロキシ接続から同じHTTPSサイトを要求します。ホスト名とポートは、選んだ方式用に提供された値に置き換えてください。

curl --proxy http://proxy.example:8080 https://example.com/
curl --proxy https://proxy.example:8443 https://example.com/

最初はHTTPでプロキシに接続し、その後CONNECTとサイトへのTLSを作ります。2番目は先にHTTPSプロキシへのTLSを作り、内部に独立したサイトTLSを通します。どちらも、サービスが要求する認証を別途指定します。

http://をhttps://に変えるだけでは、HTTP専用ポートはTLS接続先になりません。HTTPS用ホスト名があるなら、その名前を使います。IPに置き換えると証明書の名前不一致を起こす場合があります。

アプリの表示も注意して読みます。「HTTPSプロキシ」という欄は、HTTPSサイト用のプロキシを選ぶだけで、プロキシには通常のHTTPでつなぐ場合があります。curlのHTTPS_PROXYもHTTPS接続先用を選ぶため、値がhttp://で始まっても正しい設定です。表示名は対象の要求を、URLのスキームは接続方法を示します。

DNSとプロキシ経由の通信

HTTPクライアントが接続先ホスト名を渡すと、通常はプロキシがIPを調べて接続します。プロキシ自体の名前が必要なら、クライアントが別途照会します。ブラウザーが予測などの機能でDNSを使う場合もあります。これらは別の照会で、ウェブプロキシを設定しても全DNS要求が通るわけではありません。

設定の対象は、アプリが実際にプロキシへ送る通信です。別プログラムは直結を続け、例外リストで特定サイトを迂回する場合もあります。たとえばAPIスクリプトをプロキシ経由にしても、無関係なブラウザーの経路は変わりません。実際にタスクを動かすアプリと構成から出口を確認します。

クライアントはプロキシのホスト名を解決し、プロキシは渡されたサイト名を解決します。ほかのアプリや迂回規則は直接経路を使えます。

サイトへのHTTP/2とプロキシへのHTTP/2

HTTP/2は別々のストリームで複数のやり取りを1接続にまとめます。プロキシでは、どの接続が対応するかが重要です。アプリはサイトとHTTP/2を交渉でき、それはHTTP/1.1 CONNECTで作ったトンネル内でも可能です。プロキシは暗号化バイト列を中継するため、サイトのHTTP/2を理解する必要はありません。

アプリとプロキシ間のHTTP/2は別機能です。各CONNECTトンネルが独自のHTTP/2ストリームを使い、複数トンネルで1接続を共有できます。たとえば別々の2サイトへのトンネルが、その接続を共有しつつ、接続先接続とサイトTLSセッションを分離できます。クライアントからの追加接続を減らしますが、暗号化要求をプロキシが読めるようにはしません。

選んだ方式に両端が対応する必要があります。HTTPSだけでHTTP/2とは決まらず、HTTPSプロキシもHTTP/1.1を使えます。性能はクライアント、経路、サーバー負荷、接続再利用にも左右されます。HTTP/2は全タスクの高速化保証ではありません。

左では、HTTP/1.1で作るTLSトンネル内でサイトのHTTP/2を使います。右では、プロキシへの1本のHTTP/2接続のストリームで2本のCONNECTトンネルを運びます。

通常のCONNECTは、両端が許可すれば別のTCP系プロトコルも運べますが、接続先ポートが制限される場合があります。UDPは中継しません。HTTP/3はUDP上のQUICなので、同じTCPトンネルを同様には通れません。HTTPのUDP転送はCONNECT-UDPなどの追加方式と互換実装が必要です。HTTPSやHTTP/2だけの対応では、それらの対応は分かりません。

HTTP・HTTPSアクセスが役立つ用途

閲覧やサイトテストでは、CONNECT対応HTTPプロキシが、HTTP・HTTPS双方の接続方法を提供します。チームはプロキシのネットワークからサイトを見つつ、ページ描画、Cookie、ログインはブラウザーに任せられます。

クローラー、APIクライアント、定期監視では、HTTPクライアントがURLを変えずに指定出口IPから要求できます。要求の準備と応答処理はアプリの役割です。HTTPSトンネル内では、プロキシは各ページやAPI呼び出しを解析せずに運べます。

ログインと接続先要求を含め、プロキシまでの接続も守る必要があるとき、TLSで保護するHTTPSプロキシが有用です。管理できないネットワークを通る場合に重要です。クライアントはプロキシ自体へのTLSに対応する必要があり、HTTPSサイトを開けるだけでは不十分です。

接続エラーの読み方

プロキシへの到達、トンネル作成、サイト通信のどこでも失敗します。エラーコードだけでなく、段階が重要です。

現象確認する場所
プロキシが407を返すプロキシが認証を要求しています。認証情報とアクセス方式を確認します。サイトアカウントは別のログインです。
HTTPは動くがHTTPSは動かないHTTPSに予定のプロキシを使っているか、CONNECTと接続先ポートが許可されるかを確認します。
TLSまたは証明書のエラーが出るプロキシ接続とサイト接続のどちらのエラーかを特定します。証明書検証を無効にせず、対象ホスト名、TLS接続先、証明書の信頼を確認します。
403が返るCONNECTの拒否はプロキシからです。正常に確立・検証したHTTPS接続内の403は、サイトの応答です。段階が異なり、対処も異なります。

トンネルとTLSハンドシェイクの成功は、経路の動作を示します。しかし、特定アカウント、出口IP、要求の受け入れは保証しません。プロキシが動いていても、ログイン確認、CAPTCHA、頻度制限は、サイトやアプリ側で対応が必要な場合があります。

ナレッジベースに戻る