在现实Internet网络环境中,大多数计算机主机都位于防火墙或NAT之后,只有少部分主机能够直接接入Internet。很多时候,我们希望网络中 的两台主机能够直接进行通信(即所谓的P2P通信),而不需要其它公共服务器的中转。由于主机可能位于防火墙或NAT之后,在进行P2P通信之前,我们需 要进行检测以确认它们之间能否进行P2P通信以及如何通信。这种技术通常被称为NAT穿透(NAT Traversal)。最常见的NAT穿透是基于UDP的技术(如下面的RFC3489/STUN),也有基于TCP的穿透技术。NAT穿透技术最重要的 是识别目标主机的NAT类型,这也是本文所要介绍的内容。 RFC3489/STUN协议过程 STUN协议定义了三类测试过程来检测NAT类型,如下所述: Test1:STUN Client通过端口{IP-c1:Port-c1}向STUN Server{IP-s1:Port-s1}发送一个Binding Request(没有设置任何属性)。STUN Server收到该请求后,通过端口{IP-s1:Port-s1}把它所看到的STUN Client的IP和端口{IP-m1,Port-m1}作为Binding Response的内容回送给STUN Client。 Test1#2:STUN Client通过端口{IP-c1:Port-c1}向STUN Server{IP-s2:Port-s2}发送一个Binding Request(没有设置任何属性)。STUN Server收到该请求后,通过端口{IP-s2:Port-s2}把它所看到的STUN Client的IP和端口{IP-m1#2,Port-m1#2}作为Binding Response的内容回送给STUN Client。 Test2:STUN Client通过端口{IP-c1:Port-c1}向STUN Server{IP-s1:Port-s1}发送一个Binding Request(设置了Change IP和Change Port属性)。STUN Server收到该请求后,通过端口{IP-s2:Port-s2}把它所看到的STUN Client的IP和端口{IP-m2,Port-m2}作为Binding Response的内容回送给STUN Client Test3:STUN Client通过端口{IP-c1:Port-c1}向STUN Server{IP-s1:Port-s1}发送一个Binding Request(设置了Change Port属性)。STUN Server收到该请求后,通过端口{IP-s1:Port-s2}把它所看到的STUN Client的IP和端口{IP-m3,Port-m3}作为Binding Response的内容回送给STUN Client。 NAT类型检测过程如下(在RFC3489中或者在Wiki上http://zh.wikipedia.org/zh/STUN都可以找到流程图): 1. 进行Test1。如果STUN Client不能够收到STUN Server的应答(重复多次确认),那么说明该STUN Client是UDP Blocked类型(也有可能是STUN Server不可到达,这里不考虑这种情形);否则,STUN Client把返回的{IP-m1,Port-m1}和本地的{IP-c1:Port-c1}进行比较(只需要比较IP即可),如果相同,说明本机直接连 接于公网,否则本机位于NAT之后,但还需要进一步判断具体类型。 1.1. 如果本机直接连接于公网,进行Test2。如果STUN Client不能够收到STUN Server的应答(重复多次确认),那么说明该STUN Client是Symmetric Firewall类型;否则,该STUN Client是Open Internet类型。 1.2. 如果本机位于NAT之后,进行Test2。如果STUN Client能够收到STUN Server的应答,那么说明该STUN Client是Full Cone NAT;否则,需要进一步进行测试。 1.2.1. 进行Test1#2。STUN Client比较IP-m1和IP-m1#2是否相同,如果不相同,那么说明该STUN Client是Symmetric NAT类型;否则,需要进一步进行测试。 1.2.1.1 进行Test3。如果STUN Client能够收到STUN Server的应答,那么说明该STUN Client是Restricted Cone NAT类型;否则,该STUN Client是Port Restricted Cone NAT类型。 一些说明: 1. 只需要进行Test2,即可判断出是否为Open Internet或Full Cone Nat类型。 STUN实现 1.STUN Client and Server library( http://sourceforge.net/projects/stun/ ) 这个库实现了RFC3489中的STUN协议。其中,Client程序输出结果意义如下: (1)"Open"表示这里的Open Internet (2)"Independent Mapping, Independent Filter"表示这里的Full Cone NAT (3)"Independedt Mapping, Address Dependendent Filter"表示这里的Restricted Core NAT (4)"Indepndent Mapping, Port Dependent Filter"表示这里的Port Restricted Core NAT (5)"Dependent Mapping"表示这里的Symmetric NAT (6)"Firewall"表示这里的Symmetric Firewall (7)"Blocked or could not reach STUN server"表示这里的UDP Blocked 2. reTurn (http://www.resiprocate.org/ReTurn_Overview) 实现了RFC5389中的STUN协议和TURN协议。 网上一些可用STUN Server(注意:STUN协议指定默认端口为3478) stun01.sipphone.com stun.iptel.org stun.softjoys.com stun.xten.com(这个STUN Server的实现好像有问题,测试结果与前面三个不相同) 注解 [1] RFC3489中的STUN协议(Simple Traversal of UDP Through NATs)是一个完整的NAT穿透方案,但其修订版本(RFC5389)把STUN协议(Session Traversal Utilities for NAT)定位于为穿透NAT提供工具,并不提供一个完整的解决方案。此外,RFC3489只提供了UDP的NAT穿透,而RFC5389还支持TCP的穿 透)。 Reference 1.NAT穿透 (cr0_3) |