P2P穿透&四种NAT类型

  • Post author:
  • Post category:其他




以下对四种


NAT


类型分别予以说明:



1.全锥形


NAT








IP


、端口都不受限。



只要客户端由内到外打通一个洞之后(



NatIP:NatPort -> A:P1



),其他


IP


的主机


(

B

)


或端口


(

A:P2

)


都可以使用这个洞发送数据到客户端。


映射关系为:


Client->NatIP:NatPort->Any


,即任何外部主机都可通过


NatIP:NatPort


发送数据到


Clietn


上。








2.受限锥形


NAT








IP


受限,端口不受限。



当客户端由内到外打通一个洞之后


(

NatIP:NatPort -> A:P1

)





A


机器可以使用他的其他端口(



P2



)主动连接客户端,但


B


机器则不被允许。


映射关系为:


Client-> NatIP:NatPort->A


,即只有来自


A


的数据包才能通过


NatIP:NatPort


发送到


Client


上。





3.端口受限锥型








IP


、端口都受限。



返回的数据只接受曾经打洞成功的对象(


A:P1


),由


A:P2





B:P1


发起的数据将不被


NatIP:NatPort


接收。


映射关系为:


Client->NatIP:NatPort->A:P1


,即只有来自


A:P1


的数据才可通过


NatIP:NatPort


发送到


Client


上。




4.对称型


NAT







对称型


NAT


具有端口受限锥型的受限特性。但更重要的是,他对每个外部主机或端口的会话都会映射为不同的端口(洞)。只有来自相同的内部地址(


IP:PORT


)并且发送到相同外部地址(


X:x


)的请求,在


NAT


上才映射为相同的外网端口,即相同的映射。一个外部地址(


X:x


)对应一个


NAT


上的映射,如上图红色三角,每个映射仅接收来自他绑定的外部地址的数据。注:


X


在这里意为任意一台外部主机,


x


为这台主机上的任意一个端口。


映射关系为:


Client->NatIP:Pa1->A:P1


,当


Client


访问


B:P1


时,映射关系变为:


Client->NatIP:Pb->B:P1


,同理,


NatIP:Pa2


也就是


Client


访问


A:P2


时的映射。






以上我们只是说了一点基本的理论。接下来我们要实现不同内网通过internet网进行通迅


再来,我们举个图例

A<———–>NatA<———->NatB<———->B

A的地址是:192.168.1.100端口4000

B的地址是:192.168.1.100端口4000

它们两个都是内网的地址。及局域网内部地址。并不是全球唯一地址。

两个路由:

NatA的地址是:222.182.100.1

NatB的地址是:222.182.100.2

这两个路由是外网的地址,及全球唯一地址。

现在我们要实现A与B的通迅。

因为A与B都不是外网地址。所以A不可能向192.168.1.100发送消息。这消息只会它自己收到,因为这个IP是它自己的。同样B也不可以。

那么A向NatB发送消息,B能收到吗?答案是否定的,不能收到。刚才我们提到过。因为路由没有映射B的地址。A并不知道这个Session就连NatB也不知道这个Session因为B没有向A发送消息,并不产生这个Session。

就算B和A同时向双方的路由发送消息,产生的Session,A和B也得不到。因为在路由上就把这个消息当做为无用包给丢弃掉了。

那么这样的情况我们要进行通迅怎么办呢?

对,就是刚才我们提到的第三方。第三方是个什么方呢?

第三方必须是一个拥有固定外网IP的服务方。及一个外网服务器。全唯一IP地址。

图例:

假定我们这个第三方为C

C  IP:222.182.100.3端口4001

A<———–>NatA<—————>C<——————–>NatB<————->B

↑______________________________↑

原理如下

A通过路由向C发送消息,C获取A的在路由上的Session地址,映射的IP和端口

B同样。

这时候C就有了A和B的地址。

C可以和A、B进行通迅,但是A和B还不行。

现在C需要通知A方B的映射IP和端口。也要通知B方A的映射IP和端口。

这样A就有了B的映射地址,B也有了A的。但是现在还不能进行通迅。

因为在路由上A和B都只有对C的穿透。并没有相互之前的穿透。

那么A要向B发送消息怎么办呢?需要C向B发送一个消息告诉B方A的地址让B向这个地址发送一个消息,对A进行一个穿透。

这样A就可以向B发送消息了。在A向B发送消息的同时,A也在向B进行穿透。

这样就可以实现相互的通迅了。如果有多个端点,也就以此类推了。

宗上所述就是P2P的UDP实现原理了。TCP也是一样的。提示一点。Session在路由上是有时限的,一分钟到几小时不定。不同的路由不同的时间,为了保持这个Session的存在,你需要在固定时间点进行通迅,保持这个穿透,否则就得重新穿透。

值得注意的一点。

路由上的映射有两种情况

第一种情况是:Cone NAT

第二种情况是:Symmetric NAT

我们以上的实现是以Cone Nat为基础的。为什么呢?因为Cone Nat在映射的时候端口是不变的。无论你内网有多少台机器,向外网发送消息在路由上映射的端口都是不变的。

而Symmetric Nat则相反,一个映射一个端口。如果碰到这种情况只有祝你好运了,最好不要猜。(十有八九猜不到。所以不推荐猜)





版权声明:本文为yuanchunsi原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。