私は同じ(管理されていない)スイッチに接続された2つのLinuxサーバ(AとBの名前を付けましょう)を持っています。両方のサーバーでファイアウォールを無効にしました(すべてのテーブルのルールはなく、すべてのデフォルトポリシーはACCEPTに設定されています)。したがって、あるサーバーがTCP/IPパケットを送信するのを防ぐ必要はありません。TCP/IPリセット(RST)フラグを送信しない原因は何ですか?
今、私たちは着信接続を待ち受けるTCPサーバーアプリケーションを実行してから、ループ内の多くのデータを接続されたクライアントに送信します。クライアントからの読み取りを試みることはなく、クライアントが切断した場合にソケットへのwrite()を実行している間にEPIPEエラーが発生することを期待します。
次に、クライアントアプリケーションとしてnc(netcat)を実行し、Aのサーバーアプリケーションに接続してデータを受信し、数秒後にCtrl-Cを押してこの接続を中断します。
私が見ているのは、Aのサーバーアプリケーションがwrite()でハングしているだけで、EPIPEや他のエラーがありません。
私はtcpdumpのを使用してTCP/IPパケットをトレースし、ここで私が見たものであるしました:
- B上のnetcatを中断した後、Bが正しくそのFINにACKで応答AにFINを送信する - そうOKである公正な半開TCPコネクションを持っています。次に、Aは通常のACKとPSH、ACKパケットで次のデータを送信しようとします。これらのパケットには何らかの形で応答しません(既に閉じられている/存在しないTCP接続にパケットを受信しているので、RSTパケットで応答すると期待しています)
- Aは、それが新たなデータの送信を停止し、古いパケットを再送開始して(この時点で次の呼び出しを書くために)(ハング)、ACKを持っていません
私はまた、A上のnetcatを実行しようとしました(したがって、クライアントとサーバの両方のアプリケーションが同じ物理サーバ上で動作します)、このようにしてすべてが期待どおりに動作します.netcatをCtrl-Cで中断した直後に、サーバアプリケーションはEPIPEを取得します。そしてtcpdumpは、期待どおりにRSTパケットが送信されたことを示しています。
この場合、RSTを送信しない原因は何ですか?
最新のカーネル2.6.39-hardened-r8をHardened Gentoo Linuxで使用していますが、sysctlネットワーク関連の設定は特にありません。
重要なネットワークアクティビティがあることに注意することは重要であるかもしれないし、重要ではないかもしれません.によってリストされた約5000個のTCP接続がいつでもあり、平均で約1000回の接続が開かれます。それは、このようなカーネルログの何かに見ていつものだ(ただし、ポート番号は、上述のサーバ・アプリケーションによって使用される異なる):この動作は結果であるhttp://i54.tinypic.com/1zz10mx.jpg
netcatを終了した後netstatはサーバBの接続をもうリストしません(私はFIN_WAIT_2の状態になっているはずです)期待通りにCLOSE_WAIT状態の接続。 ** 2)**誰かがSO_LINGERのために起こるかもしれないと思っていますが、netcatはSO_LINGERを手動で起動せず、exit()の前にclose()を実行するので自動的に起動しないようにします。 ACK/RSTはとにかく_incoming_パケットで応答します。 – Powerman
古いカーネル(2.6.28-hardened-r9)のように見えます - RSTパケットを送信します。 – Powerman