SOCKS4 の接続要求は成功しますが、アプリケーションはサーバーの最初の挨拶を決して目にしません。確認すべき箇所の一つはコネクタの最初の読み取りです。16 バイトの読み取りは、8 バイトの SOCKS4 応答には大きすぎます。

応答フィールドバイト
応答バージョンフィールド1
結果コード1
ポートフィールド2
アドレスフィールド4

結果コード 0x5a は要求が許可されたことを示します。SOCKS4a は要求がホスト名を運ぶ方法を変えますが、応答を 16 バイトにするわけではありません。

応答の後、同じ TCP ストリームが宛先のプロトコルを運びます。メールサーバーは挨拶をすぐに送るかもしれません。そのため利用可能な 16 バイトを消費する読み取りは、プロキシ応答全体に加えてその挨拶の最初の 8 バイトまで持ち去ることがあります。まだ何も続かない場合、大きすぎるブロッキング読み取りは代わりに不要な待ち時間を追加します。

正確な長さはパーサーの責任

一度に 8 バイトを要求することは、8 バイトが到着した十分な証拠にはなりません。ストリームの読み取りはそれより少なく返ることがあります。 期限を設けて応答の長さを正確に集め、閉じられた、または失敗したストリームでは停止し、応答を検査し、後続のバイトはアプリケーションに残します。

コネクタがより大きなバッファ読み取りを使うなら、境界より後ろをすべて保持し、次の消費者に渡します。余剰を捨てるのは、読み取りサイズが違うだけで同じデータ損失です。

SOCKS5 には独自のパーサーが必要です。その応答アドレスの長さはアドレス種別によって異なる場合があります。すべてのプロキシ読み取りを固定の 8 バイト読み取りに置き換えると、一方のプロトコルを直しつつ別のものを壊します。

関連記事