5 分で読了 #networking #代理契約
このページの目次

順方向プロキシ

クライアント側のプロキシ——HTTP CONNECT は HTTPS に対して目標までの TCP トンネルを確立し、SOCKS5 は任意の TCP および UDP トラフィックの転送をサポートします。PAC は「どのトラフィックがプロキシを通るか」という判断を、全か無かのスイッチではなく、プログラム可能なロジックに変えます。

概要

順方向プロキシはクライアント側のプロキシです。クライアントはプロキシサーバーのアドレスを設定し、すべての送信トラフィックはプロキシを経由します。HTTP CONNECT メソッドは、プロキシがエンドツーエンドの TCP トンネル(HTTPS 用)を確立することを可能にし、SOCKS5 はより低レベルで、任意の TCP トラフィックと UDP 転送をサポートします。PAC は動的な URL ごとのプロキシ判断を提供します。順方向プロキシは逆方向プロキシと対称的です:前者はクライアント側、後者はサーバー側です。

HTTP CONNECT: TCP トンネル

ブラウザが HTTP プロキシを設定している場合、HTTPS リクエストは直接ターゲットサーバーに送信されません。代わりに、CONNECT メソッドを使用してエンドツーエンドの TCP トンネルを確立します。

Client → Proxy:
  CONNECT example.com:443 HTTP/1.1
  Host: example.com:443
  Proxy-Authorization: Basic <base64(user:pass)>

Proxy → example.com:443: TCP 3ウェイハンドシェイク
Proxy → Client:
  HTTP/1.1 200 Connection Established   ← トンネル確立済み

その後: クライアントとサーバー間の TLS ハンドシェイクはトンネル上で行われます:
  Client ↔ Proxy ↔ Server (TCP レベルで転送、内容は解析しない)
  → プロキシは HTTP body を見えない (TLS で暗号化されているため)
  → ただし、プロキシは CONNECT のターゲットを見る (TLS ClientHello 内の SNI もプレーンテキスト)

CONNECT と通常の GET の違い:

GET http://example.com/index.htmlCONNECT example.com:443
プロキシの役割HTTP プロキシ: HTTP を解析し、リクエストを再構築TCP トンネル: バイトストリームの転送
TLS不要 (ターゲットは HTTP を使用)クライアント ↔ サーバー エンドツーエンド
プロキシが見る内容はいいいえ (暗号化)

SOCKS5

SOCKS5 は HTTP とは独立したプロキシプロトコルで、TCP レベルで動作します。ルール: 3回のハンドシェイク (メソッドネゴシエーション、リクエスト、レスポンス) → 純粋な TCP 転送。

1. メソッドネゴシエーション (認証):
   Client → Server:
     VER=5, NMETHODS=1, METHODS=0x00  (0x00=認証なし, 0x02=ユーザー/パスワード)
   Server → Client:
     VER=5, METHOD=0x00

2. リクエスト:
   Client → Server:
     VER=5, CMD, RSV=0x00, ATYP, DST.ADDR, DST.PORT
     
     CMD: 0x01=CONNECT(TCP), 0x02=BIND(逆接続, FTP アクティブモード), 0x03=UDP ASSOCIATE
     ATYP: 0x01=IPv4(4バイト), 0x03=ドメイン名(1バイトの長さ + 名前), 0x04=IPv6(16バイト)
     DST.PORT: 2バイト (ネットワークバイトオーダー)

   Server → Client:
     VER=5, REP, RSV=0x00, ATYP, BND.ADDR, BND.PORT

     REP: 0x00=成功, 0x01=一般的な SOCKS サーバー障害,
          0x02=接続が許可されない, 0x03=ネットワーク到達不能,
          0x04=ホスト到達不能, 0x05=接続拒否,
          0x06=TTL 期限切れ, 0x07=コマンド未サポート,
          0x08=アドレスタイプ未サポート

3. データリレー: 双方向 TCP 転送 (サーバーは Client↔Target の間でバイトを透過的に転送)

DNS 解決

SOCKS5 クライアントは IP ではなくドメイン名 (ATYP=0x03) を送信します → SOCKS5 サーバーが DNS 解決を担当します。

意味: クライアント本体の DNS が汚染されている場合、SOCKS5 サーバーは独自の DNS (例: 8.8.8.8) を使用でき、ローカルでのハッキングを回避できます。

UDP ASSOCIATE

SOCKS5 は UDP 転送もサポートしています:

Client → Server: CMD=UDP ASSOCIATE, DST.ADDR=0.0.0.0, DST.PORT=0
Server → Client: REP=成功, BND.ADDR=<サーバー UDP リレー IP>, BND.PORT=<ポート>
その後: クライアントは BND.ADDR:BND.PORT に UDP データグラムを送信し、その前に SOCKS5 UDP ヘッダーを追加:
  [RSV 2B][FRAG 1B][ATYP 1B][DST.ADDR][DST.PORT][DATA]

PAC

PAC は JavaScript スクリプトであり、ブラウザは各リクエストの前にそれを実行し、URL/ホストに基づいてプロキシを使用するかどうかを動的に決定します:

function FindProxyForURL(url, host) {
    // ローカルネットワーク → 直接接続
    if (isInNet(host, "192.168.0.0", "255.255.0.0")) return "DIRECT";
    if (shExpMatch(host, "*.local"))              return "DIRECT";
    // 中国国内 → 直接接続
    if (shExpMatch(host, "*.cn"))                 return "DIRECT";
    // その他 → プロキシ
    return "PROXY 127.0.0.1:7890; SOCKS5 127.0.0.1:1080; DIRECT";
}

PAC とブラウザのプロキシ設定の違い: 従来のプロキシ設定は静的です (on/off)。PAC はリクエストごとの動的ルールを提供します。return "DIRECT" はプロキシを使用しないことを意味します。

参照

  • RFC: 7231 (CONNECT), 1928 (SOCKS5), 1929 (SOCKS5 ユーザー/パスワード認証)
  • mihomo: wiki.metacubex.one (mixed port = HTTP + SOCKS5 自動検出)
  • ツール⁠: curl --proxy socks5h://127.0.0.1:1080 https://example.com (socks5h = プロキシが DNS 解決を行う)

キーワード: HTTP CONNECT, SOCKS5, PAC, 順方向プロキシ, TCP トンネル, UDP ASSOCIATE