【网络】P2P打洞原理
1. 引入
如果你折腾过NAS或者BT下载等等玩意,可能听说过“P2P打洞”这一技术名词。简单来说,P2P打洞可以让我们直接在外网访问内网的设备,从而让没有公网IP的家庭设备也能获得“公网直连”的速度。
比如绿联、极空间等国产NAS的客户端,在外网访问的时候,都会先尝试P2P打洞让你和你的NAS实现P2P直连,打洞失败的时候才会采用服务器转发的方式;
1 |
P2P打洞后:你的当前设备和家里的NAS直接通信 |
因为服务器转发的速度直接依赖于服务器的出口带宽,所以使用服务器转发的用户越多,速度也就越慢,有的时候你会发现服务器转发的速度甚至不如没开会员的某度云盘。
2. 前置技术了解
在学习P2P打洞之前,你需要了解以下知识点。注意,本文只是对P2P打洞的 简单理解和说明 ,深入了解底层原理请自行百度其他更详细的文章!
2.1. 什么是P2P?
P2P即 Peer to Peer,是一种对等连接方式,纯P2P架构包含如下内容
P2P技术的实际的用例如下:
2.2. NAT类型
参考本站 IP层和数据链路层 博客中4.3节对NAT技术的解析。
2.2.1. NAT2:地址限制锥形NAT
所谓地址限制锥形NAT,即NAT映射之后的外网端口和IP地址对请求具有一定的限制,这个限制体现为它只允许已建立链接的主机与之进行通信。
举个具体的的例子,在地址限制锥形NAT下
1.1.1.1:8080
,会建立一个NAT映射,假设是
2.2.2.2:9000
;
1.1.1.1
这个IP能发送报文给NAT地址,对来源端口不限制;
2.2.2. NAT3:端口限制锥形NAT
在限制锥形NAT的基础上,添加了端口的限制,即只有局域网设备C请求过的S1的端口,才能发送信息给局域网主机。
1 |
端口限制锥形NAT下 |
2.2.3. NAT1:完全锥形NAT
完全锥形NAT的映射过程同上,但是不会对外网访问做任何限制。
即NAT地址建立后, 任何外网主机都可以发送信息给这个NAT地址 。
2.2.4. NAT4:对称式NAT(动态NAT)
对称式NAT把内网IP和端口到 相同目的地址和端口 的所有请求,都映射到同一个公网地址和端口;同一个内网主机,用相同的内网IP和端口向另外一个目的地址发送报文,则会用不同的映射(比如映射到不同的端口)。
和端口限制式NAT不同的是,端口限制式NAT是所有请求映射到相同的公网IP地址和端口,而对称式NAT是 为不同的请求建立不同的映射 。它具有端口受限锥型的受限特性,内部地址每一次请求一个特定的外部地址,都可能会绑定到一个新的端口号。 也就是请求不同的外部地址映射的端口号是可能不同的 ,甚至请求同一个主机的不同端口也会映射到不同的NAT地址上。
说白了就是,客户端请求目标的 端口不同 就会更换映射;甚至请求的端口相同时都有可能更换NAT的映射。
2.3. NAT类型IP端口映射示意图
根据NAT类型,可能产生如下映射表,表中
<->
符号左侧表示内网主机IP和端口,
<->
符号右侧表示NAT的外网IP和端口,
@
符号右表示限制条件:外网主机地址IP和端口。
2.4. 如何验证NAT类型
通过这个表,也能反推出我们应该如何验证一个NAT的类型
这里客户端和服务器都是我们单独实现的程序,所以可以通过自定义特定的字段来让客户端、服务器做不同的操作。验证客户端的NAT类型至少需要两个不同IP的公网服务器。
博客: NAT打洞_nat1打洞-CSDN博客 中有一个不错的流程图,在此引用一下
现在假设 192.168.0.100 通过 8000 端口 访问 114.135.246.90 的 9001 端口
经过NAT之后,会形成这样一种结果:
然后如果客户端 192.168.0.100 的8000端口:
NAT3 和 NAT4 的区别:
ip:port
时,都会从 9999 端口出去;但通过 8000 端口访问其他
ip:port
时,就会绑定 NAT 其他端口,比如 9990(目标端口变化NAT就会变化)
有流程图片,看起来会更清楚一点。
你可以下载微力同步(这是一个P2P的远程加密备份软件),在它的设置里,就可以看到你当前的网络环境是什么类型的NAT。
3. P2P打洞以及穿透性
3.1. P2P如何打洞?
如果想实现P2P打洞,那么当前局域网内设备必须是在 锥形NAT 下,才能实现直接通信。因为在对称NAT下,NAT的端口地址会经常变化,很难实现稳定的连接。
对于锥形NAT,比较好打洞的自然是
完全锥形NAT
了,因为它对外网的来源IP和端口都不做限制,那么就可以用下面的流程来实现打洞
IP:端口
互相告知对方
这个过程中,中间服务器S是不可或缺的,如果没有这个中间服务器,C1和C2就很难知道对方的NAT公网IP和端口,也就没有办法直接实现通信。
个人理解,只要C1和C2有一方是 完全锥形NAT ,那么P2P打洞就是 比较容易实现 的,假设C1是完全锥形NAT,C2是有限制的NAT:
上述过程还是比较好弄明白的。
3.2. NAT穿透性表格
下表展示了不同NAT组合的穿透性。
但是我没想明白两边都是端口限制型NAT如何打洞?百度也没找到好的说明。
搞清楚这个问题后我会回来补充本文。
3.3. NAT3如何进行打洞?
2024.05.04更新:之前没有弄明白两端都是 端口限制NAT (即NAT3)如何进行打洞,经过 一位大佬 的指点,现在弄明白了。
假设A和B都是端口限制锥形NAT,为了简单起见我直接用客户端的名字来代指最后映射的NAT公网IP地址,S代指中间服务器。
1 |
A通过内网端口1000给S:80发送请求,建立映射 A:公网8000 - S:80 |
假设是
A:内网1000
和
S:80
通信,建立了
A:公网8000 -> S:80
的NAT3映射,同时B建立了
B:公网9000 -> S:80
的NAT3映射。
这时候就需要
A:内网1000
发送一个消息给
B:公网9000
,此时因为A的内网端口没有变化,所以A的公网的端口也不会变(还是
A:公网8000
),A端的NAT设备就会将
B:公网9000
加入到请求历史中,即允许了
B:公网9000
发送消息给
A:公网8000 -> A:内网1000
。
但是因为B端的NAT设备不认识
A:公网8000
,这个请求会被直接抛弃。
这时候让B端也用原本的内网端口2000发送一个消息给
A:公网8000
(这个消息可以正常送到A端),就相当让B端的NAT设备也把
A:公网8000
加入到允许列表中,这时候A和B就可以直接通过
A:公网8000
和
B:公网9000
进行通信了,打洞成功!