2013-03-11 87 views
2

我們正面臨着一個奇怪的問題,即關閉一個死的TCP套接字(由拔掉電線引起)會影響另一個正常的打開的TCP套接字。下面是詳細的信息:爲什麼要關閉一個死的TCP套接字會影響另一個打開的TCP套接字?

  1. 拓撲
    客戶端A←→開關A←路由器A:NAT←.. ..網絡→ 路由器B:NAT→交換機B←→服務器B

  2. 問題:
    假設客戶端和服務器之間存在由於拔下導線而導致的死連接。拔掉電纜(機器和交換機之間)後,我們從另一臺機器登錄客戶端A,現在客戶端和服務器之間會有一個新的tcp連接,並且此連接正常。

    我們從服務器發現,如果我們在tcp內核仍在重新傳輸數據的時候關閉死tcp連接,那麼其他tcp連接似乎會受到污染,從客戶端到服務器的方向將變得不可用意味着客戶端通過連接發送的數據永遠不會被服務器接收到,但令我們驚訝的是從服務器到客戶端的其他方向仍然正常,通過服務器發送到客戶端的相同tcp套接字數據機。

    但是,如果我們等待直到死連接的tcp數據傳輸停止, 2小時,然後關閉套接字,然後其他TCP連接保持OK。

以下是此問題的詳細步驟:
1,有兩個客戶端這兩者都是背後路由器A:NAT時,NAT是全錐。
2.路由器B後面有一臺linux服務器:NAT,NAT是full-cone,但是這裏使用端口轉發。
3.四臺機器和兩個客戶說他們是X,Y,服務器說它是S
4. X和Y的登錄和設置一個視頻會議,現在他們都創建TCP連接到服務器,說他們是信道CX和CY通道
5.拔掉機的電纜上,其中Y是客戶端運行,現在頻道CY已經壞掉了。但通道CX仍然正常。
6.從第四臺機器登錄Y,再次與X建立視頻會議,現在有一個新的tcp通道,說它是CY2

結果:
在步驟6中,如果服務器關閉死連接 - CY --in分鐘,然後將新的信道CY2將成爲單向 - 從客戶端Y發出水溼到達數據服務器包含ACK數據包,而反過來則可以。

如果服務器關閉了死連接 - CY - 在很長時間內這樣2個小時,那麼沒有問題發生

這個問題只發生在通過NAT運行時,至少當我們在同一個局域網內運行這些應用程序(不需要遍歷NAT)時,我們從不再重現它。

有人知道爲什麼會發生?

編輯:
在服務器端,我們使用非阻塞tcp套接字和選擇模型。

 psuedocode: 
    //server 
    listenfd = socket(,SO_STREAM,); 
    localAddr.port = htons(8013); 
    localAddr.ip = inet_addr(INADDR_ANY); 
    bind(localAddr...) 
    listen(listenfd, 100); 

    ... 
    //using select model 
    select(maxFd, &fdSet, NULL, NULL); 
    for(...) 
    { 
    if (FD_ISSET(listenfd)) 
     { 
     fd = accept(...) 
     set_non_block(fd); 
     ... 
     } 
    ... 
    } 

更多信息:第一機器上
1)連接部分A:192.168.10.4:13000←→...←路由器A:NAT← - 現在:從PublicIP:8661(隨機)。 .Network ..→Router B:NAT(到端口:8013,端口轉發)→...←→服務器B

2)第二臺機器上的連接B:192.168.10.7:13000←→... ←Router A:NAT←Now:from PublicIP:8777(random).. Network ..→Router B:NAT(to port:8013,端口轉發)→...←→服務器B

3)拔下線路和連接A死了,現在在第三臺機器上創建一個新的連接C:192.168.10.10:13000←→...←路由器A:NAT←-Now:從PublicIP:8869 (隨機)..網絡..→路由器B:NAT(到端口:8013,端口轉發)→...←→服務器B

如果我們關閉連接A從服務器,然後連接C將成爲單向,但如果我們在2小時內關閉服務器的連接A,則連接C仍然正常。

+0

如果客戶端A和服務器B之間只有一條路由,服務器在拔出線路時如何與客戶端建立連接? – jxh 2013-03-11 22:50:41

+0

@ user315052有許多機器連接到LAN中的交換機,所有這些機器共享一個公共IP。 – Steve 2013-03-11 23:04:59

+1

所以你說你拔掉了交換機和路由器之間的電纜,但交換機和路由器之間可能有多條電纜?我試圖想象如何重現你的問題,但我似乎無法弄清楚。 – jxh 2013-03-11 23:08:18

回答

2

哇,這麼一個難題。我認爲我有一個可能的答案。我不太喜歡它的含義 - 但我認爲它們在查看標準時是不可避免的(here是維基百科簡化)。

NAT(特別是全錐)的工作原理是給客戶端的內部地址(IP和端口),以符合它試圖達到的外部地址。任何返回的流量都會發送到內部地址,然後由路由器轉發到外部地址。

讓我們用一個例子來擴大這個簡短的explination並顯示這是什麼意思你...

假設你有一個NAT網關,轉發端口80到內部服務器,內部目標也是80端口。 網關具有外部IP n.n.n.n和內部IP y.y.y.y

當客戶端連接到n.n.n.n:80時,NAT服務器忠實地將請求轉發給y.y.y.y:80,但在此過程中它重寫了IP幀。發件人地址現在是NAT網關內部IP,並且發件人端口不再是客戶端寫入的內容,而是由NAT網關分配的新端口。

新的端口被NAT網關分配的,是的。但它被指定爲客戶端IP的功能,它試圖訪問的端口,在這種情況下,80

一切都很好,但是......當一個客戶建立了第二個連接相同的映射函數用於。這不應該造成問題?它可以。如果網關不區分不同的客戶端地址(理想情況下,每個來自客戶端的連接應具有唯一的端口),它將簡單地覆蓋舊連接的映射。

從而導致從舊套接字重新發送流量發送到客戶端的新套接字。

非常不可取,但可能取決於NAT的實施方式。而且,由於它似乎是一個NAT問題 - 直接連接時不會顯示...

現在,我已經在我的解釋中看到了一個漏洞 - 即這意味着您無法打開兩個插槽同一臺服務器,因爲任何回報將會出現亂碼。那麼,我能想到的唯一原因就是這個插座仍然是開放的 - 因此網關不會認爲它是死的,然後爲該客戶端創建第二個映射。

希望我至少有一些意義。

+0

fredrik,感謝您的幫助。我在最後添加了更多信息,請看看。 – Steve 2013-03-19 10:49:56

+0

附加信息很好地說明了我至少試圖解釋的內容:D NAT將舊連接數據錯誤地重定向到客戶端上的新連接 - 導致連接進入錯誤狀態。它在中級DOS攻擊中表現得像個男人。如果客戶端端口(在您添加的信息中是'13000')對於第二個連接是另外一個東西,它可能會有所幫助。在公共場所使用哪個端口是無關緊要的 - 這是發生在內部和客戶端上的重要事件。 – fredrik 2013-03-19 11:49:11

+0

fredrik,三個連接A,B,C在三臺不同的機器上創建。並且我嘗試了13000以外的隨機端口,第三個連接C總是在我們關閉死連接A後斷開。如果我們不關閉連接-A,則連接C仍然保持正常。 – Steve 2013-03-19 13:01:20