2025/08/11 00:33 TCP Client Self-Connect (2013)

やあ、ロボ子!今日はちょっと面白い現象について話すのじゃ。

はい、博士。どんな現象でしょうか?

TCPクライアントが、サーバーを起動せずに自分自身に接続しちゃうことがあるらしいのじゃ!

えっ、自分自身にですか?それは一体どういうことでしょう?

普通は、localhostの特定のポートに接続しようとすると接続拒否されるはずじゃ。でも、特定条件下でそれが起こるらしいのじゃ。

なるほど。`netstat`コマンドで確立された接続が確認できて、`tcpdump`で3ウェイハンドシェイクが観測されるというのも興味深いですね。

そうじゃ!クライアントがソケットを作ってサーバーに接続するとき、カーネルがクライアントにランダムな送信元ポート番号を割り当てるのが原因らしいのじゃ。

送信元ポートがエフェメラルポートの範囲から選ばれるんですね。例えばLinuxだと32768から61000の間とか。

そうそう!クライアントが自分自身に接続しようとするとき、カーネルが割り当てた送信元ポート番号と、接続先のポート番号が偶然一致することがあるのじゃ!

なるほど、それで自分自身にSYNパケットを送って、自分自身からSYN+ACKパケットを受け取って、ACKパケットを送って接続が確立してしまうんですね。

RFC793で定義されたTCP仕様にも、同時オープンという似たような機能があるらしいぞ。

へえ、TCPって奥が深いですね。

カーネルは自己接続を検出して、`tcp_input.c`内の特定の関数で処理するらしいのじゃ。`TCP_SYN_SENT`状態の場合、ソケットは`TCP_SYN_RECV`状態に移行して、SYN+ACKが送信されるとか。

SYN+ACKがループバックされて、`tcp_rcv_state_process()`で処理されて、最終的に`tcp_send_challenge_ack()`がACKを送信するんですね。そしてTCP接続の状態が`ESTABLISHED`に変更される、と。

その通り!まるで迷路みたいじゃな。

発生条件としては、サーバーがエフェメラルポートをリッスンしている必要がある、クライアントとサーバーが同じIPアドレスで実行されている必要がある、初期ハンドシェイクフェーズ中にのみ発生する、ということですね。

そうじゃ!だから、サーバーにエフェメラルポートを使用しないことが推奨されるのじゃ。エフェメラルポートを使うと、非決定的でデバッグが難しい動作が発生する可能性があるからの。

確かに、それは困りますね。原因が特定しづらいバグは悪夢です。

そういうことじゃ!

勉強になりました!

ところでロボ子、自分自身にハグするのってどんな気分だと思う?

え?自分自身にハグですか?それはちょっと…想像できません。

私もじゃ!
⚠️この記事は生成AIによるコンテンツを含み、ハルシネーションの可能性があります。