stun協議筆記一(stun格式簡介)

一、stun協議格式

1、STUN報文頭

1)最高的2位必須置零,這可以在當STUN和其他協議複用的時候,用來區分STUN包和其他數據包。

2)STUN Message Type 字段定義了消息的類型(請求/成功響應/失敗響應/指示)和消息的主方法。
雖然我們有4個消息類別,但在STUN中只有兩種類型的事務,即請求/響應類型和指示類型。響應類型分爲成功和出錯兩種,用來幫助快速處理STUN信息。Message Type字段又可以進一步分解爲如下結構:

其中顯示的位爲從最高有效位M11到最低有效位M0,M11到M0表示方法的12位編碼。C1和C0兩位表示類的編碼。

因此:MessageType=MessageClass | MessageMethod

例如對於binding方法來說,

MessageClass定義:0b00表示request,0b01表示indication,0b10表示success response,0b11表示error response

Message Method定義爲0x001

所以binding的MessageType的定義如下枚舉值:

每一個method都有可能對應不同的傳輸類別。方法和類是正交的,因此對於每種方法,對該方法的請求,成功響應,錯誤響應和指示都是可能的。拓展定義新方法的時候注意要指定該方法允許哪些類型的消息。

根據RFC5766定義,音視頻通訊經常使用的Stun Methods定義如下:

3)Message Length 字段存儲了信息的長度,以字節爲單位,不包括20字節的STUN頭部。由於所有的STUN屬性都是都是4字節對齊(填充)的,因此這個字段最後兩位應該恆等於零,這也是辨別STUN包的一個方法之一。

4)Magic Cookie 字段包含固定值0x2112A442,這是爲了前向兼容RFC3489,因爲在classic STUN中,這一區域是事務ID的一部分。另外選擇固定數值也是爲了服務器判斷客戶端是否能識別特定的屬性。還有一個作用就是在協議多路複用時候也可以將其作爲判斷標誌之一

5)Transaction ID 字段是個96位的標識符,用來區分不同的STUN傳輸事務。對於request/response傳輸,事務ID由客戶端選擇,服務器收到後以同樣的事務ID返回response;對於indication則由發送方自行選擇。事務ID的主要功能是把request和response聯繫起來,同時也在防止攻擊方面有一定作用。服務端也把事務ID當作一個Key來識別不同的STUN客戶端,因此必須格式化且隨機在0~2^(96-1)之間。重發同樣的request請求時可以重用相同的事務ID,但是客戶端進行新的傳輸時,必須選擇一個新的事務ID。

2、STUN報文屬性(attributes)

在STUN報文頭部之後,通常跟着0個或者多個屬性,每個屬性必須是TLV編碼的(Type-Length-Value)。其中Type字段和Length字段都是16位,Value字段爲爲32位表示,如下:

  • attributes的Type定義如下:

  • webrtc的代碼定義:

  • wireshark抓包示例:

下面簡要介紹幾個常見屬性的定義:

1)MAPPED-ADDRESS

MAPPED-ADDRESS用來表示NAT客戶端的反射地址。

Family爲IP類型,即IPV4(0x01)或IPV6(0x02),Port爲端口,Address爲32位或128位的IP地址。注意Family前面的高8位必須全部置零,而且接收端必須要將其忽略掉。

 

2)XOR-MAPPED-ADDRESS

和MAPPED-ADDRESS基本相同,不同點是反射地址部分經過了一次異或(XOR)處理。

對於X-Port字段,是將NAT的映射端口以小端形式與magic cookie的高16位進行異或,再將結果轉換成大端形式而得到的,X-Address也是類似。

之所以要經過這麼一次轉換,是因爲在實踐中發現很多NAT會修改payload中自身公網IP的32位數據,從而導致NAT打洞失敗。

3)ERROR-CODE

該屬性用於error response報文中。包含了300-699表示的錯誤代碼,以及一個UTF-8格式的文字出錯信息(Reason Phrase)。

其中返回碼定義:

300:嘗試代替(Try Alternate),客戶端應該使用該請求聯繫一個代替的服務器。這個錯誤響應僅在請求包括一個 USERNAME屬性和一個有效的MESSAGE-INTEGRITY屬性時發送;否則它不會被髮送,而是發送錯誤代碼爲400的錯誤響應;
400:錯誤請求(Bad Request),請求變形了,客戶端在修改先前的嘗試前不應該重試該請求。
401:未授權(Unauthorized),請求未包括正確的資格來繼續。客戶端應該採用一個合適的資格來重試該請求。
420:未知屬性(Unknown Attribute),服務器收到一個STUN包包含一個強制理解的屬性但是它不會理解。服務器必須將不認識的屬性放在錯誤響應的UNKNOWN-ATTRIBUTE屬性中。
438:過期Nonce(Stale Nonce),客戶端使用的Nonce不再有效,應該使用響應中提供的Nonce來重試。
500:服務器錯誤(Server Error),服務器遇到臨時錯誤,客戶端應該再次嘗試。

其餘的還有:

可以翻閱rfc5389協議15小節、RFC5766定義。

參考:

RFC5389

RFC3489

RFC5766

https://www.jianshu.com/p/227bb04179c8

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章