Perl が SOCKS 接続を開いた後に TLS を追加する
IO::Socket::SSL を IO::Socket::Socks 接続の上に重ね、接続先のホスト名を検証します。
SOCKS 接続と TLS 接続は役割が異なります。まず SOCKS 経由で接続先へのバイトストリームを取得します。次にそのストリームの上で TLS を開始し、プロキシではなく接続先のウェブサイトを識別します。
HTTPS 形式の TLS エンドポイントの場合、構成は次のようになります。
use IO::Socket::Socks;
use IO::Socket::SSL;
my $target = 'example.com';
my $socket = IO::Socket::Socks->new(
SocksVersion => 5,
ProxyAddr => '127.0.0.1',
ProxyPort => 1080,
ConnectAddr => $target,
ConnectPort => 443,
) or die $!;
IO::Socket::SSL->start_SSL(
$socket,
SSL_hostname => $target,
SSL_verifycn_name => $target,
SSL_verifycn_scheme => 'http',
SSL_verify_mode => SSL_VERIFY_PEER,
) or die IO::Socket::SSL::errstr();
許可された公開プロキシ経路にある公開 HTTPS ターゲットには、SOCKS5 プロキシ一覧が ProxyAddr と ProxyPort の候補を提供します。この断片はトランスポート層を確立するだけであり、アプリケーションは接続先が期待するプロトコルを送信し、終了時にソケットを閉じる必要があります。
意図したピア名を保つ
プロキシのエンドポイントは最初の接続に属します。TLS SNI とホスト名検証が関係するのはexample.comです。その段階でプロキシのホスト名を使うと、誤った識別名を要求したり検証したりする可能性があります。
トラストストアの設定も独立した要件です。診断用の例からコピーした「すべてを信頼する」コールバックではなく、アプリケーションが意図する CA 設定を使用してください。
SOCKS の段階が失敗した場合、TLS パラメータを変えても直りません。SOCKS が成功して TLS が失敗した場合は、証明書とホスト名のエラーを証拠として保持し、一般的なプロキシ障害として扱わないでください。
モジュール名も重要です。IO::Socket::Socks と IO::Socket::SSL はコンストラクタもアップグレードの挙動も異なります。プロキシに到達しただけの生の TCP ソケットは、まだ SOCKS の接続先ネゴシエーションを完了していません。