STUN协议解析


和STUN协议相关的文档一共有三个: RFC 3489RFC 5389RFC 5780

引用

  1. nat-behavior-discovery-using-stun-rfc-5780
  2. stun-rfc-3489-vs-stun-rfc-5389-5780
  3. 网络地址转换
  4. STUN

Message Header

    0                   1                   2                   3
    0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |      STUN Message Type        |         Message Length        |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
                            Transaction ID
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
                                                                   |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

STUN消息主要分为两种:

  • Header说明
类型说明
STUN Message TypeSTUN类型
Message Lenght去除固定头部(20Byte)的剩余的长度
Transaction ID一个128位的标识符,客户端随机生成的,然后服务端要回复相同的标识符
  • STUN Message Type说明
MessageType值类型
0x0001Binding Request
0x0101Binding Response
0x0111Binding Error Response

Message Attributes

    0                   1                   2                   3
    0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |         Type                  |            Length             |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |                             Value                             ....
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

一个STUN消息可以包含0个或者多个STUN属性,属性有一个通用的头部,如上。

  • Message Attributes说明
类型说明
Type一个uint16长度的类型,用不同的值区分不同的属性
Lenght表示Value的长度,不包括固定头部的大小(4Byte)
Value不固定长度,表示属性的内容
  • Type说明
类型
0x0001MAPPED-ADDRESS
0x0002RESPONSE-ADDRESS
0x0003CHANGE-REQUEST
0x0004SOURCE-ADDRESS
0x0005CHANGED-ADDRESS
0x0006USERNAME
0x0007PASSWORD
0x0008MESSAGE-INTEGRITY
0x0009ERROR-CODE
0x000aUNKNOWN-ATTRIBUTES
0x000bREFLECTED-FROM
0x802bRESPONSE-ORIGIN
0x802cOTHER-ADDRESS

MAPPED-ADDRESS

用于表示客户端外部IP地址,如果没有NAT,那么外部IP地址和内部IP地址是相同的。前8位保留,之后8位用于表示IP类型(IPV4/6)。之后16位表示端口号。这里强制使用IPV4版本,所以Address是32位。

    0                   1                   2                   3
    0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |x x x x x x x x|    Family     |           Port                |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |                             Address                           |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

RESPONSE_ADDRESS

用于标示哪一个服务端的IP和Port发送发送的数据。数据格式参考MAPPED-ADDRESS

CHANGE-REQUEST

请求服务端使用不同的IP或者Port来给客户端发送消息。A表示“改变IP”标志,B表示“改变端口”标志。

    0                   1                   2                   3
    0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 A B 0|
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

ERROR-CODE

     0                   1                   2                   3
     0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    |                   0                     |Class|     Number    |
    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    |      Reason Phrase (variable)                                ..
    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  • ERROR-CODE说明
类型说明
Class用于存储100的倍数,这个值只能是1~6
Number100的余数,值的范围是0~99,Error Code的计算是:Class * 100 + Number
Reason PhraseByteString类型,用于描述错误信息
  • Error Code说明
Error Code说明
400请求格式不正确
401请求消息不包含MESSAGE-INTEGRITY属性
420服务器不理解请求中的强制属性
430请求消息包含MESSAGE-INTEGRITY属性,但是却使用了一个过期的共享密钥
431请求消息包含MESSAGE-INTEGRITY属性,但是HMAC校验失败。
500服务器遇到了一个临时错误。客户端应该重试
600服务器拒绝满足该请求。 客户端不应重试

RESPONSE-ORIGIN

用于标示哪一个服务端的IP和Port发送的数据。数据格式参考MAPPED-ADDRESS

OTHER-ADDRESS

用于标示服务端另一个IP和Port发送的数据。数据格式参考MAPPED-ADDRESS

RFC3489 VS RFC5780

RFC3489和RFC5780主要区别在于:NAT类型和探测方式。RFC5780细化NAT类型,采用新的探测方式,为了新类型和新探测方式新增了几种对应的属性。

RFC3489 NAT类型定义

RFC3489 NAT Variations中定义了四种NAT类型:Full cone、Restricted cone、Port-Restricted cone和Symmetric。

完全圆锥形NAT(Full cone NAT)
  • 一旦一个内部地址(iAddr:port)映射到外部地址(eAddr:port),所有发自iAddr:port的包都经由eAddr:port向外发送。任意外部主机都能通过给eAddr:port发包到达iAddr:port(注:port不需要一样)
    在这里插入图片描述
受限圆锥形NAT(Address-Restricted cone NAT)
  • 内部客户端必须首先发送数据包到对方(IP=X.X.X.X),然后才能接收来自X.X.X.X的数据包。在限制方面,唯一的要求是数据包是来自X.X.X.X。
  • 内部地址(iAddr:port1)映射到外部地址(eAddr:port2),所有发自iAddr:port1的包都经由eAddr:port2向外发送。外部主机(hostAddr:any)能通过给eAddr:port2发包到达iAddr:port1。(注:any指外部主机源端口不受限制,但是目的端口必须是port2。只有外部主机数据包的目的IP 为 内部客户端的所映射的外部ip,且目的端口为port2时数据包才被放行。
    在这里插入图片描述
端口受限圆锥形NAT(Port-Restricted cone NAT)

类似受限制锥形NAT(Restricted cone NAT),但是还有端口限制。

  • 一旦一个内部地址(iAddr:port1)映射到外部地址(eAddr:port2),所有发自iAddr:port1的包都经由eAddr:port2向外发送。
  • 在受限圆锥型NAT基础上增加了外部主机源端口必须是固定的。
    在这里插入图片描述
对称NAT(Symmetric NAT)
  • 每一个来自相同内部IP与端口,到一个特定目的地地址和端口的请求,都映射到一个独特的外部IP地址和端口。同一内部IP与端口发到不同的目的地和端口的信息包,都使用不同的映射
  • 只有曾经收到过内部主机数据的外部主机,才能够把数据包发回
    在这里插入图片描述

RFC5780 NAT类型

RFC5780 NAT类型主要分为两类:地址和端口隐射,地址和端口过滤。

Full cone

在这里插入图片描述

Restricted cone

在这里插入图片描述

Port-Restricted cone

在这里插入图片描述

Symmetric

在这里插入图片描述

下图显示了RFC 5780中定义的九种NAT类型和RFC 3489中定义的四种NAT类型,以及RFC 3489中的NAT类型如何与RFC 5780中的对应类型匹配。
在这里插入图片描述

RFC3489 探测算法

RFC3489 Binding Lifetime Discovery
在这里插入图片描述

一旦路经通过红色箱子的终点时,UDP的沟通是没有可能性的。一旦通过黄色或是绿色的箱子,就有连线的可能。

RFC5780 探测算法

RFC5780探测分为两种方式:NAT隐射和NAT过滤。

NAT隐射方式探测

在这里插入图片描述

没有NAT

在这里插入图片描述

端点无关的隐射NAT

在这里插入图片描述

地址相关的隐射NAT

在这里插入图片描述

地址和端口相关的隐射NAT

在这里插入图片描述

NAT过滤方式探测

在这里插入图片描述

端点无关的过滤NAT

在这里插入图片描述

地址相关的过滤NAT

在这里插入图片描述

地址和端口相关的过滤NAT

在这里插入图片描述

评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值