本文收集并整理了关于NAT穿越的一些技术,介绍这些技术的实现过程,让大家对NAT穿越技术的相关内容有个初步的认识与了解。
本文先介绍NAT的定义和类型,然后介绍穿越NAT的两个协议STUN和TURN,最后介绍ICE框架。
1、NAT介绍
1.1、NAT和防火墙的定义
1.1.1、防火墙
为了网络的安全性,公司一般都安装防火墙,它是一个放于私有网的设备,用来保护网络资源免受外部的恶意破坏。
防火墙检查从外部进来的每个数据包的IP地址和目的端口号,它经常如此设置:如果防火墙内的一台计算机A向防火墙外的一台计算机B主动发出请求要数据,防火墙会让外部计算机B的数据包通过,而且当且仅当数据包的目的地址和端口号与防火墙内发起请求的计算机A的地址和端口号相同;如果计算机B发来的数据包仅仅目的地址是防火墙内发起请求的计算机A的地址,而端口号不是计算机A发出请求的那个端口号,防火墙也将会丢弃那个外来的数据包。
防火墙总是被配置过滤掉所有不请自到的网络通信,有一个例外是在防火墙内提供Web Server供外部访问。在这种情况下,公司会配置防火墙允许目的地址是Web Server的IP地址且目的端口号为80的数据包通过,这就使得公司外部可以主动向公司的Web Server发起请求得到一些公司放在Server上的数据。
防火墙又分软件防火墙和硬件防火墙。
1.1.2、NAT
网络地址转换(NAT)是一个Internet标准,置于两网间的边界,其功能是将外网可见的IP地址与内网所用的地址相映射,这样,每一受保护的内网可重用特定范围的IP地址(例如192.168.x.x),而这些地址是不用于公网的。从外网来的含公网地址信息的数据包先到达NAT,NAT使用预设好的规则(其组元包含源地址、源端口、目的地址、目的端口、协议)来修改数据包,然后再转发给内网接收点。对于流出内网的数据包也须经过这样的转换处理。
NAT服务有两个主要目的:
1)许多公司使用NAT用作一个网络安全设备,因为它隐藏了内部IP地址,如果黑客不知道特定计算机的IP地址,想要攻击那台计算机是更困难的。
2)NAT让一个公司可以使用更多的内部IP地址,因为这些地址仅仅在内部使用,不可能与被别的公司和组织的IP地址产生冲突
1.2、NAT的四种类型
这里面涉及到几个概念,先介绍一下:
1)内部Tuple:指内部主机的私有地址和端口号所构成的二元组,即内部主机所发送报文的源地址、端口所构成的二元组。
2)外部Tuple:指内部Tuple经过NAT的源地址/端口转换之后,所获得的外部地址、端口所构成的二元组,即外部主机收到经NAT转换之后的报文时,它所看到的该报文的源地址(通常是NAT设备的地址)和源端口。
3)目标Tuple:指外部主机的地址、端口所构成的二元组,即内部主机所发送报文的目标地址、端口所构成的二元组。
四种NAT类型如下:
1)Full Cone NAT(完全圆锥型NAT)
所有来自同一个内部Tuple X的请求均被NAT转换至同一个外部Tuple Y,而不管这些请求是不是属于同一个应用或者是多个应用的。
除此之外,当X-Y的转换关系建立之后,任意外部主机均可随时将Y中的地址和端口作为目标地址和目标端口,向内部主机发送UDP报文,由于对外部请求的来源无任何限制,因此这种方式虽然足够简单,但却不那么安全。
2)Restricted Cone NAT(地址限制圆锥型NAT)它是Full Cone的受限版本。所有来自同一个内部Tuple X的请求均被NAT转换至同一个外部Tuple Y,这与Full Cone相同,但不同的是,只有当内部主机曾经发送过报文给外部主机(假设其IP地址为Z)后,外部主机才能以Y中的信息作为目标地址和目标端口,向内部 主机发送UDP请求报文,这意味着,NAT设备只向内转发(目标地址/端口转换)那些来自于当前已知的外部主机的UDP报文,从而保障了外部请求来源的安全性。
3)Port Restricted Cone NAT(端口限制圆锥型NAT)它是Restricted Cone NAT的进一步受限版。只有当内部主机曾经发送过报文给外部主机(假设其IP地址为Z且端口为P)之后,外部主机才能以Y中的信息作为目标地址和目标端口,向内部主机发送UDP报文,同时,其请求报文的源端口必须为P,这一要求进一步强化了对外部报文请求来源的限制,从而较Restricted Cone更具安全性。
4)Symmetric NAT(对称型NAT)这是一种比所有Cone NAT都要更为灵活的转换方式。在Cone NAT中,内部主机的内部Tuple与外部Tuple的转换映射关系是独立于内部主机所发出的UDP报文中的目标地址及端口的,即与目标Tuple无关; 在Symmetric NAT中,目标Tuple则成为了NAT设备建立转换关系的一个重要考量:只有来自于同一个内部Tuple 、且针对同一目标Tuple的请求才被NAT转换至同一个外部Tuple,否则的话,NAT将为之分配一个新的外部Tuple。
打个比方,当内部主机以相 同的内部Tuple对2个不同的目标Tuple发送UDP报文时,此时NAT将会为内部主机分配两个不同的外部Tuple,并且建立起两个不同的内、外部 Tuple转换关系。与此同时,只有接收到了内部主机所发送的数据包的外部主机才能向内部主机返回UDP报文,这里对外部返回报文来源的限制是与Port Restricted Cone一致的。不难看出,如果说Full Cone是要求最宽松NAT UDP转换方式,那么,Symmetric NAT则是要求最严格的NAT方式,其不仅体现在转换关系的建立上,而且还体现在对外部报文来源的限制方面。
1.3、NAT类型检查
前提条件:有一个公网的Server并且绑定了两个公网IP(IP-1,IP-2)。这个Server做UDP监听(IP-1,Port-1)、(IP-2,Port-2)并根据客户端的要求进行应答。NAT类型监测的步骤为:
1)检测客户端是否有能力进行UDP通信以及客户端是否位于NAT后?
客户端建立UDP socket然后用这个socket向服务器的(IP-1,Port-1)发送数据包要求服务器返回客户端的IP和Port, 客户端发送请求后立即开始接受数据包,要设定socket Timeout(300ms),防止无限堵塞. 重复这个过程若干次。如果每次都超时,无法接受到服务器的回应,则说明客户端无法进行UDP通信,可能是防火墙或NAT阻止UDP通信,这样的客户端也就不能P2P了(检测停止)。
当客户端能够接收到服务器的回应时,需要把服务器返回的客户端(IP,Port)和这个客户端socket的 (LocalIP,LocalPort)比较。如果完全相同则客户端不在NAT后,这样的客户端具有公网IP可以直接监听UDP端口接收数据进行通信(检测停止)。否则客户端在NAT后要做进一步的NAT类型检测(继续)。
2)检测客户端NAT是否是Full Cone NAT?
客户端建立UDP socket然后用这个socket向服务器的(IP-1,Port-1)发送数据包要求服务器用另一对(IP-2,Port-2)响应客户端的请求往回发一个数据包,客户端发送请求后立即开始接受数据包,要设定socket Timeout(300ms),防止无限堵塞. 重复这个过程若干次。如果每次都超时,无法接受到服务器的回应,则说明客户端的NAT不是一个Full Cone NAT,具体类型有待下一步检测(继续)。如果能够接受到服务器从(IP-2,Port-2)返回的应答UDP包,则说明客户端是一个Full Cone NAT(检测停止)。
3)检测客户端NAT是否是Symmetric NAT?
客户端建立UDP socket然后用这个socket向服务器的(IP-1,Port-1)发送数据包要求服务器返回客户端的IP和Port, 客户端发送请求后立即开始接受数据包,要设定socket Timeout(300ms),防止无限堵塞. 重复这个过程直到收到回应(一定能够收到,因为第一步保证了这个客户端可以进行UDP通信)。
用同样的方法用一个socket向服务器的(IP-2,Port-2)发送数据包要求服务器返回客户端的IP和Port。
比较上面两个过程从服务器返回的客户端(IP,Port),如果两个过程返回的(IP,Port)有一对不同则说明客户端为Symmetric NAT(检测停止)。否则是Restricted Cone NAT,是否为Port Restricted Cone NAT有待检测(继续)。
4)检测客户端NAT是否是Restricted Cone NAT还是Port Restricted Cone NAT?
客户端建立UDP socket然后用这个socket向服务器的(IP-1,Port-1)发送数据包要求服务器用IP-1和一个不同于Port-1的端口发送一个UDP数据包响应客户端, 客户端发送请求后立即开始接受数据包,要设定socket Timeout(300ms),防止无限堵塞. 重复这个过程若干次。如果每次都超时,无法接受到服务器的回应,则说明客户端是一个Port Restricted Cone NAT,如果能够收到服务器的响应则说明客户端是一个Restricted Cone NAT。
2、用于NAT穿越的STUN协议
2.1、STUN协议介绍
STUN(Simple Traversal of User Datagram Protocol Through Network Address Translators),即简单UDP穿透NAT协议,是个轻量级的协议,是基于UDP的完整的穿透NAT的解决方案。
它允许应用程序发现它们与公共互联网之间存在的NAT和防火墙及其他类型。它也可以让应用程序确定NAT分配给它们的公网IP地址和端口号。STUN是一种Client/Server的协议,也是一种Request/Response的协议,默认端口号是3478。STUN具体内容可以参考RFC3489、RFC5389。
2.2、STUN协议的实现过程
STUN协议的部署图如上,STUN协议实现穿越的流程如下:
- 1)Client A和Client B分别向STUN服务器发出请求,询问并注册自身的转换后地址。
- 2)STUN Server收到请求消息,产生响应消息,响应消息中携带请求消息的源端口,即Client A(B)在NAT上对应的外部端口,然后响应消息通过NAT发送给Client A(B)。
- 3)Client A将其在NAT上对应的外部地址和端口信息包含在消息中,发送给STUN Server请求要和Client B通讯。
- 4)STUN Server收到请求信息后,向A和B发送对方的NAT映射地址。
- 5)Client B接收到A的外部地址后,将A的外部地址作为目的地址发送Hole Punching UDP数据报,该数据报使得B端网络的NAT设备允许后续的以A端地址为源地址的UDP数据报进入其内部网络。
- 6)Client A接收到B的外部地址后,以B的外部地址为目的发送探测UDP数据报,同样该数据报也在A端网络的NAT设备上建立对应映射。
- 7)Client B收到Client A的探测数据报后,向A端发送确认数据报。至此,双方建立互通的UDP连接。
3、用于NAT穿越的TURN协议
3.1、TURN协议介绍
TURN,在RFC5766中定义,英文全称Traversal Using Relays around NAT(TURN):Relay Extensions to Session Traversal Utilities for NAT(STUN),即使用中继穿透NAT:STUN的中继扩展。简单的说,TURN与STUN的共同点都是通过修改应用层中的私网地址达到NAT穿透的效果,异同点是TURN是通过两方通讯的“中间人”方式实现穿透。
TURN方式解决NAT问题的思路与STUN相似,也是基于私网接入用户通过某种机制预先得到其私有地址对应在公网的地址(STUN方式得到的地址为出口NAT上的地址,TURN方式得到地址为TURN Server上的地址),然后在报文负载中所描述的地址信息直接填写该公网地址的方式,实际应用原理也是一样的。具体协议内容可以参考RFC5766。
3.2、TURN协议的实现过程
如上图所示,假设Client A在私网,TURN server在公网,Peer A在另外一个私网,下面大概讲述一下Client A与Peer A的通信过程:
- 1)Client A向TURN server发送Allocate request,server收到请求后,如果校验不通过,则返回401错误,如果通过,则创建一个ALLOCATION,并给Client A返回其在NAT上的地址,以及TURN server分发地址。
- 2)Client A向TURN server发送CreatePermission请求,请求创建一个与Peer A通信的许可。TURN server收到请求后创建这个许可,并且告知client A创建成功。
- 3)Client A向TURN server通过Send Indication命令发送数据。
- 4)Server收到之后解析数据,然后把数据转发给Peer A。Peer A可以向TURN server回复其数据,TURN server收到回复之后转发给Client A。
4、ICE穿越技术
4.1、ICE介绍
ICE的全称Interactive Connectivity Establishment(互动式连接建立),由IETF的MMUSIC工作组开发出来的,它所提供的是一种框架,使各种NAT穿透技术可以实现统一。ICE跟STUN和TURN不一样,ICE不是一种协议,而是一个框架(Framework),它整合了STUN和TURN。可参考RFC5245。
4.2、ICE实现过程
如上图所示,假设通信双方同时处于对称式NAT内部,现在SIP终端A要与B进行VoIP通信。A所在的内部地址是10.0.1.9,外部地址是211.35.29.30;B的内部地址是192.168.1.6,外部地址是202.205.80.130;STUN/TURN服务器的地址是218.65.228.110。
**第1步:收集候选的传输地址**。首先A发起对话请求,进行地址收集。这些地址包括:
1)直接依附于网络接口的地址(本地传输地址);
2)服务器反向候选地址(NAT映射公网地址);
3)中继地址(TURN服务器中继地址)。
A的地址搜集过程:
** 第2步:启动STUN**。会话发起者获得一组传输地址后,将在本地传输地址启动STUN服务器,这意味着发送到来源地址的STUN服务将是可达的。
** 第3步:确定传输地址的优先级**。本地传输地址>NAT映射公网地址>TURN服务器中继地址。
** 第4步:构建初始化信息(Initiate Message)**。A地址收集后,生成初始化信息。初始化消息由一系列媒体流组成,每个媒体流都有一个缺省地址和候选地址列表。缺省地址通常被Initiate消息映射到SIP信令消息传递地址上,而候选地址列表用于提供一些额外的地址。
对于每个媒体流来说,任意Peer之间实现最大连通可能性的传输地址是由公网上转发服务器(如TURN)提供的地址,通常这也是优先级最低的传输地址。客户端将可用的传输地址编成一个候选地址列表(包括一个缺省地址),并且为每个候选元素分配一个会话中唯一的标识符。该标识符以及上述的优先级都被编码在候选元素的id属性中。一旦初始化信息生成后即可被发送。初始化消息如下:
v=0
o=Dodo 2890844730 2890844731 IN IP4 host.example.com
s=
c=IN IP4 218.65.228.110
t=0 0
m=audio 8076 RTP/AVP 0
a=alt:1 1.0 : user 9kksj== 10.0.1.9 1010
a=alt:2 0.8 : user1 9kksk== 211.35.29.30 9988
a=alt:3 0.4 : user2 9kksl== 218.65.228.110 8076
** 第5步:响应处理。**包括地址收集和连通性检查。B收到初始化信息Initiate Message后,先做同样的地址收集过程,B地址收集过程如下:
然后进行连通性检测。
** 第6步:连通性检测**。连通性检查的基本原则是:
1)按照优先顺序对候选传输地址进行排序;
2)利用每一个候选地址对发送一个检查包;
3)从接收方收到肯定的应答检查。
B的连通性检测:
完成连通性检测后,B产生应答消息,其中包括B的三个候选地址(前三条)和B—>A可联通的地址(第四条,称之为到B的peer-derived地址),如下:
v=0
o= Vincent 2890844730 289084871 IN IP4 host2.example.com
s=
c=IN IP4 218.65.228.110
t=0 0
m=audio 8078 RTP/AVP 0
a=alt:4 1.0 : peer as88jl 192.168.1.6 23766
a=alt:5 0.8 : peer1 as88kl 202.205.80.130 10892
a=alt:6 0.4 : peer2 as88ll 218.65.228.110 8078
a=alt:7 0.4 3 peer3 as88ml 218.65.228.110 5556
A收到应答消息后开始类似B的连通性检测。A的连通性检测:
同B的连通性检测类似,对于B的私有地址和STUN映射公网地址的连通性检查结果都失败,而B的TURN中继地址和到B的peer-derived地址成功(本例中它们都具有相同的优先级0.4)成功。相同优先级下我们通常采用peer-derived地址,所以A发送到B的媒体流将使用218.65.228.110:5556地址,而B到A的媒体流将发送至218.65.228.110:8076地址。
** 第7步:优化的连通性检测方案**。从步骤5开始,B收到初始化信息Initiate Message后,先做同样的地址收集过程,然后把地址作为应答消息发送给A。这样A就有了B的地址,B也有了A的地址。A收到B的应答之后,开始连通性检测。步骤同上图,不一样的是,在第7条消息之后,B收到A的检测消息,先做消息8的应答,然后用被检测的地址(192.168.1.6:23766)向对端(218.65.228.110:5566)发送检测请求,如果同样能够得到应答,则说明这对地址是有效的,可用于媒体传输。这个过程也称之为四次握手:当通过地址对中的本地地址向地址对中远程地址发送一个STUN请求,并成功收到STUN响应,称该地址对是可接收的;当地址对中的本地地址收到地址对中远程地址的一个STUN请求,并成功地响应,则称该地址对为可发送的。若一个地址对是可接收的,同时又是可发送的,则称该地址对是有效的,即通过连通性检查。
版权归原作者 dvlinker 所有, 如有侵权,请联系我们删除。