2013-03-11 64 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