【stun系列03】对于stun协议头的理解
1:STUN消息头
消息头有20个字节组成:00 + 消息类型 + 消息体长度 + 魔术字 + 事务ID
- 前2个字节:
- 其中00占2位:固定全是0
- 消息类型占14位:其中根据消息头的前两个字节和C1C0划分为0x000:请求,0x001:指示,0x010:成功响应,0x011:错误响应。则消息方法只有Binding(0x01)
根据消息类型和方法交集 可以分为,Binding请求(0x00 01),Binding成功响应(0x01 01),Binding失败响应(0x01 11),Binding指示(0x00 11)。其中指示消息用的很少,可以不需要管。
- 消息体长度占16位:是消息体部分的总长度,由于4字节对齐特性,长度字段最后2位也全是0
- 魔术字占32位:4个字节,是固定值0x2112A442
- 事务ID占96位:12个字节,是由客户端随机生成的12字节随机值
自此,消息头如何生成和填充已经确定
2:常用的请求的TLV属性生成规则
TLV属性是:属性type + 属性长度 + 属性值
2.1:USERNAME
属性type:两个字节,为0x0006
属性长度:两个字节,是属性值的长度,即后续填充的value的长度
属性值:可变长度的,用户名的内容+填充字段(填充完保证4字节对齐)
2.2:MESSAGE-INTEGRITY
Request 和 Response 时 需要使用不同的密码加密生成该字段;
如果是主动发送Request需要使用对端ice密码进行加密
如果是回复对端Response需要使用本端ice密码加密并回复
属性类型:0x0008
属性长度:固定20个字节
属性值:短期认证:HMAC-SHA1计算的password值。计算方法:HMAC_SHA1(PASSWORD)
长期认证:MD5(username ":" realm ":" SASLprep(password))
对于短期认证计算网址:https://www.liavaag.org/English/SHA-Generator/HMAC/
其中对于text部分和key部分需要特别注意
text:STUN的包头+属性集合到MESSAGE-INTEGRITY位置,后续的属性不计算在内,但是需要更改stun的包头的length值,此长度需要包含MESSAGE-INTEGRITY的长度,但不包含后面属性的长度。
举例:
192.168.239.1端ice密码:
a=ice-ufrag:13BZ
a=ice-pwd:GT82bdkfK4dxuVsrc/Dv3EqV
192.168.239.140端ice密码:
a=ice-ufrag:67v27075
a=ice-pwd:745s295z8lv458ll46w2467ta460562n
HMAC的输入是stun的包的内容:
00 01 00 50 21 12 a4 42 78 2b 66 6b 32 34 30 6b
4e 51 6a 56 00 06 00 0d 36 37 76 32 37 30 37 35
3a 31 33 42 5a 00 00 00 c0 57 00 04 00 02 00 00
80 2a 00 08 70 fb e5 05 91 bf 83 3c 00 24 00 04
6e 7e 1e ff 00 08 00 14 c7 c4 9a 60 94 6f a0 24
e5 f6 21 2e c6 38 14 fe 2e 76 b2 6d 80 28 00 04
3a c7 02 9f
1:先修改stun的头部长度值,为消息属性长度减去message-integrity后面属性的长度。因为只有一个fingeprint,长度为8,所以改成48
50 - 8 -> 48
修改后如下:
00 01 00 48 21 12 a4 42 78 2b 66 6b 32 34 30 6b
4e 51 6a 56 00 06 00 0d 36 37 76 32 37 30 37 35
3a 31 33 42 5a 00 00 00 c0 57 00 04 00 02 00 00
80 2a 00 08 70 fb e5 05 91 bf 83 3c 00 24 00 04
6e 7e 1e ff 00 08 00 14 c7 c4 9a 60 94 6f a0 24
e5 f6 21 2e c6 38 14 fe 2e 76 b2 6d 80 28 00 04
3a c7 02 9f
2:作为HMAC的输入时,需要剔除fingeprint+message-integrity的属性
修改后如下:
00 01 00 48 21 12 a4 42 78 2b 66 6b 32 34 30 6b
4e 51 6a 56 00 06 00 0d 36 37 76 32 37 30 37 35
3a 31 33 42 5a 00 00 00 c0 57 00 04 00 02 00 00
80 2a 00 08 70 fb e5 05 91 bf 83 3c 00 24 00 04
6e 7e 1e ff 00 08 00 14 c7 c4 9a 60 94 6f a0 24
e5 f6 21 2e c6 38 14 fe 2e 76 b2 6d 80 28 00 04
3a c7 02 9f
将此内容作为输入,key为answer的密码:745s295z8lv458ll46w2467ta460562n,经过网站 ( https://www.liavaag.org/English/SHA-Generator/HMAC/ )校验后内容为
内容与抓包的数据值相同
2.3:FINGERPRINT
属性类型:0x8028
属性长度:固定是4字节,因为值是经过4字节异或的。
属性值:0x5354554e异或CRC32(内容); 内容是STUN头(20字节)+STUN属性体 (排除本属性)的buffer,且buffer内容是整个内容填充好后的buffer ;截取长度是HEADER.length + 20 - 8(fingerprint属性长度)
例如:buffer内容去红框内,且头的len字段不需要修改
计算crc32
https://www.lammertbies.nl/comm/info/crc-calculation 或者
http://sunshine2k.de/coding/javascript/crc/crc_js.html
计算后的crc32是0x712D1962 与 0x5354554e 取异或 =
http://xor.pw/#
2.4:ICE-CONTROLED
属性类型:0x8029
属性长度:固定是8字节
属性值:Tie breaker: 是一个64bits的随机值
2.5:ICE-CONTROLLING
属性类型:0x802a
属性长度:固定是8字节
属性值:Tie breaker: 是一个64bits的随机值
2.6:XOR-MAPPED-ADDRESS
属性类型:0x0020
属性长度:IPV4:8字节;IPV6:20字节
属性值:8位的固定值0 + 8位的协议簇类型 + 16位的端口号 + 地址异或
协议簇类型为:1:IPV4;2:IPV6
端口号:{}端口号} 异或 {魔术字的前2个字节(0x2112)}
地址:{IPV4是4字节} 异或 {魔术字(magic cookie)}
{IPV6是16字节} 异或 {魔术字(magic cookie) + 事务ID}
3:如果端口复用
需要根据stun的关键位判断进行解复用。