P2P 通信最大的障碍就是 NAT(网络地址转换),NAT 使得局域网内的设备可以与公网进行通讯,但是不同 NAT 下的设备之间通讯将会变得很困难。UDP 打洞就是用来使得设备间绕过 NAT 进行通讯的一种技术。
一、背景知识介绍
1.什么是NAT?
NAT(Network Address Translation,网络地址转换)是一种网络地址翻译技术,主要是将内部的私有IP地址(private IP)转换成可以在公网使用的公网IP(public IP)。
2.为什么会有NAT?
时光回到上个世纪80年代,当时的人们在设计网络地址的时候,觉得再怎么样也不会有超过32bit位长即2的32次幂台终端设备连入互联网,再加上增加ip的长度(即使是从4字节增到6字节)对当时设备的计算、存储、传输成本也是相当巨大的。后来逐渐发现IP地址不够用了,然后就NAT就诞生了!(虽然ipv6也是解决办法,但始终普及不开来,而且未来到底ipv6够不够用仍是未知)。
因此,NAT技术能够兴起的原因还是因为在我们国家公网IP地址太少了,不够用,所以才会采取这种地址转换的策略。可见,NAT的本质就是让一群机器公用同一个IP,这样就暂时解决了IP短缺的问题。
3.NAT有什么优缺点?
优势其实上面已经刚刚讨论过了,根据定义,比较容易看出,NAT可以同时让多个计算机同时联网,并隐藏其内网IP,因此也增加了内网的网络安全性;此外,NAT对来自外部的数据查看其NAT映射记录,对没有相应记录的数据包进行拒绝,提高了网络安全性。
那么,NAT与此同时也带来一些弊端:首先是,NAT设备会对数据包进行编辑修改,这样就降低了发送数据的效率;此外,各种协议的应用各有不同,有的协议是无法通过NAT的(不能通过NAT的协议还是蛮多的),这就需要通过穿透技术来解决。我们后面会重点讨论穿透技术。
二、NAT介绍
1.NAT工作原理:
首先,NAT A 网下的设备 1(192.168.1.101)想与某公网 IP 通讯,设备 1 将包发给 NAT A,然后 NAT A 对源 IP 进行转换(123.122.53.20)发给 NAT B(中间可能还会经过多重 NAT)。
这样做的目的是,NAT B 并不知晓 NAT A 下的各个设备,他只能与 NAT A 本身通讯,因此发送给 NAT B 的包源 IP 必须是 NAT A 的公网 IP,不然 NAT B 没有办法进行回复。
接下来 NAT B 将回复包再发回 NAT A,此时就是 NAT 发挥作用的时候了,NAT A 现在要做的就是将包再分发回之前的设备,如何确定要发给谁呢?NAT 中记录了一张表,之前 192.168.1.101 通过 2333 端口与 42.120.241.46 端口 443 通讯了,并且 NAT A 是用 60001 的端口转发出去的,那么这次接受到发往该 NAT 60001 端口的包时就应该再通过 2333 端口转发给 192.168.1.101。经过这样的过程,NAT A 下的设备都可以连接到互联网了!
2.NAT特性:
1.网络访问只能先由私网侧发起,公网无法主动访问私网主机;
2.NAT网关在两个访问方向上完成两次地址的转换或翻译,出方向做源信息替换,入方向做目的信息替换;
3.NAT网关的存在对通信双方是保持透明的;
4.NAT网关为了实现双向翻译的功能,需要维护一张关联表,把会话的信息保存下来。
3.NAT类型:
NAT分为基础型NAT(静态NAT即Static NAT,动态NAT即Dynamic NAT/Pooled NAT)和NAPT(Network Address Port Translation)两种,但由于基础型NAT已不常用,我们通常提到的NAT就代指NAPT。NAPT是指网络地址转换过程中使用了端口复用技术,即PAT(Port address Translation)。
对于基本使用的NAPT,又分为对称和锥型NAT。
1.锥型NAT,有完全锥型、受限制锥型、端口受限制锥型三种:
a) Full Cone NAT(完全圆锥型):
特点:IP和端口都不受限。
表现形式:从同一私网地址端口192.168.0.8:4000发至公网的所有请求都映射成同一个公网地址端口1.2.3.4:62000 ,192.168.0.8可以收到任意外部主机发到1.2.3.4:62000的数据报。
b) Restricted Cone NAT (限制圆锥型):
特点:IP受限,端口不受限。
表现形式: 从同一私网地址端口192.168.0.8:4000发至公网的所有请求都映射成同一个公网地址端口1.2.3.4:62000,只有当内部主机192.168.0.8先给服务器C 6.7.8.9发送一个数据报后,192.168.0.8才能收到6.7.8.9发送到1.2.3.4:62000的数据报。
c)Port Restricted Cone NAT(端口限制圆锥型):
特点:IP和端口都受限。
表现形式:从同一私网地址端口192.168.0.8:4000发至公网的所有请求都映射成同一个公网地址端口1.2.3.4:62000,只有当内部主机192.168.0.8先向外部主机地址端口6.7.8.9:8000发送一个数据报后,192.168.0.8才能收到6.7.8.9:8000发送到1.2.3.4:62000的数据报。
2. Symmetric NAT(对称NAT):
特点:对每个外部主机或端口的会话都会映射为不同的端口(洞)。
表现形式:只有来自同一内部IP:PORT、且针对同一目标IP:PORT的请求才被NAT转换至同一个公网(外部)IP:PORT,否则的话,NAT将为之分配一个新的外部(公网)IP:PORT。并且,只有曾经收到过内部主机请求的外部主机才能向内部主机发送数据包。
对称的NAT不保证所有会话中的(私有地址,私有端口)和(公开IP,公开端口)之间绑定的一致性。相反,它为每个新的会话分配一个新的端口号。
NAT的限制:对称NAT > 端口限制圆锥型 > 限制圆锥型 > 完全圆锥型
不同的NAT组合打洞的方式也有所不同,有点可以打洞,有的则不能打洞,如两个都是对称型设备则无法实现打洞。不同组合打洞结果如下:
Peer A | Peer B | 是否可以打洞 |
---|---|---|
全锥型 | 全锥型 | 是 |
全锥型 | 受限锥型 | 是 |
全锥型 | 端口受限锥型 | 是 |
全锥型 | 对称型 | 是 |
受限锥型 | 受限锥型 | 是 |
受限锥型 | 端口受限锥型 | 是 |
受限锥型 | 对称型 | 是 |
端口受限锥型 | 端口受限锥型 | 是 |
端口受限锥型 | 对称型 | 否 |
对称型 | 对称型 | 否 |
4.NAT类型检测
前提条件:有一个公网的Server并且绑定了两个公网IP(IP-1,IP-2)。这个Server做UDP监听(IP-1,Port-1),(IP-2,Port-2)并根据客户端的要求进行应答。
第一步:检测客户端是否有能力进行UDP通信以及客户端是否位于NAT后?
客户端建立UDP socket,然后用这个socket向服务器(IP-1,Port-1)发送数据包,要求服务器返回客户端的IP和Port。客户端发送请求后立即开始接受数据包,要设定socket Timeout(300ms),防止无限堵塞. 重复这个过程若干次。如果每次都超时,无法接受到服务器的回应,则说明客户端无法进行UDP通信,可能是防火墙或NAT阻止UDP通信,这样的客户端也就不能P2P了(检测停止)。
当客户端能够接收到服务器的回应时,需要把服务器返回的客户端(IP,Port)和这个客户端socket的 (LocalIP,LocalPort)比较。如果完全相同则客户端不在NAT后,这样的客户端具有公网IP可以直接监听UDP端口接收数据进行通信(检测停止)。否则客户端在NAT后要做进一步的NAT类型检测(继续)。
第二步:检测客户端NAT是否是Full Cone NAT?
客户端建立UDP socket,然后用这个socket向服务器(IP-1,Port-1)发送数据包,要求服务器用另一对(IP-2,Port-2)响应客户端的请求往回发一个数据包。客户端发送请求后立即开始接受数据包,要设定socket Timeout(300ms),防止无限堵塞. 重复这个过程若干次。如果每次都超时,无法接受到服务器的回应,则说明客户端的NAT不是一个Full Cone NAT,具体类型有待下一步检测(继续)。
如果能够接受到服务器从(IP-2,Port-2)返回的应答UDP包,则说明客户端是一个Full Cone NAT,这样的客户端能够进行UDP-P2P通信(检测停止)。
第三步:检测客户端NAT是否是Symmetric NAT?
客户端建立UDP socket,然后用这个socket向服务器(IP-1,Port-1)发送数据包,要求服务器返回客户端的IP和Port, 客户端发送请求后立即开始接受数据包,要设定socket Timeout(300ms),防止无限堵塞. 重复这个过程直到收到回应(一定能够收到,因为第一步保证了这个客户端可以进行UDP通信)。
用同样的方法用同一个socket向服务器的(IP-2,Port-2)发送数据包要求服务器返回客户端的IP和Port。
比较上面两个过程从服务器返回的客户端(IP,Port),如果两个过程返回的(IP,Port)有一个不同(IP不同或者port不同),则说明客户端为Symmetric NAT,这样的客户端无法进行UDP-P2P通信(检测停止)。
否则是Restricted Cone NAT,是否为Port Restricted Cone NAT有待检测(继续)。
第四步:检测客户端NAT是否是Restricted Cone NAT还是Port Restricted Cone NAT?
客户端建立UDP socket,然后用这个socket向服务器(IP-1,Port-1)发送数据包,要求服务器用IP-1和一个不同于Port-1的端口发送一个UDP数据包响应客户端, 客户端发送请求后立即开始接受数据包,要设定socket Timeout(300ms),防止无限堵塞. 重复这个过程若干次。如果每次都超时,无法接受到服务器的回应,则说明客户端是一个Port Restricted Cone NAT,如果能够收到服务器的响应则说明客户端是一个Restricted Cone NAT。以上两种NAT都可以进行UDP-P2P通信。
三、P2P通信
根据客户端的不同,客户端之间进行P2P传输的方法也略有不同,这里介绍了现有的穿越中间件进行P2P通信的几种技术。
1 中继(Relaying)
这是最可靠但也是最低效的一种P2P通信实现。其原理是通过一个有公网IP的服务器中间人对两个内网客户端的通信数据进行中继和转发。如下图所示:
Server S
|
|
+----------------------+----------------------+
| |
NAT A NAT B
| |
| |
Client A Client B
客户端A和客户端B不直接通信,而是先都与服务端S建立链接,然后再通过服务器S和对方建立的通路来中继传递的数据。这种方法的缺陷很明显, 当链接的客户端变多之后,会显著增加服务器的负担,完全没体现出P2P的优势。但这种方法的好处是能保证成功,因此在实践中也常作为一种备选方案。
2 逆向链接(Connection reversal)
第二种方法在当两个端点中有一个不存在中间件的时候有效。例如,客户端A在NAT之后,而客户端B拥有全局IP地址,如下图:
Server S
18.1