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消息主要分为两种:
类型 | 说明 |
---|---|
STUN Message Type | STUN类型 |
Message Lenght | 去除固定头部(20Byte)的剩余的长度 |
Transaction ID | 一个128位的标识符,客户端随机生成的,然后服务端要回复相同的标识符 |
MessageType值 | 类型 |
---|---|
0x0001 | Binding Request |
0x0101 | Binding Response |
0x0111 | Binding Error Response |
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属性,属性有一个通用的头部,如上。
类型 | 说明 |
---|---|
Type | 一个uint16长度的类型,用不同的值区分不同的属性 |
Lenght | 表示Value的长度,不包括固定头部的大小(4Byte) |
Value | 不固定长度,表示属性的内容 |
值 | 类型 |
---|---|
0x0001 | MAPPED-ADDRESS |
0x0002 | RESPONSE-ADDRESS |
0x0003 | CHANGE-REQUEST |
0x0004 | SOURCE-ADDRESS |
0x0005 | CHANGED-ADDRESS |
0x0006 | USERNAME |
0x0007 | PASSWORD |
0x0008 | MESSAGE-INTEGRITY |
0x0009 | ERROR-CODE |
0x000a | UNKNOWN-ATTRIBUTES |
0x000b | REFLECTED-FROM |
0x802b | RESPONSE-ORIGIN |
0x802c | OTHER-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 |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
用于标示哪一个服务端的IP和Port发送发送的数据。数据格式参考MAPPED-ADDRESS
。
请求服务端使用不同的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|
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
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) ..
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
类型 | 说明 |
---|---|
Class | 用于存储100的倍数,这个值只能是1~6 |
Number | 100的余数,值的范围是0~99,Error Code的计算是:Class * 100 + Number |
Reason Phrase | ByteString类型,用于描述错误信息 |
Error Code | 说明 |
---|---|
400 | 请求格式不正确 |
401 | 请求消息不包含MESSAGE-INTEGRITY 属性 |
420 | 服务器不理解请求中的强制属性 |
430 | 请求消息包含MESSAGE-INTEGRITY 属性,但是却使用了一个过期的共享密钥 |
431 | 请求消息包含MESSAGE-INTEGRITY 属性,但是HMAC校验失败。 |
500 | 服务器遇到了一个临时错误。客户端应该重试 |
600 | 服务器拒绝满足该请求。 客户端不应重试 |
用于标示哪一个服务端的IP和Port发送的数据。数据格式参考MAPPED-ADDRESS
。
用于标示服务端另一个IP和Port发送的数据。数据格式参考MAPPED-ADDRESS
。
RFC3478和RFC5780主要区别在于:NAT类型和探测方式。RFC5780细化NAT类型,采用新的探测方式,为了新类型和新探测方式新增了几种对应的属性。
RFC3478 NAT Variations中定义了四种NAT类型:Full cone、Restricted cone、Port-Restricted cone和Symmetric。
类似受限制锥形NAT(Restricted cone NAT),但是还有端口限制。
RFC5780 NAT类型主要分为两类:地址和端口隐射,地址和端口过滤。
下图显示了RFC 5780中定义的九种NAT类型和RFC 3489中定义的四种NAT类型,以及RFC 3489中的NAT类型如何与RFC 5780中的对应类型匹配。
RFC3478 Binding Lifetime Discovery
一旦路经通过红色箱子的终点时,UDP的沟通是没有可能性的。一旦通过黄色或是绿色的箱子,就有连线的可能。
RFC5780探测分为两种方式:NAT隐射和NAT过滤。