NAT(Network Address Translation)的相关术语及作用在这里不再赘述,网友如果需要可以参考文献:Peer-to-Peer Communication Across Network Address Translators。
原文地址:http://www.bford.info/pub/net/p2pnat
中文翻译(翻译后名为:穿越NAT的P2P通信方法的研究):http://www.ppcn.net/n4690c38.aspx
(注:中文资料翻译了原文的四章内容,翻译的很好,在此对这位同僚的辛勤工作表示由衷的感谢)
(另外还必须说明的一点是:本文是我在学习《P2P的NAT研究》时写的,可以说是它的另一个版本,这样做仅仅为了加深自己对该技术的理解,做一个摘记,无意冒犯)
一 NAT的类型
NAT可以分为很多种,但是最为普遍的是传统NAT,或者称为向外NAT。向外NAT在默认情况下只允许向外的Session穿越NAT,这就是我们最为常见的情况。
这种向外NAT又可以分为基本NAT(Basic NAT)和NAPT(Network Address/Port Translation)。
1. 基本NAT
基本NAT只转换IP地址,而不转换端口。一个基本NAT往往需要具有多个公网IP来满足多个内网节点中具有相同端口的应用程序的同时访问。由于这种类型的NAT设备限制大,现在已不常见。
2. NAPT
(注:Endpoint表示一个IP地址和端口对)
与基本NAT只转换IP地址不同,NAPT转换整个Endpoint。由于NAPT允许内网内的多个节点通过共享的方式使用同一个IP地址,因此,如今NAPT类型的NAT设备已经越来越多。
NAPT又可以进一步分为以下四种类型:
(1) 完全锥型NAT(FULL CONE NAT)
完全锥型NAT在内网用户A(Private Endpoint)首次向外部主机发送数据包时创建地址映射会话,并为A分配一个公网地址和端口(Public Endpoint),以后任何A向外部发送的数据都将使用这个Public Endpoint。此后,任何外部主机想要与A通信,只要将数据包发送到Public Endpoint上,A就能够顺利的进行接收。
(2) 限制锥型NAT (RESTRICT CONE NAT)
限制锥型NAT在内网用户A(Private Endpoint)首次向外部主机发送数据包时创建地址映射会话,并为A分配一个公网地址和端口(Public Endpoint),以后任何A向外部发送的数据包都将使用这个Public Endpoint。此后,如果某个外部主机(Endpoint IP:PORT)想要与A通信,只要将数据包发送到Public Endpoint并且保证A曾用当前与NAT的会话向该外部主机的IP地址发送过数据,A就能够正常收到外部主机(Endpoint IP:PORT)发送来的数据包。
(3) 端口限制锥型NAT(PORT RESTRICT CONE NAT)
端口限制锥型在内网用户A(Private Endpoint)首次向外部主机发送数据包时创建地址映射会话,并为A分配一个公网地址和端口(Public Endpoint),以后任何A向外部发送的数据都将使用这个Public Endpoint。此后,如果某个外部主机(Endpoint IP:PORT)想要与A通信,只要将数据包发送到Public Endpoint并且保证A曾用当前与NAT的会话向该外部主机的Endpoint发送过数据,A就能够正常收到外部主机(Endpoint IP:PORT)发送来的数据包。
(4) 对称型NAT(SYMMETRIC NAT)
对称型NAT是一种比较特殊的NAT。内网用户A(Private Endpoint)首次向外部主机S1发送数据包时创建地址映射会话Session1,并为A分配一个公网地址和端口(Public Endpoint1),以后A所有发向S1的数据包都使用这个Public Endpoint1。如果之后A用同一个Socket向外部主机S2发送数据包,这时对称型NAT又为其分配一个地址映射会话,并为A分配一个新的公网地址和端口对(Public Endpoint2),以后A所有发向S2的数据包都使用这个Public Endpoint2。对称型NAT规定Public Endpoint1和Public Endpoint2一定不相同。此外,如果任何外部主机想要发送数据给A,那么它首先应该收到A发给他的数据,然后才能往回发送,否则即使他知道内网主机的Public Endpoint也不能发送数据给A。这种NAT可以通过端口猜测等方法进行穿透,但是效果并不是很好,很难实现UDP-P2P通信。
图1 NAT 类型结构图
二 NAT类型的检测
前提条件:一个提供两个公网地址(通信地址分别设为:Endpoint1与Endpoint2)的服务器S进行UDP端口数据监听并根据客户的要求给出响应;待检测的用户可以正常进行UDP通信。
步骤1. 检测主机是否位于NAT后
为了检测IP地址是不是公网地址,主机A首先发送任意一个UDP数据包给服务器S(Endpoint1),S收到包之后,用Endpoint1将接收到数据包头的IP地址和端口打成一个UDP反馈包发送给用户A。A在收到反馈包之后,比较自身的Endpoint和反馈包中的Endpoint,如果一样则说明A不位于任何NAT之后,否则,就是位于NAT之后,这里并不能判断NAT的具体属于哪一种类型。
步骤2. 检测NAT是否是完全锥型
为了检测所处的NAT是否是完全锥型的,主机A向服务器S(Endpoint1)发送UDP数据包后,服务器用Endpoint2将接收到数据包头的IP地址和端口打成一个UDP反馈包发送给用户A。另外,A在发送UDP数据包后,立即开始端口侦听,设定一个等待时间上限,防止无限堵塞(因为接收是一个While循环)。这样进行若干次,如果A每次都没有收到数据包,说明A所处的NAT类型不是完全锥型的;相反,在这整个过程中只要收到一次服务的包,就说明A所处的NAT类型是完全限制型的。
步骤3. 检测NAT是否是对称型
为了检测所处的NAT是否是对称型的,主机A向服务器S(Endpoint1)发送UDP数据包,服务器S(Endpoint1)在收到数据包后,用Endpoint1将接收到数据包头的IP地址和端口打成一个UDP反馈包发送给用户A。另外,A在发送数据包后,开始侦听端口并接收数据,设定一个等待时间上限,防止无限堵塞(因为接收是一个While循环)。与此同时,主机A用同一个套接字向服务器S (Endpoint2)发送UDP数据,Endpoint2发送与上面类似的UDP回馈包。在A的整个数据接收过程中,如果收到的服务器反馈数据包中标识自身的IP地址和端口存在不相同的情况,就说明NAT是对称型的,否则就不是。
步骤4. 检测NAT是限制锥型的还是端口限制锥型
最后,为了检测所处的NAT是限制锥型的还是端口限制锥型的,主机A向服务S的Endpoint1发送UDP数据包,服务器用与Endpoint1相同的IP地址和不同的端号将带有A的Public Endpoint的UDP反馈包发送给A。另外,A在发送数据包后,立即侦听端口和并进行数据接收,设定一个等待时间上限,防止无限堵塞(因为接收是一个While循环)。重复若干次。如过在整个过程中,用户A收到S发来的数据包,就说明NAT是限制型的;否则就说明NAT是端口限制型的。