客户端位于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