我有兩臺Linux服務器(讓我們將它們命名爲A和B),連接到同一臺(非託管)交換機。我在兩臺服務器上都禁用了防火牆(所有表中都沒有規則,所有默認策略都設置爲ACCEPT)。所以,沒有什麼應該阻止一臺服務器發送任何TCP/IP數據包和另一臺服務器來接收它們。什麼可能導致TCP/IP重置(RST)標誌不被髮送?
現在,在一個我們運行TCP服務器應用程序,這聽/接受傳入的連接,然後發送大量的數據要在環連接的客戶端(S)。它不會嘗試從客戶端讀取數據,並且在客戶端斷開連接時執行write()套接字操作時會出現EPIPE錯誤。
接着,在B I運行NC(netcat的)作爲客戶端應用程序,連接到上的一個服務器應用程序,開始接收數據,和幾秒鐘後我按下Ctrl-C中斷這個連接。
我看到的,是服務器應用上的一個剛剛在寫()掛起,它並沒有得到EPIPE或其他任何錯誤。
我使用tcpdump的跟蹤TCP/IP數據包,這裏是我所看到的:
- 中斷第B的netcat後,B發送一個翅片到,它正確地ACK回覆該FIN - 所以,現在我們要公平半開TCP連接,這是確定
- 接下來,嘗試下一個數據發送到客戶端與常規ACK和PSH,ACK數據包,這也有望和正確
- BUT,B沒有按不會以任何方式回覆這些數據包(雖然我期望它回覆RST數據包,因爲它將數據包接收到已經關閉/不存在的TCP連接)
- A沒有得到ACK,所以它停止發送新數據,並開始重新發送數據包老(在這一點上一次調用write()方法掛起)
我也想跑上的一個netcat的(因此客戶端和服務器應用程序都在相同的物理服務器上運行),這樣一切都按預期運行 - 服務器應用程序在用Ctrl-C中斷netcat後立即獲得了EPIPE。並且tcpdump顯示按預期發送了RST數據包。
那麼,什麼可能會導致在此情況下,不發送RST?
我使用硬化的Gentoo Linux,跟上時代的,內核2.6.39硬化-R8,沒有任何特定的sysctl網絡相關的配置。
注意到這些服務器上存在重要的網絡活動或大約5000個tcp連接(在任何時候由netstat -alnp
列出),我認爲大約1000個連接平均每秒打開和關閉可能會也可能不重要。它通常在內核日誌是這樣看(但是從使用上面所討論的服務器應用程序的端口號是不同的):
TCP: Possible SYN flooding on port XXXXX. Sending cookies.
net_ratelimit: 19 callbacks suppressed
下面是TCP會話通常是這樣的:http://i54.tinypic.com/1zz10mx.jpg
從對其他網站的討論:** 1)**的netcat後退出了netstat不會再列出它連接上服務器B(雖然我認爲它應該在FIN_WAIT_2狀態中列出),在服務器A上的netstat仍然顯示此按照預期,處於CLOSE_WAIT狀態的連接; ** 2)**有人認爲這可能是因爲SO_LINGER而發生的,但我不同意,因爲netcat不會手動激活SO_LINGER並在exit()之前執行close(),因此不應該自動激活,並且SO_LINGER不應該影響ACK/RST無論如何都會對_incoming_包進行回覆。 – Powerman
看起來像舊內核(2.6.28-hardened-r9)按預期工作 - 發送RST數據包。 – Powerman