参考文档:
https://wenku.baidu.com/view/821cf78014791711cc7917a1.html
https://www.cnblogs.com/mlgjb/p/8243690.html
【我们这里只讨论过程,协议细节请参考 https://www.cnblogs.com/mlgjb/p/8243690.html】
我们都知道ipv4中的地址数量是有限,这个限制导致了大量的计算机是位于防火墙或NAT后面的,他们所持有的仅仅是一个内网IP地址。 通常,内网的计算机与外部公网上的计算机交互是没有问题的,但是当你想让2台在不同内网中的计算通信时,问题就来了。 这种通信我们称之为p2p通信,在通信之前我们需要检测他们之间能否进行p2p通信以及如何通信。 这就涉及到了NAT穿透的问题了(NAT Traversal)
最常见的NAT穿透是基于UDP的,例如我们将要研究的STUN。
STUN(Simple Traversal of UDP Through NAT)是一个完整的NAT穿透解决方案,参考 RFC3489
在最新的RFC5389中,STUN被定位成穿透NAT的工具,而不再是一个解决方案,Session Traversal Utilities for NAT.
我们先研究STUN是怎样一步步实现的NAT穿透的,获得一个对STUN的整体的认识。
要研究这个过程,我们先对我们的环境进行一些假设,这样方便进行描述:
如图1所示,我的客户端位于NAT后面, STUN Server位于公网中。 具体的IP和端口如下:
Client的IP地址和端口号为: IP_C 和 Port_C
NAT的映射后的IP和端口号为:IP_N 和 Port_N
STUN的IP地址和端口为: IP_S1 IP_S2 和 Port_S1 Port_S2
STEP1:验证客户端是否在NAT后面
从客户端发送一个UDP包到 IP_S1 + Port_S1, STUN收到后会把 IP_N+Port_N 保存到UDP包中作为对客户端请求的响应。然后把这个响应发送到 IP_N+Port_N。
无论客户端前面的NAT是什么类型,客户端都应该能够收到这个响应。 如果没有收到,要么是STUN Server不存在(或者你写错了地址或端口), 要么是你的NAT拒绝一切UDP包从外部进入。
当客户端收到响应数据时,我们就能从中得到 IP_N+Port_N, 也就是说我们从这一步能够得到NAT的外网地址和端口号。
拿到NAT的外网地址和端口号后,用其IP和client自身的IP地址进行比较:
如果相同,说明client具有公网地址,它没有在NAT后面。
如果不同,说明client在NAT后面,我们还要进行更多验证。
STEP2:验证我们的NAT是不是 Full Cone NAT
从客户端发送一个UDP包到 IP_S1 + Port_S1,请求Stun Server使用 IP_S2 + Port_S2 对我们的请求进行响应。
如果能收到响应数据: 说明NAT是 Full Cone NAT, 因为NAT来者不拒,不对数据进行任何过滤。
如果未收到响应数据: 我还需要进一步验证NAT的类型
STEP3:验证我们的NAT是对称NAT还是Cone NAT
从客户端发送一个UDP包到 IP_S2 + Port_S2, STUN收到后会把 IP_N+Port_N 保存到UDP包中作为对客户端请求的响应。然后把这个响应发送到 IP_N+Port_N。
这个测试中,我们关心的是UPD包中的数据, 如果包中的 Port_N 与 STEP1中的 Port_N是相同的,那么我们就可以肯定,这是个一个Cone NAT,如果不同那么就说明是个对称NAT,Stun Server无法解决这类NAT穿透问题~~
STEP4:区分 Restict Cone NAT 和 Port Restrict Cone NAT
从客户端发送一个UDP包到 IP_S1 + Port_S1, 要求 Stun Server 用 IP_S1 + Port_S2 返回响应给client。
如果client能收到:说明是 Restrict Cone NAT
如果收不到: 说明时 Port Restrict Cone NAT
到此,整个过程就结束了,除了对称NAT外,我们都能得到NAT的外网IP和端口,以及NAT的类型。
对称NAT的穿透方法将在下一篇中研究-----TURN