STUN工作原理

目录

一. 前言

二. STUN报文格式

STUN Header

RFC3489

RFC5389

STUN Message Body

RFC3489

RFC5389

三. WebRTC对STUN协议的支持

四. STUN工作流程

1. 使用STUN获取NAT映射后的地址

五. 参考资料


一. 前言

        现实网络环境中绝大多数主机都是处于 NAT 之后,对于两个处于同一内网环境的主机,它们只要知道对端的内网地址就能进行通信,而对于不在同一内网的主机,如果它们想通信,要么借助带有公网地址的主机转发,要么通过一定的手段进行 NAT 穿越。

        STUN 协议是用来 NAT 穿越的工具,它允许位于 NAT 之后的主机查找到自己 NAT 映射后的公网地址,需要通信的双方交换映射后的公网地址再进行连通性检测。

        STUN 最先在 RFC3489 中定义,英文全称是 Simple Traversal of UDP Through NAT,即用 UDP 进行 NAT 穿越,而新的 RFC5389 把 STUN 定义为 Session Traversal Utilities for NAT,即 NAT 会话传输工具,RFC3489 与 RFC5389 相比,最大的区别是后者支持 TCP 穿越。

        STUN 协议是一个 C/S 模型的协议,即一端发送请求,另一端进行响应,此外还有指示类型的消息,一端发送指示消息后,另一端不必响应。

二. STUN报文格式

RFC3489 和 RFC5389 定义的报文格式有些许差别,因此下面会分开说明。

STUN Header

RFC3489

        STUN 报文以 20 个字节的头部开始,后面跟着若干属性。

        RFC3489 STUN Header 包含三个字段(2 个字节的 STUN Message Type,2 个字节的 Message Length,16 个字节的 Transaction ID)。

STUN Message Type 的取值和对应的含义如下。

Message Type含义
0x0001绑定请求
0x0101绑定响应
0x0111绑定错误响应
0x0002共享私密请求
0x0102共享私密响应
0x0112共享私密错误响应

Message Length:STUN 报文长度(不包括固定的 20 字节的头部)。

Transaction ID:事务 ID,用于关联请求和对应的响应,同一事务的请求和响应事务 ID 相同。

RFC5389

         RFC5389 的 STUN Header 也是 20 个字节,只是 STUN Message Type 从 16bit 变成 14bit,开头的 2bit 固定为 00,Transaction ID 从 128bit 变成 96bit,减少的 32bit 变成 Magic Cookie,其值固定为 0x2112A442,使用 Magic Cookie 可以区分 STUN RFC3489 还是 RFC5389。Message Length 含义与 RFC3489 一样,表示 STUN 报文除去头部后的长度。

RFC5389 的 STUN Message Type (14bit) 可以进一步分解成以下结构。

        M11~M0 用来表示方法,RFC 规范目前只定义了一个方法:Binding,其他方法可以由使用者自行扩展。

        C1C0 表示方法的类型,对于 C1C0=0b00 表示这是一个请求,C1C0=0b01 表示指示,C1C0=0b10 表示请求成功的响应,C1C0=0b11 表示请求失败的响应。

        方法与方法的类型是正交的,即对于每一种方法,其请求,指示,请求成功响应,请求失败响应都是可能的。

STUN Message Body

        STUN 报文头部之后有 0 或多个属性,每个属性使用 TLV 编码(Type, Length, Value)。

RFC3489

Type名称说明
0x0001MAPPED-ADDRESS返回客户端NAT映射过的IP和端口
0x0002RESPONSE-ADDRESS指明对于MAPPED-ADDRESS的响应应该发送至哪里
0x0003CHANGE-REQUEST请求服务端使用不同的IP和端口发送响应
0x0004SOURCE-ADDRESS指示服务端的IP和端口
0x0005CHANGED-ADDRESSCHANGE-REQUEST的响应
0x0006USERNAME用户名,用于安全认证
0x0007PASSWORD密码,用于安全认证
0x0008MESSAGE-INTEGRITY用于消息完整性验证
0x0009ERROR-CODE错误码
0x000aUNKNOWN-ATTRIBUTES未知属性
0x000bREFLECTED-FROM拒绝

        上图表示的意思是 MAPPED-ADDRESS 这个属性一定不出现在 Binding Req 中,必须出现在 Binding Resp 中,而 RESPONSE-ADDRESS 属性可以出现在 Binding Req 中,一定不出现在其他类型的方法中。

        N/A 表示不,M 表示必须,O 表示可选,其他类型的属性以此类推。

RFC5389

Type名称说明
0x0020XOR-MAPPED-ADDRESS异或地址
0x8028FINGERPRINT 消息指纹

        RFC5389 的属性与 RFC3489 有些许不同,大部分 RFC3489 的属性在 RFC5389 中仍然能使用,此外 RFC5389 还扩展了一些属性,例如 XOR-MAPPED-ADDRESS 获取异或后的地址, FINGERPRINT 防止消息被篡改等,其他属性可查阅 RFC5389 文档,此处不过多介绍。

三. WebRTC对STUN协议的支持

        WebRTC 支持的 STUN 消息类型除了 RFC 规范提及的之外,还扩展了 GOOG Ping 的请求/响应消息。

Message Type含义
0x0001请求消息
0x0011指示消息
0x0101成功响应消息
0x0111错误响应消息
0x0200GOOG Ping 请求消息
0x0300GOOG Ping 响应消息
0x0310GOOG Ping 错误响应消息

        对于属性值,WebRTC 并没有支持 RFC 规范中提到的所有属性,支持的属性如下所示。

Type名称
0x0001MAPPED-ADDRESS
0x0006USERNAME
0x0008MESSAGE-INTEGRITY
0x0009ERROR-CODE
0x000aUNKNOWN-ATTRIBUTES
0x0014REALM
0x0015NONCE
0x0020XOR-MAPPED-ADDRESS
0x8022SOFTWARE
0x8023ALTERNATE-SERVER
0x8028FINGERPRINT
0x802FORIGIN
0xFF00RETRANSMIT-COUNT

四. STUN工作流程

1. 使用STUN获取NAT映射后的地址

        现实网络环境中大部分主机是处于 NAT 之后,即通过 ifconfig/ipconfig 查看到的是内网地址,主机访问外网时 NAT 设备会将其内网地址映射成公网地址,主机本身是无法查看某次访问外网地址 NAT 映射后的地址是多少的,但是通过 STUN 协议,主机发送 STUN binding request, 再由 STUN 服务器回复 STUN binding reponse 即可从属性拿到映射后的地址。

        webrtc.github.io 提供了一个获取服务器反射地址的页面工具,如下所示,输入 STUN 服务地址后,点击 Gather candidates 开始收集地址,type srflx 表示该地址候选项是服务器反射地址类型,即 NAT 映射后公网地址。type host 表示主机地址候选项,跟 ifconfig/ipconfig 查看到的内网地址是一样的。



        我们通过 Wireshark 抓包分析上述流程,可以看到我主机发送的是一个 RFC5389 的 STUN binding request 消息,没有携带任何属性,而 stun1.l.google.com STUN 服务器回复的是一个 RFC5389 标准的 STUN binding success reponse 消息,消息携带了一个 XOR-MAPPED-ADDRESS 属性值,属性值中包含了映射后的地址信息。

五. 参考资料

RFC 3489 - STUN - Simple Traversal of User Datagram Protocol (UDP) Through Network Address Translators (NATs)

RFC 5389 - Session Traversal Utilities for NAT (STUN)

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

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

相关文章

Docker 容器高级操作

Docker容器高级操作 Docker容器创建、停止、启动、删除等基础操作上篇已述,然Docker容器被广大开发者青睐,不可能只有如此简单的功能,必有高阶功法。那么接下来 让我们一同走进容器操作的高级篇,领略其高级操作的魅力。 查看容器 docker ps -a | grep tomcat [root@tudou…

Java中的代理模式

Java中的代理模式 1. 静态代理JDK动态代理CGLib动态代理 1. 静态代理 接口 public interface ICeo {void meeting(String name) throws InterruptedException; }目标类 public class Ceo implements ICeo{public void meeting(String name) throws InterruptedException {Th…

LearnOpenGL_Day1

文章目录 前期准备下载GLFW下载GLAD 引入库文件生成窗口重要概念——双缓冲 (double buffer)代码实现 学习总结 前期准备 下载GLFW GLFW DOWNLOAD 解压后使用CMake编译至新创建的bulid文件夹下: 下载GLAD 引入库文件 创建好工程&#x…

01 矩阵(力扣)多源广度优先搜索 JAVA

给定一个由 0 和 1 组成的矩阵 mat ,请输出一个大小相同的矩阵,其中每一个格子是 mat 中对应位置元素到最近的 0 的距离。 两个相邻元素间的距离为 1 。 输入:mat [[0,0,0],[0,1,0],[0,0,0]] 输出:[[0,0,0],[0,1,0],[0,0,0]] 输入…

RWEQ模型教程

详情点击链接:基于“RWEQ”集成技术在土壤风蚀模拟与风蚀模数估算、变化归因分析中的实践应用及SCI论文撰写 前沿 土壤风蚀是一个全球性的环境问题。中国是世界上受土壤风蚀危害最严重的国家之一,土壤风蚀是中国干旱、半干旱及部分湿润地区土地荒漠化的…

03-树1 树的同构(C++)

03-树1 树的同构 给定两棵树T1和T2。如果T1可以通过若干次左右孩子互换就变成T2,则我们称两棵树是“同构”的。例如图1给出的两棵树就是同构的,因为我们把其中一棵树的结点A、B、G的左右孩子互换后,就得到另外一棵树。而图2就不是同构的。 现…

在 Amazon EMR 上构建实时数据湖

前言 当公司业务发展遇到瓶颈时,业务分析师以及决策者们总会希望通过交叉分析大量的业务数据和用户行为数据,以解答“为什么利润会下滑?”“为什么库存周转变慢了?”等问题,最终整点“干货”出来从而促进业务发展。 …

Oracle 迁移 Hive 过程中遇到的问题总结

前言 最近一个小伙伴在做从 Oracle 到 Hive 的业务迁移工作,在迁移过程中属实遇到了一些坑,今天就来汇总一下这些坑,避免以后大家其他业务迁移的时候再出现类似的问题,即使出现了也可以拿过来进行对照解决。 问题1:Distinct window functions are not supported: count(…

图文教程:使用 Photoshop、3ds Max 和 After Effects 创建被风暴摧毁的小屋

推荐: NSDT场景编辑器助你快速搭建可二次开发的3D应用场景 1. 在 Photoshop 中设置图像 步骤 1 打开 Photoshop。 打开 Photoshop 步骤 2 我已经将小屋的图像导入到Photoshop中以演示 影响。如果您愿意,可以使用其他图像。 图片导入 步骤 3 由于小…

解决 tensorflow 出现的 ImportError: Could not find the DLL(s) ‘msvcp140_1.dll‘. 问题

在安装完tensorflow库后出现 问题详述: ImportError: Could not find the DLL(s) msvcp140_1.dll. TensorFlow requires that these DLLs be installed in a directory that is named in your %PATH% environment variable. You may install these DLLs by downlo…

深入浅出指南:Netty开发【NIO核心组件】

目录 ​Netty开发【NIO核心组件】 1.NIO基础概念 2.NIO核心组件 2.1.Channel&&Buffer简介 2.2.Selector 服务器的多线程版本 服务器的线程池版本 服务器的selector版本 2.3.Buffer 0.ByteBuffer的正确使用流程 1.ByteBuffer类型简介 2.ByteBuffer核心属性说…

记录vue的一些踩坑日记

记录vue的一些踩坑日记 安装Jq npm install jquery --save vue列表跳转到详情页,再返回列表的时候不刷新页面并且保持原位置不变; 解决:使用keepAlive 在需要被缓存的页面的路由中添加:keepAlive: true, {path: /viewExamine,nam…

ubuntu环境安装centos7虚拟机网络主机不可达,ping不通

【NAT模式下解决】1.首先vi /etc/sysconfig/network-scripts/ifcfg-ens33检查ONBOOTyes,保存 2.输入systemctl restart network命令重启网关

flutter:轮播

前言 介绍几个比较有不错的轮播库 swipe_deck 与轮播沾边,但是更多的是一种卡片式的交互式界面设计。它的主要概念是用户可以通过左右滑动手势浏览不同的卡片,每张卡片上都有不同的信息或功能。 Swipe deck通常用于展示图片、产品信息、新闻文章、社…

第四代SHARC® ADSP-21479KBCZ-2A、ADSP-21479BSWZ-2A、ADSP-21479KSWZ-2A高性能DSP(数字信号处理器)

第四代SHARC Processors 现在内置低功耗浮点DSP产品(ADSP-21478和ADSP-21479),可提供改进的性能、基于硬件的滤波器加速器、面向音频与应用的外设以及能够支持单芯片解决方案的新型存储器配置。所有器件都彼此引脚兼容,而且与以往…

Appium+python自动化(二十二)- 控件坐标获取(超详解)

简介 有些小伙伴或者是童鞋可能会好奇会问上一篇中的那个monkey脚本里的坐标点是如何获取的,不是自己随便蒙的猜的,或者是自己用目光或者是尺子量出来的吧,答案当然是:NO。获取控件坐标点的方式这里宏哥给小伙伴们分享和讲解三种方…

2024届IC秋招兆易创新数字IC后端笔试面试题

数字IC后端实现PR阶段设计导入需要哪些文件? 设计导入需要的文件如下图所示。这个必须熟练掌握。只要做过后端训练营项目的,对这个肯定是比较熟悉的。大家还要知道每个input文件的作用是什么。 在吾爱IC后端训练营Cortexa7core项目中,你认为…

Jmeter接口自动化生成测试报告html格式

jmeter自带执行结果查看的插件,但是需要在jmeter工具中才能查看,如果要向领导提交测试结果,不够方便直观。 笔者刚做了这方面的尝试,总结出来分享给大家。 这里需要用到ant来执行测试用例并生成HTML格式测试报告。 一、ant下载安…

整数0 强制转化为指针

整数0强制转化为指针的巧用 在工程中看到以下代码: #define my_container_of(ptr,type,member) \ ((type*)((char *) (ptr) - (unsigned long)(&((type*)0)->member))) ->的优先级高于&。 因此 &((type*)0)->member)的解…

微信小程序quickstartFunctions中云函数的应用

1、在quickstartFunctions文件中新建文件夹和文件 2、index.js 文件书写 const cloud require(wx-server-sdk);cloud.init({env: cloud.DYNAMIC_CURRENT_ENV }); const db cloud.database();// 链表查询试卷和对应的题库 exports.main async (event, context) > {retu…