Simultaneous TCP open(同时开放TCP连接)

http://hi.baidu.com/totty/item/f905eee5201aee3b4ddcafb4

这里有一种方法能够在某种情况下建立一个穿透NAT的端对端TCP直连。我们知道,绝大多数的TCP会话的建立,都是通过一端先发送一个SYN包开始,另一方则回发一个SYN-ACK包的过程。然而,这里确实存在另外一种情况,就是P2P的双方各自同时地发出一个SYN包到对方的公网地址上,然后各自都单独地返回一个ACK响应来建立一个TCP会话,这个过程被称之为:“Simultaneous open”(“同时开放连接”)。

如果一个NAT接收到一个来自私有网络外面的 TCP SYN 包,这个包想发起一个“引入”的 TCP 连接,一般来说,NAT会拒绝这个连接请求并扔掉这个SYN 包,或者回送一个TCP RST(connection reset,重建连接)包给请求方。但是,有一种情况,当这个接收到的 SYN 包中的源IP地址和端口、目标IP地址和端口都与NAT登记的一个已经激活的TCP会话中的地址信息相符时,NAT将会放行这个SYN 包,让它进入NAT内部。特别要指出,如果NAT恰好看到一个刚刚发送出去的一个SYN包也和上面接收到的SYN包中的地址信息相符合的话,那么NAT将会认为这个TCP连接已经被激活,并将允许这个方向的SYN包进入NAT内部。

    如果 Client A 和 Client B 能够彼此正确的预知对方的NAT将会给下一个TCP连接分配的公网TCP端口,并且两个客户端能够同时地发起一个“外出”的TCP连接,并在对方的 SYN 包到达之前,自己刚发送出去的SYN包都能顺利的穿过自己的NAT的话,一条端对端的TCP连接就成功地建立了。

(好似一个间谍活动)

不幸的是,这个诡计比3.4节所讲的UDP端口预言更容易被粉碎,并且对时间的敏感性的依赖更多!首先,除非双方的NAT都是Simple firewalls 或者都像cone NAT那样处理TCP通信,否则两个客户端还是无法建立这个TCP直连,因为它们无法预知对方的NAT会分配给新的会话的端口号是多少。 另外,如果双方的 SYN 到达对方的NAT 速度太快(举例来说,就是SYN A的还未穿过NAT A时,SYN B已经提早到达了NAT A),对方的NAT会将这个SYN扔掉,并返回一个 RST 包,这样就使得这个发快了的一方NAT关闭原来的会话,又重新建立一个新的会话,再利用这个新的会话重发一个SYN,这时端口预言就失效了,因为再次分配到相同的端口地址的几率太小了。

       最后,尽管在“TCP规范”中说明了“Simultaneous open”是一种支持的标准技术,但是在一些公共操作系统中,对这种技术的支持并不好。基于这个原因,我们也在这里郑重申明,并不推荐使用这个技术。如果您的应用程序想要穿透NAT并进行高效率高性能的P2P的通信,应该使用UDP技术!

这里我将这个技术的详细过程描述如下,欢迎大家指正:

Simultaneous TCP open(同时开放TCP连接)_第1张图片

过程详细描述:

Client A发送一个TCP SYN 包给 Client B,我们把这个SYN包叫做 SYN A,包含的信息如下:

SrcAddress:10.0.0.1                 Tcp port :1234 

DestAddress:138.76.29.7          Tcp port:310000

 

同时,Client B发送一个TCP SYN包给Client A,我们把这个包叫做 SYN B,包含的信息如下:

SrcAddress:10.1.1.3                Tcp port :1234

DestAddress:155.99.25.11       Tcp port:620000

 

SYN A首先通过NAT A(必须在SYN B到达NAT A之前),NAT A看到这个包并将其地址信息进行转换为:

SrcAddress:155.99.25.11         Tcp port :620000

DestAddress:138.76.29.7         Tcp port:310000

我们把这个经过 NAT A转换的包叫做 SYN A’

 

同样,SYN B首先通过NAT B(也必须在SYN A到达NAT B之前),NAT B看到这个包并进行地址转换为:

SrcAddress:138.76.29.7           Tcp port:310000

DestAddress:155.99.25.11       Tcp port :620000

我们把这个经过NAT B转换的包叫做 SYN B’

 

这时,NAT A和NAT B都在自己的TCP连接表中存储了含有上面两个公网IP地址和端口信息,因此,只要看到包含这两个信息的SYN包,都会让其通过。

 

就在这个瞬间,SYN A’到达了NAT B,NAT B检查了一下SYN A’,发现它的地址信息和自己TCP连接表中的信息相符,便让SYN A’通过了,并将SYN A’的地址信息转换为:我们称这个包为 SYN A’’

SrcAddress:155.99.25.11      Tcp port :620000

DestAddress:10.1.1.3           Tcp port:1234   

以使这个包能够到达内部网中Client B上

 

也就在这个瞬间,SYN B’到达了NAT A,NAT A检查了一下SYN B’,发现它的地址信息和自己TCP连接表中的信息相符,便让SYN B’通过了,并将SYN B’的地址信息转换为:我们称这个包为 SYN B’’

SrcAddress:138.76.29.7       Tcp port :310000

DestAddress:10.0.0.1          Tcp port:1234    

以使这个包能够到达内部网中Client A上

 

这时,Client A收到了SYN B’’,Client B收到了SYN A’’,并返回给对方ACK,经过三次握手,这个P2P的TCP连接就建立了。


你可能感兴趣的:(Simultaneous TCP open(同时开放TCP连接))