p2p小结(三):NAT穿越

目前的NAT存在如下事实:

  • NAT所认可的连接只能由NAT以内的主机主动发起(即:当且仅当内部主机向外发包时NAT才会建立session记录),外部的连接请求将被拒绝,这里的“连接”是个泛指,建立UDP通信也是建立“连接”

  • 转换后的公有IP和端口号只有NAT自己知道,NAT内的相应主机对此一无所知

  • NAT工作在应用层以下,无法对应用层中携带的地址信息进行识别和转换

  • NAT有多种类型,不同类型的NAT对外来数据包提出了不同的约束规则,不符合规则的外来数据包将会被丢弃

NAT的这些特性为p2p应用或基于IP的语音和视频应用带来了巨大障碍,用技术手段越过这些障碍即所谓的“NAT穿越”,其目标就是解决下面几个问题:

  • NAT外部发起的连接请求如何到达内部主机:即使已明确知道内部主机对应的公有IP及端口号,处于NAT外部的主机也是无法直接连接到该内部主机的,而且,就算由于NAT内部主机的主动行为导致NAT中建立了session记录,这个外部的主机也未必能顺利连接到该内部主机,因为某些类型的NAT会对外来的数据包做进一步的约束,如:地址限制型Cone NAT就比FullCone NAT多了对外来数据包的源IP地址的限制,不符合条件的数据包将被丢弃。

  • 如何避免应用层携带的地址信息使用私有地址:基于IP的语音和视频协议,如:SIPMGCPH.248H.323等,都是双通道(控制通道,媒体通道)工作模式,会话过程中,会要求主机在应用协议中写入自己的公有IP和端口号,发送给对端,而该主机并不知道这些信息,就只能填写自己的私有IP和端口号。NAT虽然知道,但却不支持对应用层地址信息的转换,其结果就是对端主机拿到了该主机的私有IP地址及端口号,对这个私有地址建立媒体通道显然不会成功。

IETF的主张是利用IPv6技术来解决IPv4地址耗尽的问题,因此,其未对NAT及其穿越技术进行系统的标准化。这也就导致了多种技术的产生,没有一种技术适用于所有问题场景,实际的解决方案通常是多种技术搭配使用。下面总结了常见的穿越技术:

  • ALG:Application-level Gateway,应用层网关,通常内置于NAT设备中,它将NAT的工作范围扩展到了应用层。当数据包外出时,它会识别特定的应用层协议,会根据应用层负载的IP和端口创建新的session,同时转换负载中的IP和端口号,ALG保证了那些存在于特定应用消息中的通信地址的可用性,典型的应用是NAT网络环境下的FTP通信。ALG可以理解为是专门为了配合像FTP这样的已被广泛使用(FTP先于NAT被广泛使用)的应用层协议在NAT环境下工作而存在的一种方案,它服务于特定的应用层协议,ALG支持哪些应用协议是由NAT设备厂商定义的。

  • MIDCOMMiddlebox Communications,中间盒通信。MIDCOM是IETF标准协议,它的思路是将中间盒设备(NAT,防火墙等)上处理应用层协议的逻辑(ALG干的那些事情)抽离出来,单独放到一个可信的第三方实体“MIDCOM代理”中去,MIDCOM代理与中间盒之间用MIDCOM协议进行通信。这种方式简化了中间盒的设计和维护,减轻了中间盒设备的压力(解析应用层协议的开销很大),具有很强的扩展性,如果需要支持新的应用协议,只要升级MIDCOM代理即可。不过,要想使用这个方案的话,现有的中间盒设备必须增加对MIDCOM协议的支持才行。

  • STUN:STUN是IETF标准协议,对于它的定义有两个,早期的RFC3489中将其定义为Simple Traversal of UDP Through NATs,即:UDP对NAT的简单穿越,它的目标是要成为一套独立的穿越NAT的解决方案。其思路就是,增加一个STUN服务器,NAT内部主机使用STUN协议与这个服务器通信,服务器会在其返回的STUN消息中给出该内不主机的公有IP,端口号以及NAT类型等信息。经过这样一个过程,一方面这个内部主机拿到了关键信息,另一方面在NAT上建立了一个主机-服务器的session,外部主机可以利用这个session与内部主机通信。后面的工作就看业务需要了,这个主机可以将自己的关键信息告知业务服务器,业务服务器可以将其转发给想要连接这个主机的其他主机。或者,如果处理的是FTP通信,那么这个内部主机完全可以自己给出公有IP端口号信息,而不用依赖ALG或者MIDCOM了。这是一个简单高效的方案,不过,由于是基于内部主机与服务器之间的session完成穿越,这种方式只适用于约束不高的NAT,遇到带端口限制的圆锥形NAT和对称形NAT就无效了。也就是说STUN实际上只适用于NAT的一个子集,在后来的RFC5389中,重新将STUN定义为Session Traversal Utilities for NAT,即:NAT session穿越工具,它不再是一套独立的解决方案,而是作为其它方案的基本组成部分而存在。

  • TURN:Traversal Using Relays around NAT,即:使用中继方式的NAT穿越。在RFC5766中被定义,它是对STUN的扩展,基础结构与STUN一样,STUN的工作受限于带端口限制的锥形NAT对称形NAT,而且只支持UDP协议,TURN可以解决这些问题。办法就是:当NAT内部的主机向TURN服务器查询自己的公有IP,端口号时,服务器所给出的将不再是NAT产生的IP和端口号,而是服务器自己的公有IP,以及由它来分配的一个端口号,后续的工作就与STUN的类似了,这样做的效果就是,NAT外部的那个主机会主动连接到这台TURN服务器上,后续的网络流量都经由这台服务器转发到NAT内的主机,这样做就不会存在STUN中出现的问题了,不过,与主机间直连比起来,这显然是一种低效的方案。实际情况是STUN与TURN混合使用,若STUN无效,就使用TURN进行中继。

  • ICE:Interactive Connectivity Establishment,即:交互式连通建立方式,是由IETFMMUSIC工作组开发的一种综合性的NAT穿越方式,详细见RFC5242,整合了STUN、TURN等技术,支持对各种类型NAT的穿越,如果要基于ICE方法进行穿越,需要相关的终端都支持ICE方法,同时,由于ICE功能强大,其实现的复杂度也不可避免的高出许多。不过已有现成的开源实现可以参考:PJNATH(STUN,TURN,ICE库),libnice(GLib ICE库)。

  • Full Proxy:完全代理方式,这种方式与TURN不同之处在于,TURN只对数据流做中继,而完全代理的方式下,控制流和数据流都由代理服务器进行中继,另外,使用这种方式,应用程序不需要再提供对STUN或TURN协议的支持。与TURN一样,负责中继的服务器将成为系统的瓶颈所在。

  • UPnP IGDUPnP是Universal Plug and Play的缩写,即:通用即插即用,是1999年以来微软推出的一种网络规范,该规范在2007年成为ISO标准,它由非盈利机构:UPnP论坛全权负责。其设计目标是在零配置的前提下实现网络设备间的自动发现,服务自动控制等功能。IGD是Internet Gateway Device的缩写,即:Internet网关设备,符合UPnP IGD规范的网关设备就是IGD,它能被UPnP网络中的“控制点”(另一个UPnP设备)识别,并为该“控制点”提供查询,增加,删除端口映射已经查询公有IP的服务。正是由于IGD提供的这些服务,基于UPnP IGD的穿越方案才得以实施,其原理就是:NAT内部的主机向NAT设备发起添加端口映射的命令(相当于手工添加),成功添加后,外部的主机就可以向这个端口发起连接请求了。要使用UPnP的方式来完成NAT穿越有三个必要条件:1.操作系统支持UPnP(Windows已提供支持);2.应用程序支持UPnP;3.NAT支持UPnP(绝大多数NAT设备都已支持)。

  • Hole punching:打洞是一种能让两个分别处于NAT设备之后的两台主机直接建立连接的技术,打洞的过程,可以理解为是NAT建立一个session的过程。这种技术的实施依赖于一个处于公网的服务器,需要建立连接的两台主机都要先与这个服务器建立通信,整个过程由这个服务器辅助完成。其原理简单地说就是各NAT后的主机通过服务器拿到对方的公有IP和端口号,然后主动向对方发送数据包,这样就能致使NAT建立了相应的session,扫除了通信障碍。当然,实际的情况要复杂一些,基于TCP协议的打洞以及当主机处于对称式NAT后时的打洞会比较难处理。其实STUN所使用的就是基于UDP的打洞,不过它只适用于几乎没有什么约束的完全锥形NAT,其它更复杂的情况没做考虑。

这些NAT穿越技术中ALGMIDCOM是在设备上做文章,将关键的工作交由设备来完成,简化了应用程序的开发,它们主要用来满足像FTP,SIP这类业务需要在控制流中传递IP和端口号的需求。STUNTURNICE是层层递进的,ICE综合利用了前两者,他们不依赖设备特性,关键工作转移到应用程序(包括服务端程序)身上,因此这种方式程序的编码复杂度比较高。Full Proxy是干脆用了代理服务器,避开了NATUPnP IGD是利用了设备提供的服务,这种方式方式完全依赖于操作系统和NAT设备,好在目前主流的操作系统和NAT设备都是支持UPnP的,同时,UPnP有统一标准,实现相应的应用程序并不困难。最后的Hole punching是一种不依赖设备的,灵活有效的技术,广泛应用在p2p、VoIP等应用中。

NAT的具体行为并未被标准化,不同厂商的NAT设备,其行为各异,没有一种穿越技术适用于所有网络环境。


References:


Prev-p2p小结(二):NAT
Next-p2p小结(四):TCP打洞