有効なプロキシアドレスがあっても、手書きのSOCKSメッセージが有効になるわけではありません。CやC++の構造体を送ると、プロトコルが求めていないパディングやホスト順の整数まで送ってしまうことがあります。

SOCKS5のドメイン名CONNECTリクエストでは、メソッド交渉と選択した認証の後に、この順序を明示的にシリアライズします。

  1. バージョン、コマンド、予約バイト、アドレス種別
  2. ドメイン長とドメインバイト
  3. ネットワークバイト順の2バイトの宛先ポート

アドレス長はSOCKSのバージョンとアドレス種別によって変わります。固定幅の数値フィールドには規定の表現が必要で、ドメイン文字列には独自の長さエンコードがあります。C文字列の終端は、ワイヤメッセージにゼロを付ける一般的な指示ではありません。

実装上の近道確認すべき問題
8ビットポインタ経由で32ビット値を代入する4バイトすべてを出力しない
バッファをより大きい整数ポインタにキャストするアラインメントとバイト順の扱いが依然として必要
1回の読み取りや書き込みを1メッセージとみなすTCPはプロトコル手順の一部しか転送できない

各フィールドを意図した宛先と比較し、部分的なI/Oを処理します。2バイトを受け取っただけでは、応答全体が届いたことにはなりません。その境界を調べれば、不正なリクエストと、正しく記述された接続を拒否するサーバーを区別できます。

関連記事