STUN in P2P network

0x1 STUN简介

STUN(Session Traversal Utilities for NAT)是一种协助穿越NAT的工具,并不独立提供穿越的解决方案。详细请参考
RFC3489,升级版协议是RFC5389RFC7350

STUN的使用场景如下,Interactive Connectivity Establishment (ICE) [MMUSIC-ICE], Client-initiated
connections for SIP [SIP-OUTBOUND], and NAT Behavior Discovery [BEHAVE-NAT]。

0x2 NAT检测

RFC3489中将NAT的实现分为四大类:
1.Full Cone NAT (完全锥形NAT)
2.Restricted Cone NAT (限制锥形NAT ,可以理解为IP限制,Port不限制)
3.Port Restricted Cone NAT (端口限制锥形NAT,IP+Port 限制)
4.Symmetric NAT (对称NAT)
其中完全最上层的完全锥形NAT的穿透性最好,而最下层的对称形NAT需要借助TURN服务器进行数据转发,两个client之间不能进行Peer to Peer的通信。

NAT类型检测过程如下
nat_check

如上图所示,一旦路经到达红色节点时,Peer to Peer的连接是没有可能性的,需要借助服务器进行转发。一旦通过黄色或是绿色的节点,Peer to Peer的连接是可以成功的。

下面介绍STUN是如何判断NAT的类型的。
内容来自ICE协议下NAT穿越的实现

假设B是客户端,C是STUN服务器,C有两个IP分别为IP1和IP2(至于为什么要两个IP,接着往下看):

STEP1.判断客户端是否在NAT后:

B向C的IP1的pot1端口发送一个UDP包。C收到这个包后,会把它收到包的源IP和port写到UDP包中,然后把此包通过IP1和port1发还给B。这个IP和port也就是NAT的外网 IP和port(如果你不理解,那么请你去看我的BLOG里面的NAT的原理和分类),也就是说你在STEP1中就得到了NAT的外网IP。

熟悉NAT工作原理的朋友可以知道,C返回给B的这个UDP包B一定收到。如果在你的应用中,向一个STUN服务器发送数据包后,你没有收到STUN的任何回应包,那只有两种可能:1、STUN服务器不存在,或者你弄错了port。2、你的NAT拒绝一切UDP包从外部向内部通过。

当B收到此UDP后,把此UDP中的IP和自己的IP做比较,如果是一样的,就说明自己是在公网,下步NAT将去探测防火墙类型,我不想多说。如果不一样,说明有NAT的存在,系统进行STEP2的操作。

STEP2.判断是否处于Full Cone Nat下:

B向C的IP1发送一个UDP包,请求C通过另外一个IP2和PORT(不同与SETP1的IP1)向B返回一个UDP数据包(现在知道为什么C要有两个IP了吧,虽然还不理解为什么,呵呵)。

我们来分析一下,如果B收到了这个数据包,那说明什么?说明NAT来着不拒,不对数据包进行任何过滤,这也就是STUN标准中的full cone NAT。遗憾的是,Full Cone Nat太少了,这也意味着你能收到这个数据包的可能性不大。如果没收到,那么系统进行STEP3的操作。

STEP3.判断是否处于对称NAT下:

B向C的IP2的port2发送一个数据包,C收到数据包后,把它收到包的源IP和port写到UDP包中,然后通过自己的IP2和port2把此包发还给B。

和step1一样,B肯定能收到这个回应UDP包。此包中的port是我们最关心的数据,下面我们来分析:

如果这个port和step1中的port一样,那么可以肯定这个NAT是个CONE NAT,否则是对称NAT。道理很简单:根据对称NAT的规则,当目的地址的IP和port有任何一个改变,那么NAT都会重新分配一个port使用,而在step3中,和step1对应,我们改变了IP和port。因此,如果是对称NAT,那这两个port肯定是不同的。

如果在你的应用中,到此步的时候PORT是不同的,那么这个它就是处在一个对称NAT下了。如果相同,那么只剩下了restrict cone 和port restrict cone。系统用step4探测是是那一种。

STEP4.判断是处于Restrict Cone NAT还是Port Restrict NAT之下:

B向C的IP2的一个端口PD发送一个数据请求包,要求C用IP2和不同于PD的port返回一个数据包给B。

我们来分析结果:如果B收到了,那也就意味着只要IP相同,即使port不同,NAT也允许UDP包通过。显然这是Restrict Cone NAT。如果没收到,没别的好说,Port Restrict NAT.

0x3 StunServer实现分析

STUN协议是一个客户机/服务器协议。StunServer可能和其他服务器(如web server, turn server)集成在一起。而stun client也可以在p2p的客户端中实现。
在核心的STUN协议中,只有一种称为“Binding”的方法。STUN客户端使用Binding来创建和发现NAT映射。当STUN服务器收到STUN Binding时,它会记录请求来着哪个公网IP和端口,此公网IP和端口会发生给STUN客户端,这样收到STUN Binding响应的客户端会根据这些信息判断NAT的类型。
stun

0x4 StunServer测试

测试结果如下,
kevin@ubuntu:~/Kevin/nat/stunserver$ ./stunclient 68.xxx.xxx.xxx 3478
Binding test: success
Local address: 192.168.40.200:47045
Mapped address: 116.xxx.xxx.xxx:56077

其中68.xxx.xxx.xxx是运行StunServer服务器的公网IP地址。
返回给Stun客户端的信息中包括了Stun客户端的公网IP为116.xxx.xxx.xxx,和内网地址(192.168.40.200)不一致,说明位于NAT之后。至于是哪种NAT类型,需要参考前面的流程进行多次测试。