P2P NAT穿越

NAT 不仅实现地址转换,同时还起到防火墙的作用,隐藏内部网络的拓扑结构,保护内部主机。 NAT 不仅完美地解决了 lP 地址不足的问题,而且还能够有效地避免来自网络外部的攻击,隐藏并保护网络内部的计算机。 这样对于外部主机来说,内部主机是不可见的。但是,对于P2P 应用来说,却要求能够建立端到端的连接,所以如何穿透NAT 也是P2P 技术中的一个关键。


由于nat的透明性,所以clienta-1和clientb-1不用关心和server通信的过程,他们只需知道server开放服务的地址和端口即可。

使用udp穿透nat

 通常情况下,当进程使用udp和外部主机通信时,NAT会建立一个session,这个session能够保留多久并没有标准,或许几秒,几分钟,几小时。假设Clienta-1在应用程序中看到了Clientb-1在线,并且想和Clientb-1通信,一种办法是server作为中间人,负责转发Clienta-1和Clientb-1之间的消息,但是这样服务器太累。另一种方法就是让Clienta-1和Clinetb-1建立端到端的连接,然后他们自己通信。这也就是p2p连接。

(1)全锥NAT ,穿透全锥型NAT 很容易,根本称不上穿透,因为全锥型NAT 将内部主机的映射到确定的地址,不会阻止从外部发送的连接请求,所以可以不用任何辅助手段就可以建立连接。

(2)限制性锥NAT和端口限制性锥NAT (简称限制性NAT),穿透限制性锥NAT,会丢弃它未知的源地址发向内部主机的数据包。所以如果现在ClientA-1 直接发送UDP数据包到ClientB-1,那么数据包将会被NAT-B无情的丢弃。

所以采用下面的方法来建立ClientA-1和ClientB-1之间的通信

1 ClientA-1(202.103.142.29:5000)发送数据包到Server,请求和ClientB-1(221.10.145.84:6000)通信。

2 Server将ClientA-1的地址和端口(202.103.142.29:5000)发送给ClientB-1,告诉ClinetB-1,ClinetA-1想和他通信。

3 ClinetB-1向ClinetA-1(202.103.142.29:5000)发送udp数据包,当然这个包在到达NAT-A的时候,还是会被丢弃,这并不是关键,因为发送这个udp包只是为了让NAT-B记住这次通信的目的地址,端口号,当下次以这个地址和端口号为源的数据到达的时候就不会被NAT-B丢弃,这样就在NAT-B上打了一个从ClinetB-1到ClinetA-1的洞。

4 为了让ClinetA-1知道什么时候才可以向ClinetB-1发送数据,所以ClientB-1在向ClientA-1(202.103.142.29:5000)打孔NAT-B之后还要向Server发送一个消息,告诉Server它已经准备好了。

5 Server发送一个消息给ClinetA-1,内容为:ClinetB-1已经准备好了,你可以向ClientB-1发送消息了。

ClientA-1向ClientB-1发送udp数据包,这个数据包不会被NAT-B丢弃(在第3步中,已经在NAT-B上打了一个从ClientB-1到ClientA-1的洞),以后ClinetB-1向ClinetA-1发送的数据包也不会被ClientA-1丢弃,因为NAT-A已经知道是ClientA-1首先发起的通信.至此,ClinetA-1和ClientB-1就可以通信了。


使用TCP 穿透NAT

使用TCP 协议穿透NAT的方式和使用UDP 协议穿透NAT的方式几乎一样,没有什么本质上的区别,只是将无连接的UDP变成了面向连接的TCP 。值得注意是:

1 ClientB-1在向ClientA-1打孔时,发送的SYN数据包,而且同样会被NAT-A丢弃。同时,ClientB-1需要在原来的socket上监听,由于重用socket ,所以需要将socket属性设置为SO_REUSEADDR 。

2 ClientA-1 向ClientB-1 发送连接请求。同样,由于ClientB-1到ClientA-1 方向的孔已经打好,所以连接会成功,经过3次握手后,ClientA-1到ClientB-1之间的连接就建立起来了。


猜你喜欢

转载自blog.csdn.net/daitu3201/article/details/80407323