NAT Check
Version 3, with TCP Support!
检查你的NAT (Network Address Translator) 和p2p协议的兼容性
NAT Check by
Bryan Ford
, web magic by
Dave Andersen
Hosted by
the MIDCOM-P2P project
on
SourceForge
P2P协议的实现在当前IPV4环境下,就技术上来讲,更重要的是如何穿越NAT以及保证连接的稳定性能。有必要先澄清几个概念。
Firewall, NAT, Loopback tanslation (参考
http://blog.csdn.net/hxhbluestar/archive/2004/11/11/177793.aspx
)
NAT Check是这样的一个小程序,它可以自动检测你的NAT对P2P协议的支持程度,version 3版本可以检测以下功能:
Version 3, with TCP Support!
检查你的NAT (Network Address Translator) 和p2p协议的兼容性
NAT Check by
Bryan Ford
, web magic by
Dave Andersen
Hosted by
the MIDCOM-P2P project
on
SourceForge
P2P协议的实现在当前IPV4环境下,就技术上来讲,更重要的是如何穿越NAT以及保证连接的稳定性能。有必要先澄清几个概念。
Firewall, NAT, Loopback tanslation (参考
http://blog.csdn.net/hxhbluestar/archive/2004/11/11/177793.aspx
)
NAT Check是这样的一个小程序,它可以自动检测你的NAT对P2P协议的支持程度,version 3版本可以检测以下功能:
- TCP/UDP consistent translation
- TCP simultaneous open
- TCP/UDP loopback translation
- TCP unsolicited connections filtered
- UDP unsolicited messages filtered
你可以在下载、编译运行这个C程序:
natcheck.c
(如果是64位电脑,可以在添加编译参数"-DHAVE_STDINT"或者直接修改程序的#define)
如果你想在Windows平台上运行NAT Check, 首先安装Windows上的GCC环境
MinGW
,然后使用-lws2_32编译选项编译即可)
Technical Explanation这个程序使用的技术相当简单,并且已经被许多在线游戏和其它p2p应用广泛地使用。你可以在
here
和
here
查看以前的讨论。
The Technique假
定通讯中的三台机器A,B,C。主机A是“well-known" intenet
server,有固定的IP地址,它充当B和C通讯的”介绍人“角色。B和C都在NAT(可能是同一个NAT)的后面,都只有私网地址。其中B希望能通过
A的帮助,和C建立直接的p2p连接。为了发起一个到C的p2p连接,B首先向A发送一条消息(UDP
包,内容包含请求命令,B自己的本地地址和udp端口),请求”介绍“C。
A将C的真实IP和udp端口(也就是私网IP和端口)以及由A观察IP和端口(C经过NAT转换后的公网IP和端口)回复给B,同时A将B的这一对”地
址/端口"信息发送给C。(这里隐含C立刻向A发送udp响应的需求,否则,因为nat上的session过期,A无法得知C的正确的公网端口)现在B和C双方都知道建立一个p2p连接的需求,并且知道对方的公网地址/端口和本地地址/端口。双发尝试直接向对方发送udp包。如果两台机器正好在一个NAT后,则两者汇报的公网IP应该是相同的,这时B和C可以根据内网的地址/端口建立直接的连接。 大部分情况下,B和C在不同的子网内,他们各自的内网地址/端口是没有意义的。这时候,B和C需要向对方的公网地址/端口发送udp请求(此时,他们各自使用的本地udp端口应该还是他们向A发送udp消息时的同一端口,这样,nat-cone nat-才会复用公网端口,并发起一个新的session),现在两个nat上都有目的ip/port是对方的udp连接session, 所以这时候到达的udp包不会被过滤。因为发起连接有先后,所以,最初的几个到达对方nat的udp包会因为目标地址/端口不一致而被过滤。一旦双方的nat上都开启了新的session(称为hole)后,udp包将畅通无阻,这样,B和C之间的p2p连接就建立起来了。 Required NAT Behavior以
上技术的实现,有个重要的前提,那就是,NATS必须满足一个条件:对于每一对内部IP/Port(UDP),NAT只分配唯一的公网
IP/Port,而不是给每一个新的udp
session分配新的udp公网端口。NAT上session是由源地址/端口对和目标地址/端口对两部分定义的。如果两个udp包的这两部分相同,那
么NAT认为它们是一个session的,就会放行,否则会被过滤。RFC 3022
explicitly allows and suggests that NATs behave in the former,
"desirable" fashion, by maintaining a single (public IP, public port)
mapping for a given (internal IP, internal port) combination
independent of the number of active sessions involving this mapping.
这种behavior不仅有益于UDP应用的兼容,而且有利于NAT节省宝贵的公网端口地址。因为在session级上一样可以过滤进来的包,所以也不存
在安全性方面的问题。NAT不采用此behavior的唯一考虑估计是为了省事,毕竟,新来一个session就新开一个端口在技术实现上要简单的多。
不幸的是,RFC 3022 does not require NATs to implement the desirable behavior。写这个小程序的一个目的也就是想知道现在的internet上到底有多少NATs是支持这种behavior的。 你可以将测试结果
提交到这里
,或者
查看累计结果
。 Changes in Version 2Version 2 of NAT Check contains the following enhancements:- 不
再尝试猜测nat的类型,基本NAT还是NATP。因为大部分NATP会在绑定公私网端口的时候,首选相同的端口,这在表现形式上是和基本NAT是一样
的。NAT Check碰到这种情况,就会误以为此NAT是Basic类型的。唯一的方法是在同一私网内的两台机器上同时运行NAT Check。 - 可以测试NAT的一个特性: 回环转换(loopback translation, 是原文作者自己起的名称). 如果NAT支持回环转换,表示一台主机可以通过NAT赋予的公网地址和端口访问位于同一NAT后的私有网域中的另外一台主机。大部分的NAT可能还不支持这个功能,不过,它将会变得越来越重要,因为许多P2P客户端位于自己的NAT和ISP配置的公用NAT之后。(Twice-NAT) [注:此处Twice-NAT术语来自于natcheck.c,"BAD for P2P over Twice-NAT", 当NAT不支持loopback translation时,p2p over Twice-NAT会有问题。据我的理解,Twice-NAT指两层NAT,而不是平常所说的Twice NAT,后者是NAT的一种新特性,可以同时更改IP包的源地址(端口)和目的地址(端口),解决nat内的IP地址和外部IP地址重叠的问题(IP overlapping)]
- NAT Check 的命令行选项"-v", 打开它,你就鞥在测试过程中看到详细的反馈信息。
natcheck.c
本质上来讲,只是"ping" 两个不同的位于Internet上的服务器的众所周知的udp端口。这两台服务器都运行同样的程序
natserver.c
. 另外,还有第三台运行
natbouncer.c
的"conspiring"服务器。前面的两台服务器只要收到udp请求,除了直接回复客户程序外,还会向第三台服务器发送一份,而这第三台服务器会将这
个包回复给那个客户端,这个由第三台服务器发送的包不是客户端所期望的,属于“对方主动发起的”("unsolicited")。这个"bounce"的
过程主要是测试NAT的安全性能,看它是否过滤这些"unsolicited"的包。
natcheck.c
会绑定同一本地端口向前两台公网服务器同时发送一些udp包,根据判断两台服务器的回复包中报告的客户端公网地址/端口是否相同来判定此NAT是否实现了
上面所说的"desirable
behavior",也就是同一内部ip/port发起的多个session只共享映射到nat上的一个公网ip/port对。
Related Links
Dan Kegel's NAT/P2P page
IETF MIDCOM working group
nat-peer-games group on Yahoo!
P2P area at the Global Grid Forum
NAT/firewall page at the P2P working group page
(inactive)
防火墙 (Firewall)
防火墙限制了私网与公网的通信,它主要是将(防火墙)认为未经授权的的包丢弃,防火墙只是检验包的数据,并不修改数据包中的IP地址和TCP/UDP端口信息。
网络地址转换(NAT)
当有数据包通过时,网络地址转换器不仅检查包的信息,还要将包头中的IP地址和端口信息进行修改。以使得处于NAT之后的机器共享几个仅有的公网IP地址(通常是一个)。网络地址转换器主要有两种类型:
- 不
- 基础NAT (Basic NAT) :基础NAT 将私网主机的私有IP地址转换成公网IP地址,但并不将TCP/UDP端口信息进行转换。基础NAT一般用在当NAT拥有很多公网IP地址的时候,它将公网IP地址与内部主机进行绑定,使得外部可以用公网IP地址访问内部主机。
- 网络地址和端口转换 (Network Address/Port Translator NAPT):这是最普遍的情况,网络地址/端口转换器检查、修改包的IP地址和TCP/UDP端口信息,这样,更多的内部主机就可以同时使用一个公网IP地址。请
参考[NAT-TRAD]和[NAT-TERM]两个文档了解更多的NAT分类和术语信息。另外,关于NAPT的分类和术语,[STUN]在最近做了更多
的定义。当一个内部网主机通过NAT打开一个“外出”的TCP或UDP会话时,NAPT分配给这个会话一个公网IP和端口,用来接收外网的响应的数据包,
并经过转换通知内部网的主机。这样做的效果是,NAPT在 [私有IP:私有端口] 和[公网IP:公网端口]之间建立了一个端口绑定。
端口绑定指定了NAPT将在这个会话的生存期内进行地址转换任务。这中间存在一个这样的问题,如果P2P应用程序从内部网络的一个[私有IP地址:端口]对同时发出多条会话给不同的外网主机,那么NAT会怎样处理呢?请看以下几种方案。
- 锥形NAT (Cone NAT) :当建立了一个 [私有IP:端口]-[公网IP:端口] 端口绑定之后,对于来自同一个[私有IP:端口]会话,锥形NAT服务器允许发起会话的应用程序 重复使用这个端口绑定,一直到这个会话结束才解除(端口绑定)。
- 对称NAT (Symmetric NAT) :对称NAT,与Cone NAT是大不相同的,并不对会话进行端口绑定,而是分配一个全新的 公网端口 给每一个新的会话。(因为很难正确得知这个新分配的公网端口的具体数值,本文谈及的p2p udp hole punch技术并不适用于这种nat。事实上,对称nat已不多见)
当NAT的私网内部机器想通过公共地址来访问同一台局域网内的机器的时,NAT设备等价于做了两次NAT的事情,在包到达目标机器之前,先将私有地址转换为公网地址,然后再将公网地址转换回私有地址。我们把具有上叙转换功能的NAT设备叫做“回环转换”设备。
更多内容,可以技术细节可参考
http://midcom-p2p.sourceforge.net/draft-ford-midcom-p2p-01.txt
本文来自ChinaUnix博客,如果查看原文请点:http://blog.chinaunix.net/u1/43206/showart_482889.html