STUN 存在的目的就是进行NAT穿越,NAT有四种类型,每种类型如何穿越,它的基本原理是什么,都是属于STUN协议中的一部分。
RFC STUN规范中,实际上有两套STUN规范:
它就是将STUN定义成简单的通过UDP进行NAT穿越的一套规范,也就是告诉你如何一步一步通过UDP进行穿越,但是这套规范在穿越的过程中还是存在很多问题,尤其是现在的网络
路由器对UDP的限制比较多,有的路由器甚至不允许进行UDP传输,所以这就导致了我们通过RFC3489这套规范进行NAT穿越的时候它的失败率会非常高。所以为了解决这个问题,
又定义了另一套标准,RFC5389.
RFC5389是在RFC3489的基础上又增加了一些功能,但是它对整个STUN的描述就不一样了, 它是把STUN描述成一系列穿越NAT的工具,所以都叫STUN,但是他们的含义完全就不一
样了。RFC5389在UDP尝试可能失败的情况下,尝试使用TCP,也就是说RFC5389是包括UDP和TCP的两种协议进行NAT穿越的,这是两套规范最本质的区别。当然在协议的具体内
容上,包括协议头还有协议体中的属性都有很多的变化,但是那些都不是最关键的,最关键的是RFC5389里面将TCP纳入进来。你可以通过TCP进行穿越。
这是STUN 的RFC的两套规范。大家一定要清楚,尤其是查文档的 时候一定要清楚查询的是哪一套规范。
下面我们就具体看看这个STUN协议:
STUN这个协议它是包括了消息头和消息体,消息头是20字节固定的消息头,Body中可以有0个或者多个Attribute属性,后面我们会介绍属性的作用。
比如我客户端发送了好几个请求,那服务端对于每一个请求都要返回一个响应 ,那怎么知道某个响应是对应到的请求呢,就通过这个事物ID。如果它事物ID号相同,说明这两是匹配的,整个逻辑就知道怎么做了,否则的话就很难判断。
所以它有三部分组成,第一是两个字节的类型,第二是两个类型的消息长度,不包括这个消息头,第三个是16字节的128位的事物ID,请求与响应的匹配。这个是消息头。
首先我看消息类型,消息类型的最低两位必须是 0 0,就是RFC5389最新的协议 ,这是第一点的不同;
第二点的不同是,事物ID,老的里面是128位事物ID,在新的里面是 96位,其中有32位单独划出来了单独作为 Magic Cookie,一个魔法数,
以上两点就是RFC3489和5389的STUN消息头的区别。
1.前两位必须是00,以区分复用同一端口时STUN协议:就是不同的协议复用同一个端口的时候,用它来区分哪个是STUN协议哪个不是STUN协议,这是两位00的作用。
2.剩下的14位中有两位用于分类,就是C0和C1,C0和C1是占两位,所以它有四种类型,也就是四个分类,第一种是请求,第二种是指示,第三种是成功,第四种是错误应答,所以它将Message Type消息类型分成了四类。
3.剩下的12位是用于不同请求的定义,比如1代表绑定,2代表私有消息隐私数据,……,但是在STUN 3489里面定义了两个,就是用这12位定义了两种,但是5389里面就一种,一种就够了。
14位其中C0和C1分别在上图中两个不同位置,两个不是放在一起的,它是隔着的,隔着有什么好处,就是按照16进制的话,我们4位为一组,所有的M代表的是请求的值,C是分类,
这样划分,四个一组,第一组里面全都是请求,都是消息类型,第二组里面代表分类,第三组里面又代表另外一种分类。所以这两个进行不同的组合就能分成不同的类型了。
C0C1第一个0是C0第二个零是C1。因为这个C1是处于这个高字节,对于网络数据对于协议分析对于二进制数据处理的人来说,这些都是比较容易理解的,对于没有接触过这些知识的
人可能稍微有点麻烦。
0b00:表式是一个请求
0b01:表示是一个指示
0b10:表示是请求成功的响应
0b11:表示是请求失败的响应
所以这里我们只要记住成功响应和失败的响应就好了。
下面我们就可以看一下STUN的消息类型,它一共定义了6个消息类型,这个就是STUN的消息类型,但是RCF5389就将这个私密类型去掉了。就剩下一个 ,那完全够用了。
对于这部分类型,为什么要了解呢,就是后面要对C0和C1要做详细的解释。
大端模式:数据的高字节保存在内存的低地址中
小端模式:数据的高字节保存在内存的高地址中
网络字节顺序:采用大端排序方式
了解这个模式之后,我们在聊C0和C1它是怎么排序的,大家就会很清楚它是怎么排序的。
网络字节排序采用大端,所以左侧(数据高字节)在内存的低地址中,先进行发送。
0x0001:结合C0C1,可以知道,是绑定请求消息
0x0101:C0为0,C1是1,是请求成功响应消息
0x0111:C0为1,C1是1,是请求失败的响应
新的RFC5389将它分成了两部分,前四个字节也就是32位是一个magic cookie,magic就是一个魔法数了,在这里是固定的0x2112A442,所以我们看到固定的值是这个的话,就是
RFC5389否则就是RFC3489。
通过它是可以识别客户端是否可以识别某些属性,因为不同的规范属性实际上是有变化的,所以你看到 这个魔法数之后就是RFC5389, RFC5389定义了一些新的属性,如果不是的
话,这些新的属性就可以忽略掉。
剩下的12个字节,96位,标识同一个事物的请求和响应,当我们客户端发送多个请求的时候,就能通过这个事物ID将服务端返回的响应与之前发送的请求进行一一匹配。
下面再看STUN Message Body 消息体,消息头后有0或多个属性。每个属性都使用TLV(动态)编码:Type,Length,Value
Value这个值是可以变化的,变化的程度怎么知道有多长呢?通过这个Length,这个Length标示了Value的长度,最终的消息是一个32位对齐的,如果最后不是32位对齐,要通过补0来达到对齐,这是整个Body。
M:必须 O:可选 N/A:没有 C:客户端使用
原文:https://www.cnblogs.com/ssyfj/p/14797389.html