引言;本文的目的在于学习和了解 NAT 的基本知识,然后通过 P2P 组网
一、什么是NAT?
1、NAT 简介
NAT(Network Address Translation ,网络地址转换) 是一种广泛应用的解决IP
短缺的有效方法, NAT
将内网地址转和端口号换成合法的公网地址和端口号,建立一个会话,与公网主机进行通信。 NAT
不仅实现地址转换,同时还起到防火墙的作用,隐藏内部网络的拓扑结构,保护内部主机。 此外还完美地解决了 lP
地址不足的问题,而且还能够有效地避免来自网络外部的攻击,隐藏并保护网络内部的计算机。 这样对于外部主机来说,内部主机是不可见的。但是,对于P2P
应用来说,却要求能够建立端到端的连接,所以如何穿透NAT 也是P2P 技术中的一个关键。
1.1 为什么会有NAT
时光回到上个世纪80年代,当时的人们在设计网络地址的时候,觉得再怎么样也不会有超过32bits位长即2的32次幂台终端设备连入互联网,再加上增加ip的长度(即使是从4字节增到6字节)对当时设备的计算、存储、传输成本也是相当巨大的。后来逐渐发现IP地址不够用了,然后就NAT就诞生了!(虽然ipv6也是解决办法,但始终普及不开来,而且未来到底ipv6够不够用仍是未知)。
因此,NAT技术能够兴起的原因还是因为在我们国家公网IP地址太少了,不够用,所以才会采取这种地址转换的策略。可见,NAT的本质就是让一群机器公用同一个IP,这样就暂时解决了IP短缺的问题。
1.2 NAT有什么优缺点
优势其实上面已经刚刚讨论过了,根据定义,比较容易看出,NAT可以同时让多个计算机同时联网,并隐藏其内网IP,因此也增加了内网的网络安全性;此外,NAT对来自外部的数据查看其NAT映射记录,对没有相应记录的数据包进行拒绝,提高了网络安全性。
那么,NAT与此同时也带来一些弊端:首先是,NAT设备会对数据包进行编辑修改,这样就降低了发送数据的效率;此外,各种协议的应用各有不同,有的协议是无法通过NAT的(不能通过NAT的协议还是蛮多的),这就需要通过穿透技术来解决。我们后面会重点讨论穿透技术。
简单的背景了解过后,下面介绍下NAT实现的主要方式,以及NAT都有哪些类型。
2、NAT 分类
从表面上看有三种类型:静态 NAT 、动态地址 NAT 、地址端口转换 NAPT 。
2.1 静态NAT
静态地址转换将内部私网地址与合法公网地址进行一对一的转换,且每个内部地址的转换都是确定的。
内网IP | 外网IP |
---|---|
192.168.1.55 | 219.123.234.110 |
192.168.1.59 | 219.123.234.111 |
192.168.1.211 | 219.123.234.112 |
2.2 动态NAT
动态地址转换也是将内部本地地址与内部合法地址一对一的转换,但是动态地址转换是从合法地址池中动态选择一个未使用的地址来对内部私有地址进行转换。
内网IP | 资源池 | 外网IP |
---|---|---|
192.168.1.55 | 219.123.234 - 219.123.250 | 分配后 |
192.168.1.59 | 分配后 | |
192.168.1.211 | 分配后 |
2.3 NAPT
它也是一种动态转换,而且多个内部地址被转换成同一个合法公网地址,使用不同的端口号来区分不同的主机,不同的进程。
内网IP | 外网IP |
---|---|
192.168.1.55:8877 | 219.123.234.110:9200 |
192.168.1.59:6652 | 219.123.234.111:9201 |
192.168.1.211:1232 | 219.123.234.112:9202 |
通过上面实现方式的介绍,不难看出,现实环境中 NAPT 的应用显然是更广泛的,因此下面就重点介绍下 NAPT 的主要类型有哪些。
从实现的技术角度,又可以将 NAPT 分成如下几类:
对于NAPT
我们主要分为两大类:锥型NAT
和对称型NAT
。
其中锥型NAT又分:完全锥型,受限锥型和端口受限锥型。概括的说:对称型NAT是一个请求对应一个端口;锥型NAT(非对称NAT)是多个请求(外部发向内部)对应一个端口,只要源IP端口不变,无论发往的目的IP是否相同,在NAT上都映射为同一个端口,形象的看起来就像锥子一样,下面分别介绍这四种类型及其差异。
- 全锥 NAT(Full Cone NAT)
- 限制性锥 NAT (Restricted Cone NAT )
- 端口限制性锥 NAT( Port Restricted Cone NAT)
- 对称 NAT ( Symmetric NAT)
(1)全锥 NAT(Full Cone NAT)
全锥NAT 把所有来自相同内部IP 地址和端口的请求映射到相同的外部IP 地址和端口。任何一个外部主机均可通过该映射发送数据包到该内部主机。
特点:IP和端口都不受限
表现形式:将来自内部同一个IP地址同一个端口号(IP_IN_A : PORT_IN_A)的主机监听/请求,映射到公网IP某个端口(IP_OUT_B : PORT_OUT_B)的监听。任意外部IP地址与端口对其自己公网的IP这个映射后的端口访问(IP_OUT_B : PORT_OUT_B),都将重新定位到内部这个主机(IP_IN_A : PORT_IN_A)。该技术中,基于C/S架构的应用可以在任何一端发起连接。是不是很绕啊。再简单一点的说,就是,只要客户端,由内到外建立一个映射(NatIP:NatPort -> A:P1)之后,其他IP的主机B或端口A:P2都可以使用这个洞给客户端发送数据。
(2)受限锥型NAT(Restricted Cone NAT)
把所有来自相同内部IP 地址和端口的请求映射到相同的外部IP 地址和端,但是和全锥NAT 不同的是:只有当内部主机先给外部主机发送数据包, 该外部主机才能向该内部主机发送数据包。
特点:IP受限,端口不受限。
表现形式:与完全锥形NAT不同的是,在公网映射端口后,并不允许所有IP进行对于该端口的访问,要想通信必需内部主机对某个外部IP主机发起过连接,然后这个外部IP主机就可以与该内部主机通信了,但端口不做限制。举个栗子。当客户端由内到外建立映射(NatIP:NatPort –> A:P1),A机器可以使用他的其他端口(P2)主动连接客户端,但B机器则不被允许。因为IP受限啦,但是端口随便。见下图(绿色是允许通信,红色是禁止通信)
(3)端口受限型NAT(Port Restricted Cone NAT)
端口限制性锥NAT 与限制性锥NAT 类似, 只是多了端口号的限制, 即只有内部主机先向外部地址:端口号对发送数据包, 该外部主机才能使用特定的端口号向内部主机发送数据包。
特点:IP和端口都受限。
表现形式:该技术与受限锥形NAT相比更为严格。除具有受限锥形NAT特性,对于回复主机的端口也有要求。也就是说:只有当内部主机曾经发送过报文给外部主机(假设其IP地址为A且端口为P1)之后,外部主机才能以公网IP:PORT中的信息作为目标地址和目标端口,向内部主机发送UDP报文,同时,其请求报文的IP必须是A,端口必须为P1(使用IP地址为A,端口为P2,或者IP地址为B,端口为P1都将通信失败)。例子见下图。这一要求进一步强化了对外部报文请求来源的限制,从而较Restrictd Cone更具安全性。
(4) 对称 NAT ( Symmetric NAT)
对称NAT 与上述3 种类型都不同, 不管是全锥NAT ,限制性锥NAT 还是端口限制性锥NAT ,它们都属于锥NAT (Cone NAT )。当同一内部主机使用相同的端口与不同地址的外部主机进行通信时, 对称NAT 会重新建立一个Session ,为这个Session 分配不同的端口号,或许还会改变IP 地址。
特点:对每个外部主机或端口的会话都会映射为不同的端口(洞)
表现形式:只有来自同一内部IP:PORT、且针对同一目标IP:PORT的请求才被NAT转换至同一个公网(外部)IP:PORT,否则的话,NAT将为之分配一个新的外部(公网)IP:PORT。并且,只有曾经收到过内部主机请求的外部主机才能向内部主机发送数据包。内部主机用同一IP与同一端口与外部多IP通信。客户端想和服务器A(IP_A:PORT_A)建立连接,是通过NAT映射为NatIP:NatPortA来进行的。而客户端和服务器B(IP_B:PORT_B)建立连接,是通过NAT映射为NatIP:NatPortB来进行的。即同一个客户端和不同的目标IP:PORT通信,经过NAT映射后的公网IP:PORT是不同的。此时,如果B想要和客户端通信,也只能通过NatIP:NatPortB(也就是紫色的洞洞)来进行,而不能通过NatIP:NatPortA(也就是黄色的洞洞)
3、NAT路由类型判断
根据上面的介绍,我们可以了解到,在实际的网络情况中,各个设备所处的网络环境是不同的。那么,如果这些设备想要进行通信,首先判断出设备所处的网络类型就是非常重要的一步。举个例子来说:对于视频会议和VoIP软件,对位于不同NAT内部的主机通信需要靠服务器来转发完成,这样就会增加服务器的负担。
为了解决这种问题,要尽量使位于不同NAT内部的主机建立直接通信,其中,最重要的一点就是要判断出NAT的类型,然后才能根据NAT的类型,设计出直接通信方案。不然的话,两个都在NAT的终端怎么通信呢?我们不知道对方的内网IP,即使把消息发到对方的网关,然后呢?网关怎么知道这条消息给谁,而且谁允许网关这么做了?
为了解决这个问题,也就是处于内网的主机之间能够穿越它们之间的NAT建立直接通信,STUN(Session Traversal Utilities for NAT,NAT会话穿越应用程序)技术就是其中比较重要的一种解决方法,并得到了广泛的应用(PS:除此之外,还有UPNP技术,ALG应用层网关识别技术,SBC会话边界控制,ICE交互式连接建立,TURN中继NAT穿越技术等等,本文不一一做介绍) 对于 STUN 这部分内容在本文最后的延伸阅读里,篇幅较长,有兴趣的可以阅读。
测试工具
NatTypeTester (NAT路由类型检测工具)是一款帮助用户检测NAT路由类型的工具,打开即可使用,非常方便。NAT类型会影响我们平时使用网络的情况,如果不清楚自己路由的NAT的话,就用这个工具来试试吧。工具下载
RFC支持
RFC 3489
RFC 5389
RFC 5769
RFC 5780
RFC 7350
RFC 7443
RFC 7635
RFC 8489
互联网协议
IPv4
IPv6
传输协议
UDP
TCP
TLS-over-TCP
DTLS-over-UDP
增加 SOCKS5 支持
4、P2P网络
p2p网络,即对等计算机网络,是一种在对等者(Peer)之间分配任务和工作负载的分布式应用架构,是对等计算模型在应用层形成的一种组网或网络形式。网络的参与者共享他们所拥有的一部分硬件资源(处理能力、存储能力、网络连接能力、打印机等),这些共享资源通过网络提供服务和内容,能被其它对等节点(Peer)直接访问而无需经过中间实体。在此网络中的参与者既是资源、服务和内容的提供者(Server),又是资源、服务和内容的获取者(Client)。
在P2P网络环境中,彼此连接的多台计算机之间都处于对等的地位,各台计算机有相同的功能,无主从之分,一台计算机既可作为服务器,设定共享资源供网络中其他计算机所使用,又可以作为工作站,整个网络一般来说不依赖专用的集中服务器,也没有专用的工作站。网络中的每一台计算机既能充当网络服务的请求者,又对其它计算机的请求做出响应,提供资源、服务和内容。通常这些资源和服务包括:信息的共享和交换、计算资源(如CPU计算能力共享)、存储共享(如缓存和磁盘空间的使用)、网络共享、打印机共享等
P2P网络技术的特点体现在以下几个方面:
非中心化:网络中的资源和服务分散在所有节点上,信息的传输和服务的实现都直接在节点之间进行,可以无需中间环节和服务器的介入,避免了可能的瓶颈。P2P的非中心化基本特点,带来了其在可扩展性、健壮性等方面的优势。
可扩展性:在P2P网络中,随着用户的加入,不仅服务的需求增加了,系统整体的资源和服务能力也在同步地扩充,始终能比较容易地满足用户的需要。理论上其可扩展性几乎可以认为是无限的。P2P网络加入的用户越多,P2P网络中提供的资源就越多,下载的速度反而越快。
健壮性:P2P架构天生具有耐攻击、高容错的优点。由于服务是分散在各个节点之间进行的,部分节点或网络遭到破坏对其它部分的影响很小。P2P网络一般在部分节点失效时能够自动调整整体拓扑,保持其它节点的连通性。P2P网络通常都是以自组织的方式建立起来的,并允许节点自由地加入和离开。
高性价比:性能优势是P2P被广泛关注的一个重要原因。随着硬件技术的发展,个人计算机的计算和存储能力以及网络带宽等性能依照摩尔定理高速增长。采用P2P架构可以有效地利用互联网中散布的大量普通结点,将计算任务或存储资料分布到所有节点上。利用其中闲置的计算能力或存储空间,达到高性能计算和海量存储的目的。目前,P2P在这方面的应用多在学术研究方面,一旦技术成熟,能够在工业领域推广,则可以为许多企业节省购买大型服务器的成本。
隐私保护:在P2P网络中,由于信息的传输分散在各节点之间进行而无需经过某个集中环节,用户的隐私信息被窃听和泄漏的可能性大大缩小。此外,目前解决Internet隐私问题主要采用中继转发的技术方法,从而将通信的参与者隐藏在众多的网络实体之中。在P2P中,所有参与者都可以提供中继转发的功能,因而大大提高了匿名通讯的灵活性和可靠性,能够为用户提供更好的隐私保护。
应用场景:
- 大流量传输,不经过服务器,直接点对点传输,速度取决本地网络宽带速度
- 远程局域网,提升网络环境
- 局域网文件共享
- 流媒体直播
所以要实现P2P的网络组建成功,本地环境下的 NAT 是有关键性的因素,下文主要讲解对于不同 NAT 下穿透的条件和成功率进行研究。
4.1 穿透条件
- 中间服务器保存信息、并能发出建立UDP隧道的命令
- 网关均要求为Cone NAT类型。Symmetric NAT不适合。
- 完全圆锥型网关可以无需建立udp隧道,但这种情况非常少,要求双方均为这种类型网关的更少。
- 假如X1网关为Symmetric NAT, Y1为Address Restricted Cone NAT 或Full Cone NAT型网关,各自建立隧道后,A1可通过X1发送数据报给Y1到B1(因为Y1最多只进行IP级别的甄别),但B2发送给X1的将会被丢弃(因为发送来的数据报中端口与X1上存在会话的端口不一致,虽然IP地址一致),所以同样没有什么意义。
- 假如双方均为Symmetric NAT的情形,新开了端口,对方可以在不知道的情况下尝试猜解,也可以达到目的,但这种情形成功率很低,且带来额外的系统开支,不是个好的解决办法。pwnat工具据说可以实现。
- 不同网关型设置的差异在于,对内会采用替换IP的方式、使用不同端口不同会话的方式,使用相同端口不同会话的方式;对外会采用什么都不限制、限制IP地址、限制IP地址及端口。
- 这里还没有考虑同一内网不同用户同时访问同一服务器的情形,如果此时网关采用AddressRestricted Cone NAT 或Full Cone NAT型,有可能导致不同用户客户端可收到别人的数据包,这显然是不合适的。
4.2 穿透流程
不同的网络拓扑 NAT 穿透的方法和流程有所区别,具体如下。
(1)同一个NAT设备下
- clinet A与Server S建立UDP连接,公共NAT(155.99.25.11)给client A分配一个公网端口62000;
- client B与Server S建立UDP连接,公共NAT(155.99.25.11)给client A分配一个公网端口62005;
- client A通过Server S发送一个消息要求连接client B,S给A回应B的公网和私网地址,并转发A的公网和私网地址给B;
- A和B根据获取的地址试图直接发送UDP数据报文;是否成功取决于NAT设备是否支持hairpin translation(端口回流)。——打开端口回流相当于与client A的数据经过NAT设备转发后才到达client B,即从外网NAT接口绕了一圈再访问到同一个子网里的client B。(优点是可以防止内部攻击)
(2)不同NAT设备下
- A使用4321端口与S连接,NAT给回话在NAT分配外网62000端口(155.99.25.11:62000)与S连接;同理B以相同的方式与S连接,分配的外网地址端口是138.76.29.7:31000。
- A往S注册消息包里包含里A的私有地址10.0.0.1:4321,此时S保存了A的地址;S给A临时分配了一个用于公网的地址(155.99.25.11:62000),同时用于观察外网数据包。
- 同理B往S注册的消息包里也包含里B的地址,NAT同样给B临时分类了一个外网地址(138.76.29.7:31000)
- Client A根据以上已知信息通过穿透的方式与B连接UDP通信:
- Client A发送请求消息,寻求连接B;
- S给A回应B的外网和内网地址,通给给B发送A的外网和内网地址;
A和B开始利用这些地址尝试直接发送UDP报文给彼此,不幸的是,此时A和B都无法接收对应的消息。因为A和B都是在不同的私有网络中,A和B之前都是与S通信回话,并没有与对方建立回话;即A没有为B打开一个洞,B也没有为A打开一个洞。这个过程的第一个报文需要会被拒绝同时打开对应的“洞”,随后才可以直接通信,具体如下:
1. A给B公网地址(10.0.0.1:4321 to 138.76.29.7:31000)发送的第一个报文,实际上是在A的NAT私有网络上“穿透”来为新识别的地址(10.0.0.1:4321 138.76.29.7:31000) 建立UDP会话,并经主网地址(155.99.25.11:62000 138.76.29.7:31000)来传送。
2. 如果A发送到B的公网地址的消息在B发送到A的第一个消息越过B自己的NAT之前到达B的NAT,那么B的NAT可能会将A的入站消息解释为非请求的传入通信量并丢弃它。
3. 同理,B给A公网地址方法的第一个消息也会在B的NAT上“穿透”来为地址(10.1.1.3:4321, 155.99.25.11:62000)建立回话。
4. 随后可以正常P2P通信。
(3)多层NAT下
说明:NAT C 是一个大型的工业NAT设备,由ISP(Internet Service Provider,互联网服务提供商)部署,用于将许多客户多路复用到几个公共IP地址上。
- Client A和client B无法通道NAT A和NAT A进行P2P通信,因为它们属于NAT C的局域网地址,因此client A和client B只能通道NAT C的hairpin translation进行P2P通信,如果NAT C不支持hairpin translation,则它们很难进行P2P通信。
- 每个客户机像前面方式一样启动到服务器S的连接,引起NAT A和B各自创建一个单独的公共/私有转化——session A-S(18.181.0.31:1234 10.0.0.1:4321)和session B-S(18.181.0.31:1234 10.1.1.3:4321),并引起NAT C为每个会话建立一个公共/私有翻译——session A-S(18.181.0.31:1234 10.0.1.1:45000)和session B-S(18.181.0.31:1234 10.0.1.2:5500)。
1. 首先client A给client B的公网地址(155.99.25.11:62005)发送消息;
2. NAT A翻译原数据报文从10.0.0.1:4321带10.0.0.1:45000;
3. 数据报现在到达NAT C,它识别出数据报的目标地址是NAT C自己翻译的公共地址之一;
4. 如果NAT C是好的,那么其能翻译出数据报文的源地址和目标地址(155.99.25.11:62000和10.0.1.2:55000)同时通过“回环”返回数据包到私有网络;
5. NAT B 翻译数据报文得到NAT B私网地址,最终到达client B。
6. Client B给client A发送数据报文与上述步骤类似。
4.3 NAT穿透成功率
不同的NAT组合穿透的方式也有所不同,有点可以穿透,有的则不能穿透,如两个都是对称型设备则无法实现穿透,不同组合穿透测试结果如下。
Peer A | Peer B | 是否可以穿透 |
---|---|---|
全锥型 | 全锥型 | 是 |
全锥型 | 受限锥型 | 是 |
全锥型 | 端口受限锥型 | 是 |
全锥型 | 对称型 | 是 |
受限锥型 | 受限锥型 | 是 |
受限锥型 | 端口受限锥型 | 是 |
受限锥型 | 对称型 | 是 |
端口受限锥型 | 端口受限锥型 | 是 |
端口受限锥型 | 对称型 | 否 |
对称型 | 对称型 | 否 |
5、ZeroTier-One
Zerotier 可以组建虚拟局域网,官方声称是P2P直连的。想要实现P2P访问必须先通过一个中介进行连接,官方的节点在网络高峰期不是很好使,并且根节点都在国外,所以最好自己找台国内服务器搭建moon节点,保证p2p的稳定性。Zerotier 怎么使用这里就不讲了,请自行百度,教学很多,这里只讲下moon节点的搭建和使用。
5.1 安装配置ZeroTier客户端
执行命令: curl -s https://install.zerotier.com/ | sudo bash
启动安装好的ZeroTier
执行命令:sudo systemctl start zerotier-one.service
执行命令:sudo systemctl enable zerotier-one.service
将安装好ZeroTier的加入你事先注册好的ZeroTier虚拟局域网中
执行命令:sudo zerotier-cli join NETWORK ID
此处的 NETWORK ID 请更改为你己的 ID
以上两个步骤如果成功会反馈如图
然后去zerotier管理页面,对加入的设备进行打钩,这样你的服务器就已经加入你的网络中了
5.2 搭建ZeroTier的Moon中转服务器,生成moon配置文件
执行命令:cd /var/lib/zerotier-one/
执行命令:sudo zerotier-idtool initmoon identity.public > moon.json
然后修改配置文件 moon.json
添加IP,IP是服务器的IP,9993 是 zerotier 的默认端口,服务器防火墙上需要开放 UDP:9993 ,否则是连接不上Moon
生成签名文件
执行命令:zerotier-idtool genmoon moon.json
执行之后会生产一个000000xxxx.moon的文件,将这个文件下载本地,xxxx是随机的,这个后面要用
将moon节点加入网络。创建moons.d文件夹,并把签名文件移动到文件夹内
执行命令:sudo mkdir moons.d
执行命令:sudo mv 000000448c38987b.moon moons.d/
此处的 000000448c38987b.moon 是上一步生成的文件名,改成你自己生成的文件名的,这里只是演示,不要无脑复制粘贴。
然后重启中转服务器的 zerotier-one
执行命令:sudo systemctl restart zerotier-one
到这里,服务器的moon就配置完成了。
对客户端安装zerotier后,将配置好的moon文件配置到客户端,并重启zerotier完成与moon的连接。
5.3 配置客户端
LINUX 下
使用之前步骤中 moon.json 文件中的 id 值 (10 位的字符串,就是xxxxxx),不知道的话在服务器上执行如下命令可以得到id。
执行命令:grep id /var/lib/zerotier-one/moon.json | head -n 1
然后在客户端机器里执行命令:
执行命令:zerotier-cli orbit ed2c88f24 ed2c88f24
此处的ed2c88f24刚刚在服务器得到的ID值
Windows下
打开服务程序 services.msc , 找到服务 "ZeroTier One" , 并且在属性内找到该服务可执行文件路径,并且在其下建立 moons.d 文件夹,然后将 moon 服务器下生成的 000xxxx.moon 文件,拷贝到此文件夹内.再重启服务
路径一般是 Windows: C:\ProgramData\ZeroTier\One
测试是否成功(客户端cmd管理员运行)若有出现服务器IP地址,即可证明moon连接成功
执行命令:zerotier-cli listpeers (下图就是链接成功到moon的样子,截图内创建了两个moon )
6、总结
连上节点的新设备去管理页面打勾就行了,我自己是建立了2个moon节点,一个在贵州,一个在南京,现在里面有差不多几十台设备,地域分布的很广,跨通4个省份,2个月的期间,也做了很久的穿透测试和观察,p2p的直连成功率大概是80%左右,ping 值一半小于30MS 就是穿透成功了的,大于就基本走的服务器中转了。 中转速度就看服务器的公网带宽了,设备在同一 NAT 下的穿透成功几乎100% ,跨域NAT的情况下,可以先用测试工具看看上面的 NAT 类型,可以估计是否能成功。ZeroTier 的功能还有很多,不止于用来组网,管理端还支持自定义路由,和网关,更多用法待测试后再补充,没测试过这里就不先瞎 BB了,误导人~
STUN协议 (延伸阅读)
STUN是一种网络协议,它允许位于NAT(或多重NAT)后的客户端找出自己的公网地址,查出自己位于哪种类型的NAT之后以及NAT为某一个本地端口所绑定的Internet端端口。这些信息被用来在两个同时处于NAT路由器之后的主机之间建立UDP通信。该协议由RFC 5389定义。STUN由三部分组成:STUN客户端、STUN服务器端、NAT路由器。STUN服务端部署在一台有着两个公网IP的服务器上。STUN客户端通过向服务器端发送不同的消息类型,根据服务器端不同的响应来做出相应的判断,一旦客户端得知了Internet端的UDP端口,通信就可以开始了。
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。
STUN协议的输出是: 1)公网IP和Port 2)防火墙是否设置 3)客户端是否在NAT之后,及所处的NAT的类型
因此我们进而整理出,通过STUN协议,我们可以检测的类型一共有以下七种:
A:公开的互联网IP。主机拥有公网IP,并且没有防火墙,可自由与外部通信
B:完全锥形NAT。
C:受限制锥形NAT。
D:端口受限制形NAT。
E:对称型UDP防火墙。主机出口处没有NAT设备,但有防火墙,且防火墙规则如下:从主机UDP端口A发出的数据包保持源地址,但只有从之前该主机发出包的目的IP/PORT发出到该主机端口A的包才能通过防火墙。
F:对称型NAT
G:防火墙限制UDP通信。
STEP1:检测客户端是否有能力进行UDP通信以及客户端是否位于NAT后 -- Test1 客户端建立UDP socket,然后用这个socket向服务器的(IP-1,Port-1)发送数据包要求服务器返回客户端的IP和Port,客户端发送请求后立即开始接受数据包。重复几次。 a)如果每次都超时收不到服务器的响应,则说明客户端无法进行UDP通信,可能是:G防火墙阻止UDP通信 b)如果能收到回应,则把服务器返回的客户端的(IP:PORT)同(Local IP: Local Port)比较: 如果完全相同则客户端不在NAT后,这样的客户端是:A具有公网IP可以直接监听UDP端口接收数据进行通信或者E。 否则客户端在NAT后要做进一步的NAT类型检测(继续)
STEP2:检测客户端防火墙类型 -- Test2 STUN客户端向STUN服务器发送请求,要求服务器从其他IP和PORT向客户端回复包: a)收不到服务器从其他IP地址的回复,认为包前被前置防火墙阻断,网络类型为E b)收到则认为客户端处在一个开放的网络上,网络类型为A
STEP3:检测客户端NAT是否是FULL CONE NAT -- Test2 客户端建立UDP socket然后用这个socket向服务器的(IP-1,Port-1)发送数据包要求服务器用另一对(IP-2,Port-2)响应客户端的请求往回发一个数据包,客户端发送请求后立即开始接受数据包。 重复这个过程若干次。 a)如果每次都超时,无法接受到服务器的回应,则说明客户端的NAT不是一个Full Cone NAT,具体类型有待下一步检测(继续)。 b)如果能够接受到服务器从(IP-2,Port-2)返回的应答UDP包,则说明客户端是一个Full Cone NAT,这样的客户端能够进行UDP-P2P通信。
STEP4:检测客户端NAT是否是SYMMETRIC NAT -- Test1#2 客户端建立UDP socket然后用这个socket向服务器的(IP-1,Port-1)发送数据包要求服务器返回客户端的IP和Port, 客户端发送请求后立即开始接受数据包。 重复这个过程直到收到回应(一定能够收到,因为第一步保证了这个客户端可以进行UDP通信)。 用同样的方法用一个socket向服务器的(IP-2,Port-2)发送数据包要求服务器返回客户端的IP和Port。 比较上面两个过程从服务器返回的客户端(IP,Port),如果两个过程返回的(IP,Port)有一对不同则说明客户端为Symmetric NAT,这样的客户端无法进行UDP-P2P通信(检测停止)因为对称型NAT,每次连接端口都不一样,所以无法知道对称NAT的客户端,下一次会用什么端口。否则是Restricted Cone NAT,是否为Port Restricted Cone NAT有待检测(继续)
STEP5:检测客户端NAT是Restricted Cone 还是 Port Restricted Cone -- Test3 客户端建立UDP socket然后用这个socket向服务器的(IP-1,Port-1)发送数据包要求服务器用IP-1和一个不同于Port-1的端口发送一个UDP 数据包响应客户端, 客户端发送请求后立即开始接受数据包。重复这个过程若干次。如果每次都超时,无法接受到服务器的回应,则说明客户端是一个Port Restricted Cone NAT,如果能够收到服务器的响应则说明客户端是一个Restricted Cone NAT。以上两种NAT都可以进行UDP-P2P通信。
通过以上过程,至此,就可以分析和判断出客户端是否处于NAT之后,以及NAT的类型及其公网IP,以及判断客户端是否具备P2P通信的能力了。
此处评论已关闭