公网穿透和RTC

RTC

RTC 是 Real-Time Communication 的简写,正如其中文名称 “即时通讯” 的意思一样,RTC 协议被广泛用于各种即时通讯领域,诸如:

  • 在线教育;
  • 直播中的主播连麦 PK;
  • 日常生活的音视频电话;
  • ......

WebRTC 则是 Google 基于 RTC 协议实现的一个开源项目,为 Web 页面提供了实时音视频传输所需的能力(前端部分);

RTC 有一个非常重要的特性,它是一个支持点对点直接传输的 P2P 协议;

P2P

P2P 是 “Peer to Peer” 的简写,在金融领域大家应该都听过这个名词(P2P 暴雷),金融中 P2P 可以指代 “个人对个人的网络放贷”;在互联网中也有着类似的意思,表示数据 “点对点传输” ,指数据可以在两个互联网用户之间直接传输,无需服务器在中间进行转发;

举个例子:IM 聊天软件中有 A、B 两个正在聊天的用户,聊天过程中,用户 A 的文字信息是没办法直接通过网络发送给用户 B 的,而是需要一个服务器 S 在中间做转发,“A -> S -> B”;但采用 RTC 协议的视频电话就不一样了,电话的音视频数据可以通过网络直接在两个用户之间传输,无需中间服务器进行转发:“A -> B”;

采用 RTC 协议能带来两个非常大的优势:

  • 大幅度降低服务端的负载,减少成本;
  • 用户间直接进行数据传输,延迟上能带来不小的提升;

NAT “墙”

从上文知道,RTC 是一个 P2P 协议,数据可以直接在用户之间传输;但现实往往比理论来的复杂,实际用户的网络环境并没有那么简单,如果不做一些特殊处理,数据很大概率无法在两个用户之间传输,之所以无法直接传输,为了大家更好的理解需要从头说起;

随着互联网的用户逐年增多,接入互联网的设备也越来越多,公网 IPv4 的地址池慢慢见底,新接入互联网的设备很难再分配到单独公网的 IPv4 地址,为了解决这个问题,引入了一个叫 NAT(Network address translation)的协议;新接入的设备不再直接分配公网的 IPv4 地址,而是躲在 NAT 设备(路由器等)之后,NAT 会给后面的每一个设备都分配一个单独的内网地址,NAT 内部将维护一个内外网的地址映射表格,举个例子:

NAT 设备会修改发出去和收到的数据包,比如把上面 “192.168.0.1:8088” 发出去的包改成 “220.181.38.149:1111” ,这样外部的设备就会以为自己是在跟 “220.181.38.149:1111” 通信,接收到响应包之后,NAT 会把目标地址 “220.181.38.149:1111” 修改为 “192.168.0.1:8088”,随后转发到内网;这样就实现了一个公网的 IPv4 地址给多个设备共同使用的效果;

NAT 在实现上述功能之后,为了内网设备不被攻击,还使用了两个安全策略:

  • NAT 超时:NAT 维护的内外网地址映射表存在超时时间,一段时间内没有数据传输,对应的映射就会被取消,造成连接链路中断;
  • NAT 墙:NAT 还实现了类似防火墙的能力,外部主动发送给内部设备的数据包到了 NAT 之后可能会被丢弃;

根据 NAT 墙策略的不同,最常见的 NAT 可以分为四种:

  1. Full Cone NAT(完全锥形):表示映射表中所有的地址,外网设备都可以直接访问到,是最宽松的策略了;
  2. Restricted Cone NAT(IP 限制锥形):没被访问过的外网地址发的数据包都会被丢弃,用上面的例子来解释,假如 “192.168.0.1:8088” 访问过外网 “103.15.99.89:80” 这个地址,那外网 “103.15.99.89” 这个 IP 的所有端口都将可以访问通内网,但其他外网地址的访问会被阻止;
  3. Port Restricted Cone NAT(端口限制锥形):类似 2,不过除了限制外网的 IP 地址外还会限制端口;
  4. Symmetric NAT(对称形):这种 NAT 的丢包策略和 3 一样,只要外网的 IP 和端口有一个没被访问过,数据包就会被丢弃;但是该类型的 NAT 内外网地址映射的策略不一样,对称型 NAT 不会直接给一个内网设备分配固定的 IP 和端口,而是根据访问的外网地址分配不同的 IP 和端口;举个例子,假设内网设备 A 访问外网 B 时的映射为 “192.168.0.1:8088 <--> 220.181.38.149:1111”,那么内网 A 访问外网 C 时的映射可能会变成 “192.168.0.1:8088 <--> 220.181.38.149:2222”;

为什么要叫锥形和对称形?

所谓锥形,是指本地端访问所有外网单元时都使用同样的公网IP和端口;例如,

本端 220.181.38.149:2222 --------  抖音

本端 220.181.38.149:2222 --------  王者荣耀

本端 220.181.38.149:2222 --------  小红书

而对称形,是指本地端访问不同外网单元时使用不同的公网IP和端口;例如:

本端 220.181.38.149:1111 --------  抖音

本端 220.181.38.149:2222 --------  王者荣耀

本端 220.181.38.149:3333 --------  小红书

ICE -- NAT “打洞”

知道 NAT 的存在之后,再举一个例子 :用户 A 知道用户 B 的网络地址,并且 A 和 B 在不同的 NAT 之后;某一时刻 A 想主动联系 B,然后 A 经过自己 NAT 发一个请求给 B,请求到达 B 的 NAT 时,因为 B 没联系过 A,所以 B 的 NAT 便会将 A 的请求丢弃;

上面简单的例子就可以看出,虽然 RTC 是一个 P2P 的协议,但因为 NAT 墙的存在,就算通讯的双方知道对方的网络地址,也没办法直接沟通......

所以,需要引入一个机制对这个沟通过程进行协调,帮助通讯双方能够越过 NAT 并成功建立连接,这套机制就是 ICE(Interactive Connectivity Establishment),ICE 是一个框架协议,可以让互联网中两个设备进行点对点的连接,ICE 框架包含的两个主要工具协议:

  • STUN
  • TURN

STUN

STUN(Session Traversal Utilities for NAT)是一个工具协议,这个协议的主要目的是协调帮助两个在 NAT 之后的设备建立 UDP (也可以是 TCP)传输;既然 STUN 是一个协议,那我们就可以采用任意技术栈来开发实现一个 STUN 服务及 STUN 客户端,实现的 STUN 主要有两个作用:

  1. 帮助获取客户端的公网地址,并通过复杂的策略,探测出客户端所处的 NAT 类型;
  2. STUN 还可以帮助两个客户端之间进行 NAT “打洞”或者协调 TURN 在两个客户端中间充当中继服务;

NAT 探测

服务端可以非常轻松的在数据包中获取请求的来源 IP 和端口,但是并没有办法知道对应的请求是客户端直发还是 NAT 转发的,更没办法知道是哪种类型的 NAT,客户端也一样无法知道自己的 NAT 情况;但只要 STUN 客户端及 STUN 服务齐心协力,就可以一步步探测出 NAT 情况;

STUN 服务和 STUN 客户端会按照下面的逻辑进行配合,一步步探测客户端所处的 NAT 情况;

ps:一个 STUN 服务需要拥有两个 IP ,通过两个 IP 的服务互相配合来探测 NAT 的情况
  1. 第一步,判断是否存在 NAT,客户端主动发一个请求到 STUN 服务的 “IP1 端口 1” 上,STUN 服务把收到的请求的 IP 和端口直接返回给客户端,客户端会将 STUN 服务返回的 IP 和端口跟自己的 IP 和端口进行比较,
    1. 如果一致,则表明客户端处在公网中,或者说客户端没有在 NAT 之后;(可建立host类型连接)
    2. 如果不一致,则表明客户端处在 NAT 之后,需要往下走继续探测 NAT 类型;
  2. 第二步,判断 NAT 是不是 Full Cone NAT(完全锥形),客户端发送请求到 STUN 服务的 “IP1 端口 1”,STUN 服务收到请求之后用 “IP2 端口 2” 主动往客户端发送一个请求,
    1. 如果客户端能够收到 STUN 服务 IP2 的请求,则表明 NAT 策略非常宽松来者不拒,是完全锥形;(可建立srflx类型的连接)
    2. 如果客户端没办法收到 STUN 服务 IP2 的请求,则数据包被 NAT 丢弃了,NAT 不是完全锥形,需要往下走继续探测 NAT 类型;
  3. 第三步,判断 NAT 是不是 Symmetric NAT(对称形),客户端主动往 STUN 服务的 “IP2 端口 2” 发送请求,STUN 服务收到请求之后把请求的来源 IP 和端口直接返回给客户端,客户端用收到的 IP 和端口跟 “第一步” 中的 IP 和端口进行比较,
    1. 如果两次收到的端口不一致,则表明 NAT 是对称形的;
    2. 如果一致,则表明 NAT 不是对称形的,需要进一步探测 NAT 类型;
  4. 第四步,判断 NAT 对端口的限制,客户端主动往 STUN 服务的 “IP2 端口 2” 发请求,要求 STUN 服务用 “IP2 端口 3” 往客户端发请求,
    1. 如果客户端收到了 “IP2 端口 3” 的请求,则表明 NAT 没有对端口进行限制,是 Restricted Cone NAT(IP 限制锥形);(可建立prflx类型连接)
    2. 如果没收到请求,则表明 NAT 限制了端口,是 Port Restricted Cone NAT(端口限制锥形);

NAT “打洞”

经过上面四个步骤之后,便知道了客户端的公网地址以及所在的 NAT 情况,光知道 NAT 情况还没用,NAT 依旧会对请求进行拦截,STUN 还需要协调两个客户端对各自的 NAT 进行打洞,客户端才能穿越 NAT 完成连接建立,下面从简单到复杂举几个例子来说明 NAT 的打洞流程;

只有一方在 NAT 后

假设:客户端 A 和客户端 B 需要建立 P2P 连接,客户端 A 直接拥有一个公网 IP,而客户端 B 在 NAT 之后;

这种情况下如果客户端 A 直接与客户端 B 通信,通信将会失败,客户端 A 发送的数据包会被客户端 B 的 NAT 丢弃;此时,STUN 服务端便会进行协调,让客户端 B 主动先往客户端 A 发送数据包,客户端 B 的 NAT 便记录了客户端 A 的通信记录,客户端 A 后续便可以与客户端 B 进行通信了;

客户端 B 主动连接客户端 A ”这个过程就被形象的称为 “给客户端 B 的 NAT 打洞”;

双方都在非对称形 NAT 后

假设:客户端 A 和客户端 B 需要建立 P2P 连接,客户端 A 和客户端 B 在不同的 NAT 之后;

这种情况下客户端 A 和客户端 B 往对方发送的数据都会被 NAT 丢弃,STUN 服务便会协调两个客户端,让它们先主动都往对方发送数据,在自己的 NAT 上留下对方的 “洞”,后续两个客户端便可以完成连接的建立了;

双方在对称形 NAT 后

假设:客户端 A 和 B 的 NAT 均为 Symmetric NAT(对称形);

这种情况下,先说结论,STUN 服务将无法协调客户端 B 的 NAT 打洞;

由于对称形 NAT 的特性,STUN 服务端看到的客户端 A “ip 、 端口”,将会和客户端 B 看到的客户端 A 的 “ip、 端口” 不一样,此时如果 STUN 服务强行协调客户端 B 给 NAT 进行打洞,打的洞客户端 A 并没办法使用;

所以这种情况下是没有办法建立 P2P 连接的,也因为这种情况的存在,才引入了 TURN 中继协议;

TURN

TURN 全称 “Traversal Using Relays around NAT(TURN):Relay Extensions to Session Traversal Utilities for NAT(STUN)” ,从全称就可以看出,TURN 是 STUN 的一个补充协议,当 STUN 无法完成两个客户端的 P2P 直连时,TURN 便会充当一个 “中继服务器”的角色,对两个客户端之间的信息进行转发;

如何快速判断是否能打洞?

给 NAT 类型进行一个排序,从宽松到严格的顺序如下:

  1. Full Cone NAT(完全锥形)
  2. Restricted Cone NAT(IP 限制锥形)
  3. Port Restricted Cone NAT(端口限制锥形)
  4. Symmetric NAT(对称形)

如果两个客户端的 NAT 类型的序号相加大于等于 7 ,则无法打洞成功,需要引入 TURN 服务;举个例子,如果两个客户端分别是 “4. Symmetric NAT(对称形)” 和 “2. Restricted Cone NAT(IP 限制锥形)”,则这两个客户端能打洞成功,因为他们的序号相加为 6 ,小于 7;

webRTC ICE

WebRTC建立网络连接的过程,主要包括收集candidate、交换candidate和按优先级尝试连接,该过程被称为ICE(Interactive Connectivity Establishment,交互式连接建立)。其中每个 candidate 都包含IP地址、端口、传输协议、类型等信息。

根据 RFC5245 协议 ,WebRTC将 candidate分为了四个类型:host、srflx、prflx、relay,它们的优先级依次降低。

host:Host Candidate,根据主机的网卡数量决定,一般一个网卡对应一个ip地址,然后给每个ip随机分配一个端口生成;这种类型的连接里,使用的是本机物理网卡的IP和端口。

srflx:Server Reflexive Candidate,根据STUN服务器获得的ip和端口生成;这种类型的连接里,使用的是STUN服务器映射的IP和端口;

prflx:Peer Reflexive Candidate,根据对端的ip和端口生成;这种类型的连接里,使用的是NAT上分配的IP和端口;

relay:Relayed Candidate,根据TURN服务器获得的ip和端口生成;这种类型的连接里,使用的是TURN服务器中继的IP和端口;

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

MySQL基本SQL语句(上)

MySQL基本SQL语句&#xff08;上&#xff09; 一、客户端工具的使用 1、客户端工具mysql使用 mysql: mysql命令行工具&#xff0c;一般用来连接访问mysql数据库 选项说明-u, --username指定登录用户名-p, --password指定登录密码(注意是小写p),一定要放到最后面-h, --hostn…

JavaScript中数据类型的转换

前端面试大全JavaScript中数据类型的转换 &#x1f31f;经典真题 &#x1f31f;数据类型转换介绍 &#x1f31f;强制转换&#xff08;显式转换&#xff09; Number( ) String( ) Boolean( ) &#x1f31f;自动转换&#xff08;隐式转换&#xff09; 自动转换为布尔值 …

web前端tips:js继承——寄生组合式继承

上篇文章给大家分享了 js继承中的 寄生式继承 web前端tips&#xff1a;js继承——寄生式继承 今天给大家分享一下 js 继承中的 寄生组合式继承 寄生组合式继承 寄生组合式继承是一种结合了寄生式继承和组合式继承的方式&#xff0c;它的目标是减少组合式继承中多余的调用父…

方差分析(F检验)用于特征选择的Python实现

方差分析&#xff08;F检验&#xff09;又称ANOVA&#xff0c;方差齐性检验&#xff0c;是一种用来捕捉每个特征变量与响应变量之间线性关系的过滤方法&#xff0c;实现路径是针对两个及两个以上分组的样本均值进行差异显著性检验&#xff0c;基本思想是将不同分组的样本均值之…

DaVinci Resolve Studio达芬奇软件 18.6.3

DaVinci Resolve Studio 18是一款专业的视频编辑和调色软件&#xff0c;适用于电影、电视节目、广告等各种视觉媒体的制作。它具有完整的后期制作功能&#xff0c;包括剪辑、调色、特效、音频处理等。 以下是DaVinci Resolve Studio 18的主要特点&#xff1a; - 提供了全面的视…

NIFI源码编译部署在服务器CentOS环境中

一、下载Apache NiFi源码&#xff1a; Apache NiFi官网地址&#xff0c;文档 Apache NiFi源码GitHub地址 二、部署nifi 2.1进入opt目录&#xff0c;并创建software、module [rootlocalhost /]# cd /opt/ [rootlocalhost opt]# ls containerd [rootlocalhost opt]# mkdir s…

Apipost推出IDEA插件,代码写完直接调试

IDEA是一款功能强大的集成开发环境&#xff08;IDE&#xff09;&#xff0c;它可以帮助开发人员更加高效地编写、调试和部署软件应用程序。我们在编写完接口代码后需要进行接口调试等操作&#xff0c;一般需要打开额外的调试工具。 今天给大家介绍一款IDEA插件&#xff1a;Api…

MybtisPlus快速开发(从controller到mapper)

创建新项目 写好配置文件 server:port: 8905#配置MP控制台打印日志 mybatis-plus:configuration:log-impl: org.apache.ibatis.logging.stdout.StdOutImplspring:datasource:type: com.zaxxer.hikari.HikariDataSourcedriver-class-name: com.mysql.cj.jdbc.Driverurl: jdbc:m…

基于SpringBoot月度员工绩效考核管理系统

摘 要 科学时代的发展改变了人类的生活&#xff0c;促使网络与计算机技术深入人类的各个角落&#xff0c;得以普及到人类的具体生活中&#xff0c;为人类的时代文明掀开新的篇章。本系统为月度员工绩效考核管理系统&#xff0c;是专为企业开发的对员工考核的协助软件。可以帮助…

4.7-容器网络之host和none

这一节我们来看一下docker中的另外两种网络&#xff0c;host和none。 docker network inspect none 于是就看到Containers, 里面包含了一个test1 表示这个容器连接到了none。

职业测评链接

职业测评链接&#xff1a; https://www.16personalities.com/ch?utm_sourceresults-turbulent-campaigner&amp%3Butm_mediumemail&amp%3Butm_campaignch&amp%3Butm_contentlogo-0

【Linux】:信号(一)产生

信号 一.前台进程和后台进程1.前台进程2。后台进程3.总结 二.自定义信号动作接口三.信号的产生1.键盘组合键2.kill信号进程pid3.系统调用1.kill函数2.raise函数3.abort函数 四.异常五.软件条件六.core文件 一.前台进程和后台进程 1.前台进程 一个简单的代码演示 像这种程序在…

2024 本田 CBR1000RR-R Fireblade SP

本田在米兰车展期间也发布了自家的旗舰仿赛&#xff0c;虽然不是重大改款&#xff0c;只是更新一些内容&#xff0c;性能方面有所小提升&#xff0c;但是毕竟人家是本田&#xff0c;毕竟人家是火刃&#xff0c;还是要尊重一下&#xff0c;写一篇内容的。 新款还是有一些亮点&am…

SPI学习

SPI介绍 SPI&#xff1a;串行外设设备接口&#xff08;Serial Peripheral Interface&#xff09;&#xff0c;是一种高速的&#xff0c;全双工&#xff0c;同步通信总线。 全双工&#xff1a;同一时刻&#xff0c;能同时接收数据和发送数据。 半双工&#xff1a;同一时刻&am…

子类出现和父类同名的成员,子类如何访问父类的同名成员?

一. 子类访问子类同名的成员&#xff0c;直接访问即可。 #include <iostream> using namespace std;class Base { public:Base(int age 0) : m_age(age) {}int get_age() {return m_age;}static int get_counter() {return ms_counter;}int m_age;static int ms_counte…

C语言——指针(三)

&#x1f4dd;前言&#xff1a; 上篇文章C语言——指针&#xff08;二&#xff09;中对&#xff1a;指针的运算和指针变量类型对指针使用的影响开展了进一步的探讨&#xff0c;这篇文章我们继续学习一下指针与一维数组之间的关系&#xff1a; 1&#xff0c;对数组名的理解 2&am…

electron调用dll问题总汇

通过一天的调试安装&#xff0c;electron调用dll成功&#xff0c;先列出当前的环境&#xff1a;node版本: 18.12.0&#xff0c;32位的&#xff08;因为dll为32位的&#xff09; VS2019 python node-gyp 1、首先要查看报错原因&#xff0c;通常在某一行会有提示&#xff0c;常…

CCF CSP认证 历年题目自练Day50

题目 试题编号&#xff1a; 201809-3 试题名称&#xff1a; 元素选择器 时间限制&#xff1a; 1.0s 内存限制&#xff1a; 256.0MB 问题描述&#xff1a; 题目分析&#xff08;个人理解&#xff09; 还是先理解题意&#xff0c;关于html的部分&#xff0c;可以按照样例画出…

如何使用MES管理系统管理与统计员工绩效

MES管理系统解决方案在生产流程优化中发挥着至关重要的作用&#xff0c;特别是在员工绩效的统计与管理方面。本文深入探讨了MES管理系统如何通过多种方式&#xff0c;包括实时数据采集、生产过程可视化、以及绩效指标设定与评估&#xff0c;以更精准、全面的方式统计员工绩效&a…

C盘爆红 教你如何快速释放空间

目录 问题描述&#xff1a; C盘爆红 快速清理空间&#xff1a; 1.找到设置 2.选择系统 3.打开存储 4.进入清理建议 5.选择以前的Windows安装文件 6.点击清理 7.至此清理完成 问题描述&#xff1a; C盘爆红 快速清理空间&#xff1a; 1.找到设置 2.选择系统 3.打开存储 4.进入清…