公网穿透和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 可以分为四种:
- Full Cone NAT(完全锥形):表示映射表中所有的地址,外网设备都可以直接访问到,是最宽松的策略了;
- Restricted Cone NAT(IP 限制锥形):没被访问过的外网地址发的数据包都会被丢弃,用上面的例子来解释,假如 “192.168.0.1:8088” 访问过外网 “103.15.99.89:80” 这个地址,那外网 “103.15.99.89” 这个 IP 的所有端口都将可以访问通内网,但其他外网地址的访问会被阻止;
- Port Restricted Cone NAT(端口限制锥形):类似 2,不过除了限制外网的 IP 地址外还会限制端口;
- 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 主要有两个作用:
- 帮助获取客户端的公网地址,并通过复杂的策略,探测出客户端所处的 NAT 类型;
- STUN 还可以帮助两个客户端之间进行 NAT “打洞”或者协调 TURN 在两个客户端中间充当中继服务;
NAT 探测
服务端可以非常轻松的在数据包中获取请求的来源 IP 和端口,但是并没有办法知道对应的请求是客户端直发还是 NAT 转发的,更没办法知道是哪种类型的 NAT,客户端也一样无法知道自己的 NAT 情况;但只要 STUN 客户端及 STUN 服务齐心协力,就可以一步步探测出 NAT 情况;
STUN 服务和 STUN 客户端会按照下面的逻辑进行配合,一步步探测客户端所处的 NAT 情况;
ps:一个 STUN 服务需要拥有两个 IP ,通过两个 IP 的服务互相配合来探测 NAT 的情况
- 第一步,判断是否存在 NAT,客户端主动发一个请求到 STUN 服务的 “IP1 端口 1” 上,STUN 服务把收到的请求的 IP 和端口直接返回给客户端,客户端会将 STUN 服务返回的 IP 和端口跟自己的 IP 和端口进行比较,
- 如果一致,则表明客户端处在公网中,或者说客户端没有在 NAT 之后;(可建立host类型连接)
- 如果不一致,则表明客户端处在 NAT 之后,需要往下走继续探测 NAT 类型;
- 第二步,判断 NAT 是不是 Full Cone NAT(完全锥形),客户端发送请求到 STUN 服务的 “IP1 端口 1”,STUN 服务收到请求之后用 “IP2 端口 2” 主动往客户端发送一个请求,
- 如果客户端能够收到 STUN 服务 IP2 的请求,则表明 NAT 策略非常宽松来者不拒,是完全锥形;(可建立srflx类型的连接)
- 如果客户端没办法收到 STUN 服务 IP2 的请求,则数据包被 NAT 丢弃了,NAT 不是完全锥形,需要往下走继续探测 NAT 类型;
- 第三步,判断 NAT 是不是 Symmetric NAT(对称形),客户端主动往 STUN 服务的 “IP2 端口 2” 发送请求,STUN 服务收到请求之后把请求的来源 IP 和端口直接返回给客户端,客户端用收到的 IP 和端口跟 “第一步” 中的 IP 和端口进行比较,
- 如果两次收到的端口不一致,则表明 NAT 是对称形的;
- 如果一致,则表明 NAT 不是对称形的,需要进一步探测 NAT 类型;
- 第四步,判断 NAT 对端口的限制,客户端主动往 STUN 服务的 “IP2 端口 2” 发请求,要求 STUN 服务用 “IP2 端口 3” 往客户端发请求,
- 如果客户端收到了 “IP2 端口 3” 的请求,则表明 NAT 没有对端口进行限制,是 Restricted Cone NAT(IP 限制锥形);(可建立prflx类型连接)
- 如果没收到请求,则表明 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 类型进行一个排序,从宽松到严格的顺序如下:
- Full Cone NAT(完全锥形)
- Restricted Cone NAT(IP 限制锥形)
- Port Restricted Cone NAT(端口限制锥形)
- 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和端口;
相关文章:

公网穿透和RTC
RTC RTC 是 Real-Time Communication 的简写,正如其中文名称 “即时通讯” 的意思一样,RTC 协议被广泛用于各种即时通讯领域,诸如: 在线教育;直播中的主播连麦 PK;日常生活的音视频电话;.....…...

uniapp 使用web-view外接三方
来源 前阵子有个需求是需要在原有的项目上加入一个电子签名的功能,为了兼容性和复用性后面解决方法是将这个电子签名写在一个新的项目中,然后原有的项目使用web-view接入这个电子签名项目; 最近又有一个需求,是需要接入第三方的…...

SQL Sever 复习笔记【一】
SQL Sever 基础知识 一、查询数据第1节 基本 SQL Server 语句SELECT第2节 SELECT语句示例2.1 SELECT - 检索表示例的某些列2.2 SELECT - 检索表的所有列2.3 SELECT - 对结果集进行筛选2.4 SELECT - 对结果集进行排序2.5 SELECT - 对结果集进行分组2.5 SELECT - 对结果集进行筛选…...

外贸平台信息群发脚本的优势!
随着全球电子商务的快速发展,越来越多的外贸企业开始注重海外市场的拓展,而在这个过程中,如何有效地向海外客户发送信息成为了关键的一环,传统的邮件群发和手动发送方式不仅效率低下,而且容易出错。 因此,…...

一文打尽相机单目标定(远心,沙姆镜头)
文章目录 普通镜头标定远心镜头标定沙姆镜头标定远心沙姆镜头标定实战 普通镜头标定 远心镜头标定 沙姆镜头标定 远心沙姆镜头标定 实战...

基于springboot+vue的秒杀商城(前后端分离)
博主主页:猫头鹰源码 博主简介:Java领域优质创作者、CSDN博客专家、公司架构师、全网粉丝5万、专注Java技术领域和毕业设计项目实战 主要内容:毕业设计(Javaweb项目|小程序等)、简历模板、学习资料、面试题库、技术咨询 文末联系获取 项目介绍…...

C++-火车编组
Description 货运火车要在编组站根据挂常车厢到达目的地重新分组。 如果一列火车有4节车厢,经过编组后,车厢的编组顺序为3,2,4,1,你知道编组站是怎么编组的吗? 小明到编组站参观后发现编组站的铁路有很多岔道,火车在岔道上来来回回地开动…...

kafka学习笔记(一)--脑裂
我知道你想裂,但你先别裂 目录 脑裂Kafka脑裂实验Kafka如何防止脑裂--Leader Epochepoch的局限性ISR列表ISR列表的伸缩机制 脑裂 用集群部署的大多数的分布式系统无可避免会面临脑裂问题。简单来说,脑裂就是在同一时刻出现了两个“Leader(或…...

一看就懂的RxJava源码分析
一看就懂的RxJava源码分析 前言零、观察模式简介一、RxJava使用示例一二、示例一源码分析0. 示例一代码分解1. RxJava中的观察者是谁?2. RxJava中的被观察者又是谁?3. 观察者又是如何安插到被观察者中的?4. 示例一RxJava源码整体关系类图4. R…...

halcon中灰度图自动二值化
1、首先图片要先形成灰度图,如果下一句是二值化的那就删掉 dev_clear_window() read_image(Image, D:/desktop/tmpp/微信图片_20231201184731.png) * 转为灰度图 rgb1_to_gray(Image, GrayImage) 2、双击图像变量中的GrayImage 3、工具栏点击打开灰度直方图按钮&…...

Mybatis-Plus实体类注解怎么用
TableName 用在实体类上,指定实体类对应的表名称。 TableName(value "表名") TableId 用在属性上,指定主键字段的名称和类型。主键字段的名称一般是id,类型为自增。 TableId(value "id", type IdType.AUTO) TableFi…...

我是如何写作的?
以前是如何写作的 从小学三年级开始学写作文,看的作文书,老师布置作文题目,内容我都是自己写的。那时会积累一些好词,听到什么好词就记住了。并没有去观察什么,也没有好好花心思在写作上。总觉得我写的作文与真正好的…...

绩效考核实施之——如何做好部门间绩效的平衡?
绩效考核是企业人力资源管理的难点,而绩效考核的公正往往是绩效考核成败的关键, 如果绩效考核的不公平不合理,极易带来企业人员的负面情绪,甚至引起人才的流失。想要保证绩效考核的公平性,就要做好绩效的平衡…...

全新付费进群系统源码 完整版教程
首先准备域名和服务器 安装环境:Nginx1.18 MySQL 5.6 php7.2 安装扩展sg11 伪静态thikphp 后台域名/admin账号admin密码123456 代理域名/daili账号admin密码123456 一、环境配置 二、建站上传源代码解压 上传数据库配置数据库信息 三、登入管理后台 后台域名/ad…...

拉新地推任务管理分销助手公众号开发
拉新地推任务管理分销助手公众号开发 拉新地推任务管理分销助手公众号开发功能可以帮助企业进行地推任务的管理和分销助手的开发。以下是一些可能的功能介绍: 任务管理:这个功能可以让企业创建、分配和管理地推任务。管理员可以创建地推任务,…...

MySQL三范式
欢迎大家到我的博客浏览。MySQL三范式 | YinKais Blog 简介 三大范式是 MySQL 数据库设计表结构所遵循的规范和指导方法,目的是为了减少冗余,建立结构合理的数据库,从而提高数据存储和使用的性能。 三大范式之间是有依赖关系的,…...

玩转微服务-技术篇-JSDOC教程
一. 简介 JSDoc 3 是一个用于 JavaScript 的API文档生成器,类似于 Javadoc 或 phpDocumentor。可以将文档注释直接添加到源代码中。JSDoc 工具将扫描您的源代码并为您生成一个 HTML 文档网站。 JSDoc 是一种用于 JavaScript 代码文档注释的标记语言和工具。它不仅…...

Android12之logcat日志显示颜色和时间(一百六十七)
简介: CSDN博客专家,专注Android/Linux系统,分享多mic语音方案、音视频、编解码等技术,与大家一起成长! 优质专栏:Audio工程师进阶系列【原创干货持续更新中……】🚀 优质专栏:多媒…...

【Windows】内网穿透实现hMailServer远程发送邮件
目录 前言1. 安装hMailServer2. 设置hMailServer3. 客户端安装添加账号4. 测试发送邮件5. 安装cpolar6. 创建公网地址7. 测试远程发送邮件8. 固定连接公网地址9. 测试固定远程地址发送邮件 前言 hMailServer 是一个邮件服务器,通过它我们可以搭建自己的邮件服务,通过cpolar内网…...

深信服技术认证“SCSA-S”划重点:SQL注入漏洞
为帮助大家更加系统化地学习网络安全知识,以及更高效地通过深信服安全服务认证工程师考核,深信服特别推出“SCSA-S认证备考秘笈”共十期内容,“考试重点”内容框架,帮助大家快速get重点知识~ 划重点来啦 深信服安全服务认证工程师…...

Leetcode-二叉树oj题
1.二叉树的前序遍历 144. 二叉树的前序遍历https://leetcode.cn/problems/binary-tree-preorder-traversal/这个题目在遍历的基础上还要求返回数组,数组里面按前序存放二叉树节点的值。 既然要返回数组,就必然要malloc一块空间,那么我们需…...

软件磁盘阵列(software RAID)
RAID-0 等量模式(各个磁盘平均存放文件) RAID-1 镜像模式(一个文件存放两个磁盘) RAID 01 RAID 10 组合模式 RAID 5 三块以上磁盘,记录文件和同位码(存放不通磁盘,通过同…...

浏览器安全攻击与防御
前言 浏览器是我们访问互联网的主要工具,也是我们接触信息的主要渠道。但是,浏览器也可能成为攻击者利用的突破口,通过各种手段,窃取或篡改我们的数据,甚至控制我们的设备.本文将向大家介绍一些常见的浏览器安全的攻击…...

vue生命周期、工程化开发和脚手架
1、前言 持续学习记录总结中,vue生命周期、工程化开发和脚手架 2、Vue生命周期 Vue生命周期:就是一个Vue实例从 创建 到 销毁 的整个过程。 生命周期四个阶段:① 创建 ② 挂载 ③ 更新 ④ 销毁 1.创建阶段:创建响应式数据 2.挂…...

文件搜索工具HoudahSpot mac中文版特点
HoudahSpot mac是一款文件搜索工具,它可以帮助用户快速准确地找到文件和文件夹,支持高级搜索和过滤,同时提供了多种视图和操作选项,方便用户进行文件管理和整理。 HoudahSpot mac软件特点 高级搜索和过滤功能:软件支持…...

maven中scope和optional区别
文章目录 1. Scope(作用范围):2. Optional(可选项): 1. Scope(作用范围): Maven的<scope>元素用于指定依赖项的作用范围,即依赖项在构建和运行时的可见…...

《ChatGPT实操应用大全》探索无限可能
🗣️探索ChatGPT,开启无限可能🚀 文末有免费送书福利!!! ChatGPT是人类有史以来最伟大的发明。他能写作、绘画、翻译、看病、做菜、编程、数据分析、制作视频、解高等数学题…,他会的技能…...

基于helm的方式在k8s集群中部署gitlab - 部署(一)
文章目录 1. 背景说明2. 你可以学到什么?3. 前置条件4. 安装docker服务(所有节点)5. 部署k8s集群5.1 系统配置(所有节点)5.2 安装kubelet组件(所有节点)5.2.1 编写kubelet源5.2.2 安装kubelet5.2.3 启动kubelet 5.3 集…...

flask web开发学习之初识flask(二)
文章目录 一、创建程序实例并注册路由1. 为视图绑定绑定多个URL2. 动态URL 二、启动开发服务器1. 自动发现程序实例2. 管理环境变量3. 使用pycharm运行服务器4. 更多的启动选项5. 设置运行环境6. 调试器7. 重载器 一、创建程序实例并注册路由 app.py # 从flask包中导入flask类…...

利用异或、取反、自增bypass_webshell_waf
目录 引言 利用异或 介绍 eval与assert 蚁剑连接 进阶题目 利用取反 利用自增 引言 有这样一个waf用于防御我们上传的文件: function fun($var): bool{$blacklist ["\$_", "eval","copy" ,"assert","usort…...