STUN协议详解
1.概述
STUN(session traversal utilities for NAT),一种处理NAT传输的协议,主要作为工具来服务其他协议。它允许位于NAT(或多重NAT后的客户端找出自己的公网地址,查出自己位于那种类型的NAT之后以及NAT为某一个本地端口所绑定的internet端口),这些信息被用来两个同时处于NAT路由器之后的主机之间建立UDP通信。目的就是找到外界连接内部地址所需的信息。
2.STUN协议架构
1.请求/响应(request/response)类型,由客户端给服务器发送请求,并等待服务端返回响应,用于确定一个NAT给客户端分配的具体绑定。客户端通过事务ID将请求响应连接起来。
2.指示类型(indication transaction),由服务器或者客户端发送指示,另一方不产生响应,用于保持绑定的激活状态。事务ID通常作为debugging aid使用。
所有的STUN报文信息都包含有一个固定头部,包含了方法,类和事务ID。方法表示是具体哪一种传输类型。STUN中只定义了一种方法,即binding(绑定),其他方法可以由使用者自行扩展;Binding方法可以用于请求/响应类型和指示类型。
STUN基于客户机-服务器协议。如一个VoIP电话或者软件可能会包含一个STUN客户端。这个客户端向STUN服务器发送请求,之后,服务器就会向STUN客户端报告NAT路由器的公网IP地址以及NAT为允许传入流量传回内网而开通的端口。同时还使得STUN客户端能够确定正在使用的NAT类型——因为不同的NAT类型处理传入的UDP分组的方式不同。
3 STUN报文格式
包括20字节的STUN header
BODY中可以有0个或多个attribute
3.1 STUN HEADER
最高2为0,以区分复用同一端口时STUN协议
2位用于分类,C0和C1
12位用域定义 请求/指示
STUN MESSAGE TYPE (16位,包括前面置零的2位)定义了STUN的消息类型:
0x0001:捆绑请求
0x0101:捆绑响应
0x0111:捆绑错误响应
0x0002:共享私密请求
0x0102:共享私密响应
0x0112:共享私密错误响应
Magic Cookie:32位字段包含固定值0x2112A442
transaction ID,96位的事务ID标识符,用于随机请求和响应,标识同一个式服务的请求和响应。
3.2 STUN BODY
消息头后有0或多个属性
每个属性进行TLV编码:Type,Length,Value
0x0014: REALM
0x0015:NONCE
0x0020:XOR-MAPPED-ADDRESS
0x8022:SOFTWARE
0X8023:ALTERNATE-SERVER
0X8024:FINGERPRINT
在ICE中,包含STUN中用到的几个属性,具体如下所示:
0x0024 PRIORITY
0x0025 USE-CANDIDATE
0x8029 ICE-CONTROLLED
0x802A ICE-CONTROLLING
6 和 7 是最关键的用于验证
3.2.1 MAPPED-ADDRESS/映射地址
MAPPED-ADDRSS同时也是class STUN的一个属性,之所以还存在也是为了前向兼容。其包含了NAT客户端的反射地址。
Family位IP类型,即IPV4(0x01)或IPV6(0x02)
port位端口
address为32位或128位的IP地址。
3.2.2 XOR-MAPPED-ADDRESS/异或映射地址
XOR-MAPPED-ADDRESS和MAPPED-ADDRESS基本相同,不同点是反射地址部分经过一次异或(XOR)处理。
X-port字段:是将NAT的映射端口以小端形式与magic cookie的高16位进行异或,再将结果转换成大段形式而得到的,X-Address也是类似。之所以要经过这么一次转换,是因为在实践中发现很多NAT会修改payload中自身公网IP的32位数据,从而导致NAT打洞失败。
3.2.3 ERROR-CODE/错误码
ERROR-CODE属性用于error response报文中。其中包含了300-699表示的错误码,以及一个UTF-8格式的文字出错信息(Reason phrase)。
流星雨爱编程: 优质好文,作者在阐述每个知识点时,都力求详尽且清晰,使得读者可以轻松理解并掌握。此外,文章中还引用了一些具有代表性的代码片段,这些代码既展示了编程的魅力,也使得读者能够更好地理解相关概念和技巧
CSDN-Ada助手: 哇, 你的文章质量真不错,值得学习!不过这么高质量的文章, 还值得进一步提升, 以下的改进点你可以参考下: (1)使用更多的站内链接;(2)增加除了各种控件外,文章正文的字数;(3)使用标准目录。
最胖的棒棒: 请教一个问题,在tcc的包里面的base sequence numbe应该是前面码流rtp包的扩展头里面的一系列transport sequence number。但是我用wireshark抓包的时候发现两个值对不上,我可以看到rtp包里面的扩展头在不断增加,但是tcc的包反馈的base sequence numbe和码流里面transport sequence number差距很大。举个例子:序号15013的包是码流包,他的rtp扩展头里面序号是0x028db。序号15014的包是tcc的包,但是base sequence number是0x5e60。我理解tcc的这个包有点延时性,但这个差距真的是太大了。不解~~
ctotalk: 不错
ctotalk: mark