【网络】P2P打洞原理

本文首发于 ❄️慕雪的寒舍

1. 引入

如果你折腾过NAS或者BT下载等等玩意,可能听说过“P2P打洞”这一技术名词。简单来说,P2P打洞可以让我们直接在外网访问内网的设备,从而让没有公网IP的家庭设备也能获得“公网直连”的速度。

比如绿联、极空间等国产NAS的客户端,在外网访问的时候,都会先尝试P2P打洞让你和你的NAS实现P2P直连,打洞失败的时候才会采用服务器转发的方式;

P2P打洞后:你的当前设备和家里的NAS直接通信
采用服务器转发:报文从家里NAS - 服务器 - 你的当前设备

因为服务器转发的速度直接依赖于服务器的出口带宽,所以使用服务器转发的用户越多,速度也就越慢,有的时候你会发现服务器转发的速度甚至不如没开会员的某度云盘。

2. 前置技术了解

在学习P2P打洞之前,你需要了解以下知识点。注意,本文只是对P2P打洞的简单理解和说明,深入了解底层原理请自行百度其他更详细的文章!

2.1. 什么是P2P?

P2P即 Peer to Peer,是一种对等连接方式,纯P2P架构包含如下内容

  • 没有总是在线的服务器
  • 任意端之间直接通信
  • 对等方之间可以间断链接,并可以动态改变IP地址

P2P技术的实际的用例如下:

  • 文件分发(BT下载)
  • 流媒体
  • VolP
  • 内网穿透式访问(建立P2P链接,直接和内网主机通信)即本文即将要讲述的P2P打洞。

2.2. NAT类型

参考本站 IP层和数据链路层 博客中4.3节对NAT技术的解析。

2.2.1. NAT2:地址限制锥形NAT

所谓地址限制锥形NAT,即NAT映射之后的外网端口和IP地址对请求具有一定的限制,这个限制体现为它只允许已建立链接的主机与之进行通信。

  • 局域网主机C需要和公网服务器S1进行通信
  • 局域网主机C发送请求报文,通过运营商路由器转发,抵达S1服务器
  • 这个过程中每一层的路由器都建立了一个NAT转发表
  • 如果是限制锥形NAT,运营商的路由器将会限制该NAT地址的外网访问IP地址:
    • 只有S1服务器发来的报文能被正常往内网转发(端口不限制),发送给给局域网主机C;
    • 其他公网服务器(和S1不同IP地址)如果企图向该NAT地址发送报文,会被运营商路由器拒绝;

举个具体的的例子,在地址限制锥形NAT下

  • C请求1.1.1.1:8080,会建立一个NAT映射,假设是 2.2.2.2:9000
  • 只有1.1.1.1这个IP能发送报文给NAT地址,对来源端口不限制;
  • 其他来源IP都会被NAT地址拒绝。

2.2.2. NAT3:端口限制锥形NAT

在限制锥形NAT的基础上,添加了端口的限制,即只有局域网设备C请求过的S1的端口,才能发送信息给局域网主机。

端口限制锥形NAT下
C请求 1.1.1.1:8080
只有 1.1.1.1:8080 能发送报文给C的NAT地址
其他来源IP或者1.1.1.1上不同的端口发来的报文都会被拒绝

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和端口。

image.png

2.4. 如何验证NAT类型

通过这个表,也能反推出我们应该如何验证一个NAT的类型

  • 局域网客户端C向服务器S1发起请求,服务器S1能得到一个C的NAT地址和端口;
  • 服务器S1让C向自己的另外几个端口发起请求,如果这些请求的来源IP和端口都一致,则代表C是锥形NAT,如果出现了不同的端口,则代表是对称NAT
  • 服务器S1将这个地址和端口交给服务器S2,S2向C发送一个报文;
  • 如果C收到了这个S2发来的报文,代表是完全锥形NAT,不对外网来源做限制;
  • 如果C没有收到,说明是限制锥形NAT;
  • 服务器S1换一个端口向C的NAT地址和端口发起请求;
  • 如果C收到了,则代表是地址限制锥形NAT,对端口不做限制;
  • 如果C没有收到,则代表是端口限制锥形NAT,对地址和端口都做了限制;
  • 服务器S1尝试让客户端C用相同的本地端口,给S1的另外一个端口发送请求,如果两次请求的来源端口出现了变化,说明是对称式NAT

这里客户端和服务器都是我们单独实现的程序,所以可以通过自定义特定的字段来让客户端、服务器做不同的操作。验证客户端的NAT类型至少需要两个不同IP的公网服务器。

博客:NAT打洞_nat1打洞-CSDN博客 中有一个不错的流程图,在此引用一下

image.png

现在假设 192.168.0.100 通过 8000 端口 访问 114.135.246.90 的 9001 端口

经过NAT之后,会形成这样一种结果:

  • 内网的 192.168.0.100:8000 ↔ 120.230.117.10:9999 NAT公网IP,形成绑定关系
  • 服务端 114.135.246.90:9001 被 120.230.117.10:9999 NAT公网IP,访问

然后如果客户端 192.168.0.100 的8000端口:

  • 8000 端口 能收到 紫色 发来的消息,就是 NAT1
  • 8000 端口 收不到 紫色 发来的消息,却能收到 浅蓝色 线发来的消息,就是 NAT2
  • 8000 端口 收不到 紫色 和 浅蓝色 线发来的消息,只能收到 绿色 线返回来的消息,就是 NAT3 | NAT4

NAT3 和 NAT4 的区别:

  • NAT3 是 8000 端口与 9999 端口形成绑定关系,不管通过 8000 端口访问谁,·都是从 9999 端口出去
  • NAT4 是 8000 端口与 9999 端口形成的绑定关系是有条件的,8000 端口访问同一 ip:port 时,都会从 9999 端口出去;但通过 8000 端口访问其他 ip:port 时,就会绑定 NAT 其他端口,比如 9990(目标端口变化NAT就会变化)

有流程图片,看起来会更清楚一点。

你可以下载微力同步(这是一个P2P的远程加密备份软件),在它的设置里,就可以看到你当前的网络环境是什么类型的NAT。

image.png

3. P2P打洞以及穿透性

3.1. P2P如何打洞?

如果想实现P2P打洞,那么当前局域网内设备必须是在锥形NAT下,才能实现直接通信。因为在对称NAT下,NAT的端口地址会经常变化,很难实现稳定的连接。

对于锥形NAT,比较好打洞的自然是完全锥形NAT了,因为它对外网的来源IP和端口都不做限制,那么就可以用下面的流程来实现打洞

  • 需要中间服务器S
  • 客户端C1和C2都是完全锥形NAT
  • 客户端C1请求和C2实现P2P连接
  • 客户端C1向中间服务器S发起请求,NAT会为C1维护一个端口和地址
  • 服务器S收到C1的请求,并对内网客户端C2下发一个通知,让C2也来请求S
  • C2也向服务器发起一个请求,NAT为C2也维护了一个地址
  • 此时服务器S就同时知道C1和C2通过NAT出来的一个公网端口和IP地址
  • 服务器S将C1/C2的IP:端口互相告知对方
  • C1和C2都得到了对方的IP和端口,因为是完全锥形NAT,双方可以直接通信
  • 打洞完成

这个过程中,中间服务器S是不可或缺的,如果没有这个中间服务器,C1和C2就很难知道对方的NAT公网IP和端口,也就没有办法直接实现通信。

个人理解,只要C1和C2有一方是完全锥形NAT,那么P2P打洞就是比较容易实现的,假设C1是完全锥形NAT,C2是有限制的NAT:

  • 服务器S知道了C1的NAT的公网IP地址和端口后,将其告知C2;
  • C2重新对C1的完全锥形NAT发送请求,限制锥形NAT会对C2的新请求更新自己的限制表中的白名单,将C1的IP地址和端口也加入到了这个白名单中
  • 此时限制锥形NAT的限制就消失了,C1和C2依旧可以点对点发起通信。

上述过程还是比较好弄明白的。

3.2. NAT穿透性表格

下表展示了不同NAT组合的穿透性。

image.png

但是我没想明白两边都是端口限制型NAT如何打洞?百度也没找到好的说明。

  • 关于端口受限型 NAT 打洞可行性的思考 - 糯米PHP
  • 双方都是端口限制NAT能实现P2P打洞吗?

搞清楚这个问题后我会回来补充本文。

3.3. NAT3如何进行打洞?

2024.05.04更新:之前没有弄明白两端都是端口限制NAT(即NAT3)如何进行打洞,经过一位大佬的指点,现在弄明白了。

假设A和B都是端口限制锥形NAT,为了简单起见我直接用客户端的名字来代指最后映射的NAT公网IP地址,S代指中间服务器。

A通过内网端口1000给S:80发送请求,建立映射 A:公网8000 - S:80
B通过内网端口2000给S:80发送请求,建立映射 B:公网9000 - S:80

假设是A:内网1000S: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:公网8000B:公网9000进行通信了,打洞成功!

3.4. 打洞失败怎么办?

如果打洞失败,C1和C2就得借助中间服务器S的转发来实现通信,此时通信的速度就会出现限制。同时,中间服务器S的带宽/流量资费也比较感人。

这也是为什么绿联和极空间虽然提供了中间服务器转发的方式,但依旧会想办法让你和你的NAS能实现P2P直接通信。除了能提高连接速度,更多的是节省它们服务器的带宽和资费。

4. The end

P2P打洞的大概原理就是如此,更深层次的就不再研究了~你看明白了吗?

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/410692.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

ES 根据条件删除文档

随着业务量的增多&#xff0c;es中数据越来越多&#xff0c;但有些数据其实后期并无业务用途&#xff0c;可直接做物理删除&#xff0c;程序里做兼容&#xff0c;但历史每个月的索引里的数据需要处理这部分冗余数据。 es提供_delete_by_query 根据查询条件进行删除的操作&…

呼入的电话通过http接口转接(mod_cti基于FreeSWITCH)

文章目录 前言联系我们配置流程1.呼入路由配置2.呼入安全配置3.配置生效规则4. 动作解析动作说明接口返回说明 5.创建拨号方案并启用 前言 呼叫流程&#xff1a;任意手机呼叫指定的号码&#xff0c;进入到中间件中&#xff0c;然后通过接口转接到对应的坐席分机中。接口作用&a…

警惕!血脂偏高,这些身体信号你不可不知!

在快节奏的现代生活中&#xff0c;高血脂&#xff0c;这个看似“沉默的杀手”&#xff0c;正悄然威胁着越来越多人的健康。它不像感冒发烧那样有明显的症状&#xff0c;却能在不知不觉中侵蚀血管&#xff0c;增加心血管疾病的风险。今天&#xff0c;我们就来揭开高血脂的神秘面…

探索最佳无代码低代码工具:加速 Web 应用开发

Web 应用无处不在。 从用户友好的在线表单到功能强大的企业级解决方案&#xff0c;Web 应用的多样性和复杂性不断增长。 随着低代码无代码技术的发展&#xff0c;构建一个 Web 应用的门槛正在大大降低。 对于刚踏入 Web 开发领域的人员来说&#xff0c;正确的低代码/无代码工…

【AI大模型】提示词(Prompt)全面解析

文章目录 前言前置准备&#xff08;非常重要&#xff09;一、Prompt 提示词介绍1.1 Prompt 的重要性 二、Prompt 提示词元素构成与实践2.1 关键字2.2 上下文2.3 格式要求2.4 实践示例 三、Prompt 提示词编写原理3.1 清晰性3.2 具体性3.3 适应性 四、Prompt 提示词编写常用的分隔…

游戏开发设计模式之装饰模式

目录 装饰模式在游戏开发中的具体应用案例是什么&#xff1f; 如何在Unity中实现装饰模式以动态扩展游戏对象的功能&#xff1f; 装饰模式与其他设计模式&#xff08;如适配器模式、代理模式&#xff09;相比&#xff0c;有哪些优势和劣势&#xff1f; 优势 劣势 与适配器…

错误使用 gretna_GUI_PreprocessInterface>RunBtn_Callback

&#x1f3c6;本文收录于《CSDN问答解惑-专业版》专栏&#xff0c;主要记录项目实战过程中的Bug之前因后果及提供真实有效的解决方案&#xff0c;希望能够助你一臂之力&#xff0c;帮你早日登顶实现财富自由&#x1f680;&#xff1b;同时&#xff0c;欢迎大家关注&&收…

【IC设计】跨时钟异步处理系列——单比特跨时钟

文章目录 建立时间和保持时间单比特信号的跨时钟处理慢时钟域的信号传输到快时钟域打两拍 快时钟域的信号传输到慢时钟域方案一 脉冲展宽同步 (打拍打拍&#xff0c;进行或)代码原理图 方案二 脉冲电平检测双触发器同步边沿检测代码原理图 建立时间和保持时间 所谓的建立时间或…

spring boot(学习笔记第十九课)

spring boot(学习笔记第十九课) Spring boot的batch框架&#xff0c;以及Swagger3(OpenAPI)整合 学习内容&#xff1a; Spring boot的batch框架Spring boot的Swagger3&#xff08;OpenAPI&#xff09;整合 1. Spring boot batch框架 Spring Batch是什么 Spring Batch 是一个…

<数据集>TACO垃圾识别数据集<目标检测>

数据集格式&#xff1a;VOCYOLO格式 图片数量&#xff1a;6004张 标注数量(xml文件个数)&#xff1a;6004 标注数量(txt文件个数)&#xff1a;6004 标注类别数&#xff1a;18 标注类别名称&#xff1a;[Crankshaft, Centrifugal_body, Washer_container, Circlip_containe…

基于Java的高校学生工作系统的设计与实现(论文+源码)_kaic

摘 要 本系统为高校学生工作管理系统&#xff0c;系统能够为高校提供便捷的学生信息管理功能。该系统采用 Java 语言编写&#xff0c;系统采用MVC架构进行设计&#xff0c;通过Servlet和JSP等技术实现前后端数据交互和页面呈现&#xff1b;采用 Mysql作为后台数据库&#xff0…

出现Property ‘sqlSessionFactory‘ or ‘sqlSessionTemplate‘ are requiredProperty报错

目录&#xff1a; bug Property ‘sqlSessionFactory‘ or ‘sqlSessionTemplate‘ are requiredProperty报错解决方法 bug Property ‘sqlSessionFactory‘ or ‘sqlSessionTemplate‘ are requiredProperty 报错 在一个springboot demo启动的时候出现以下错误 &#xff0c;…

2024升级zblog小程序开源源码/基于uniapp开发的(支持微信小程序、百度小程序、安卓APP)

源码简介&#xff1a; 2024最新zblog多端小程序开源源码&#xff0c;它是基于uniapp开发的&#xff0c;它是针对和支持微信小程序、百度小程序和安卓APP哦&#xff01;百度百科小程序源码下载。 这个基于uniapp开发的zblog多端小程序开源源码&#xff0c;听说对收录和SEO都有…

Chrome 中的 RCE 会在 JIT 编译器中产生不正确的副作用

此类漏洞通常是“一键式”攻击的起点,当受害者访问恶意网站时,该漏洞会危害受害者的设备。Chrome 中的渲染器 RCE 允许攻击者危害 Chrome 渲染器进程并执行任意代码。但是,渲染器进程的权限有限,因此攻击者需要将此类漏洞与第二个“沙盒逃逸”漏洞串联起来:Chrome 浏览器进…

ssm基于微信小程序的付费自习室系统源码调试讲解

本项目包含程序源码数据库LW调试部署环境&#xff0c;文末可获取一份本项目的java源码和数据库参考。 系统的选题背景和意义 选题背景&#xff1a; 随着社会的发展和教育竞争的加剧&#xff0c;越来越多的学生和职场人士需要一个安静、舒适、专注的学习环境。然而&#xff0c;传…

STM32学习记录-08-USART串口

1 通信接口 通信的目的:将一个设备的数据传送到另一个设备,扩展硬件系统 通信协议:制定通信的规则,通信双方按照协议规则进行数据收发 USART:TX数据发送、RX数据接收 I2C:SCL时钟、SDA数据 SPI:SCLK时钟、MOSI主机输出、MISO主机输入、CS片选 CAN:CAN_H、CAN_L一对差分数据…

Reactor 模式的 Java 实现(feat. Scalable IO in Java - Doug Lea)

原文地址&#xff1a;http://hscarb.github.io/java/20240827-reactor-java.html Reactor 模式的 Java 实现&#xff08;feat. Scalable IO in Java - Doug Lea&#xff09; 1. 背景 Doug Lea 在 Scalable IO in Java 的 PPT 中描述了 Reactor 编程模型的思想&#xff0c;大…

【计算机网络】计算机网络的分层结构

为什么要分层&#xff1f;为什么要制定协议&#xff1f; 计算机网络功能复杂→采用分层结构&#xff0c;将诸多功能合理地划分在不同层次→对等层之间制定协议&#xff0c;以实现功能。

6G网络的关键技术、应用前景与挑战并存的科技征途

移动通信技术正以前所未有的速度迭代更新&#xff0c;而6G技术的研发与商用化进程渐渐成为了当前科技领域的热点与焦点。在5G技术尚未完全普及的今天&#xff0c;全球各国已纷纷将目光投向了更加充满想象的6G网络时代。本文将探讨全球6G研发的最新进展&#xff0c;特别是欧盟与…

javacv-ffmpeg ProcessBuilder批量旋转图片

javacv-ffmpeg ProcessBuilder实现对图片的旋转&#xff0c;最近需要处理很多图片&#xff0c;量有点多&#xff0c;所以不能一个一个去编辑旋转图片&#xff0c;所以写一个工具类&#xff0c;实现对图片的旋转 maven配置文件&#xff0c;加上对ffmpeg的依赖&#xff0c;由于f…