P2P學習(三)網絡傳輸基本知識---STUN協議(一)


一:STUN協議介紹

(一)STUN協議簡介

STUN 存在的目的就是進行NAT穿越,NAT有四種類型,每種類型如何穿越,它的基本原理是什么,都是屬於STUN協議中的一部分。

(二)RFC STUN規范

RFC STUN規范中,實際上有兩套STUN規范:

規范一:RFC3489

STUN的全稱是Simple Traversal of User Datagram Protocol (UDP) Through Network Address Translators (NATs),即穿越NAT的簡單UDP傳輸,

是一個輕量級的協議,允許應用程序發現自己和公網之間的中間件類型,同時也能允許應用程序發現自己被NAT分配的公網IP

它就是將STUN定義成簡單的通過UDP進行NAT穿越的一套規范,也就是告訴你如何一步一步通過UDP進行穿越,但是這套規范在穿越的過程中還是存在很多問題,尤其是現在的網絡

路由器對UDP的限制比較多,有的路由器甚至不允許進行UDP傳輸,所以這就導致了我們通過RFC3489這套規范進行NAT穿越的時候它的失敗率會非常高。所以為了解決這個問題,

又定義了另一套標准,RFC5389.

規范二:RFC5389

1.RFC5389中,STUN的全稱為Session Traversal Utilities for NAT,即NAT環境下的會話傳輸工具,是一種處理NAT傳輸的協議,但主要作為一個工具來服務於其他協議。

和STUN/RFC3489類似,可以被終端用來發現其公網IP和端口,同時可以檢測端點間的連接性,也可以作為一種保活(keep-alive)協議來維持NAT的綁定。

和RFC3489最大的不同點在於,STUN本身不再是一個完整的NAT傳輸解決方案,而是在NAT傳輸環境中作為一個輔助的解決方法,同時也增加了TCP的支持

RFC5389廢棄了RFC3489,因此后者通常稱為classic STUN,但依舊是后向兼容的。而完整的NAT傳輸解決方案則使用STUN的工具性質,ICE就是一個基於offer/answer方法的完整NAT傳輸方案,如SIP

2.RFC5389是在RFC3489的基礎上又增加了一些功能,但是它對整個STUN的描述就不一樣了, 它是把STUN描述成一系列穿越NAT的工具,所以都叫STUN,但是他們的含義完全就不一

樣了。RFC5389在UDP嘗試可能失敗的情況下,嘗試使用TCP,也就是說RFC5389是包括UDP和TCP的兩種協議進行NAT穿越的,這是兩套規范最本質的區別。當然在協議的具體內

容上,包括協議頭還有協議體中的屬性都有很多的變化,但是那些都不是最關鍵的,最關鍵的是RFC5389里面將TCP納入進來。你可以通過TCP進行穿越。

這是STUN 的RFC的兩套規范。大家一定要清楚,尤其是查文檔的 時候一定要清楚查詢的是哪一套規范。

二:STUN協議詳解

STUN是一個C/S架構的協議,支持兩種傳輸類型

一種是請求/響應(request/respond)類型,由客戶端給服務器發送請求,並等待服務器返回響應;

另一種是指示類型(indication transaction),由服務器或者客戶端發送指示,另一方不產生響應。

兩種類型的傳輸都包含一個96位的隨機數作為事務ID(transaction ID),

對於請求/響應類型,事務ID允許客戶端將響應和產生響應的請求連接起來;
對於指示類型,事務ID通常作為debugging aid使用。

所有的STUN報文信息都含有一個固定頭部(類型+長度+事務ID,3個字段),包含了方法,類和事務ID

方法表示是具體哪一種傳輸類型---由type字段剩下的12位決定(兩種傳輸類型<RFC3489中有兩種>又分了很多具體類型),STUN/RFC5389中只定義了一個方法,即binding(綁定),其他的方法可以由使用者自行拓展;

Binding方法可以用於請求/響應類型和指示類型,用於前者時可以用來確定一個NAT給客戶端分配的具體綁定,用於后者時可以保持綁定的激活狀態。類表示報文類型是請求/成功響應/錯誤響應/指示---由(C0C1)決定

在固定頭部之后是零個或者多個屬性(attribute),長度也是不固定的。

下面我們就具體看看這個STUN協議:

STUN這個協議它是包括了消息頭和消息體,消息頭是20字節固定的消息頭,Body中可以有0個或者多個Attribute屬性,后面我們會介紹屬性的作用。

(一)消息頭(固定20字節)

第三個是事物ID,它是16字節或128bit組成,它的作用就是請求和響應事物是相同的ID,用於請求與響應的匹配的:

比如我客戶端發送了好幾個請求,那服務端對於每一個請求都要返回一個響應 ,那怎么知道某個響應是對應到的請求呢,就通過這個事物ID。如果它事物ID號相同,說明這兩是匹配的,整個邏輯就知道怎么做了,否則的話就很難判斷。

所以它有三部分組成,第一是兩個字節的類型,第二是兩個類型的消息長度,不包括這個消息頭,第三個是16字節的128位的事物ID,請求與響應的匹配。這個是消息頭。

消息頭的格式

上圖的格式是最新的RFC5389的格式,剛剛我們上面說三個的是RFC3489,那么RFC5389和RFC3489之間有什么區別呢?

首先我看消息類型,消息類型的最低兩位必須是 0 0,就是RFC5389最新的協議 ,這是第一點的不同;
第二點的不同是,事物ID,老的里面是128位事物ID,在新的里面是 96位,其中有32位單獨划出來了單獨作為 Magic Cookie,一個魔法數,
以上兩點就是RFC3489和5389的STUN消息頭的區別。

下面我們再來看每一項,首先是這個STUN Message Type(2字節==16位)

1.前兩位必須是00,以區分復用同一端口時STUN協議:就是不同的兩個STUN協議復用同一個端口的時候,用它來區分哪個是最新的STUN協議RFC5389,哪個是老的STUN協議RFC3489,這是兩位00的作用。
2.剩下的14位中有兩位用於分類,就是C0和C1,C0和C1是占兩位,所以它有四種類型,也就是四個分類,第一種是請求,第二種是指示,第三種是成功,第四種是錯誤應答,所以它將Message Type消息類型分成了四類。
3.剩下的12位是用於定義請求和指示,比如1代表綁定,2代表私有消息隱私數據,……,但是在STUN 3489里面定義了兩個,就是用這12位定義了兩種,但是5389里面就一種,一種就夠了。

下圖就是STUN Message Type的結構中的C0C1用於分類:

14位其中C0和C1分別在上圖中兩個不同位置,兩個不是放在一起的,它是隔着的,隔着有什么好處,就是按照16進制的話,我們4位為一組,所有的M代表的是請求的值,C是分類,

這樣划分,四個一組,第一組里面全都是請求,都是消息類型,第二組里面代表分類,第三組里面又代表另外一種分類。所以這兩個進行不同的組合就能分成不同的類型了。

我們來看 C1C0:

C1C0第一個是C1第二個是C0。因為這個C1是處於這個高字節(存放在左側低地址),對於網絡數據對於協議分析對於二進制數據處理的人來說,這些都是比較容易理解的,對於沒有接觸過這些知識的

人可能稍微有點麻煩。

0b00:表式是一個請求 0b01:表示是一個指示 0b10:表示是請求成功的響應 0b11:表示是請求失敗的響應

所以這里我們只要記住成功響應和失敗的響應就好了。

下圖就是STUN Message Type的結構中的最后12位定義的不同消息類型

下面我們就可以看一下STUN的消息類型,它一共定義了6個消息類型,這個就是STUN的消息類型,但是RCF5389就將這個私密類型去掉了。就剩下一個 ,那完全夠用了。

通過大小端模式理解C0C1:

對於這部分類型,為什么要了解呢,就是后面要對C0和C1要做詳細的解釋。

大端模式:數據的高字節保存在內存的低地址中
小端模式:數據的高字節保存在內存的高地址中
網絡字節順序:采用大端排序方式

了解這個模式之后,我們在聊C0和C1它是怎么排序的,大家就會很清楚它是怎么排序的。 

圖片為內存圖,左側為低地址,右側為高地址!

網絡字節排序采用大端,所以對於數據0x0001左側(數據高字節)在內存的低地址中,先進行發送。如下圖所示:0x0001中的1為數據低字節,卻存放在內存最右側(高地址)中!

0x0001:結合C1C0,可以知道,00是表示是一個請求消息
0x0101:C1為1,C0是0,是請求成功響應消息
0x0111:C1為1,C0是1,是請求失敗的響應

其中最后一個數字表示具體的請求(是前面所提到的12位中的內容,1表示綁定)

下面這個字段是事物ID

新的RFC5389將它分成了兩部分,前四個字節也就是32位是一個magic cookie,magic就是一個魔法數了,在這里是固定的0x2112A442,所以我們看到固定的值是這個的話,就是

RFC5389否則就是RFC3489。

1.前面4字節,32位,固定值0x2112A442. 通過它可以判斷客戶端是否可以識別某些屬性。

通過它是可以識別客戶端是否可以識別某些屬性,因為不同的規范屬性實際上是有變化的,所以你看到 這個魔法數之后就是RFC5389, RFC5389定義了一些新的屬性,如果不是的

話,這些新的屬性就可以忽略掉。

2.后面12字節 ,96位,標識同一個事物的請求和響應

剩下的12個字節,96位,標識同一個事物的請求和響應,當我們客戶端發送多個請求的時候,就能通過這個事物ID將服務端返回的響應與之前發送的請求進行一一匹配。

字段是個96位的標識符,用來區分不同的STUN傳輸事務。對於request/response傳輸,事務ID由客戶端選擇,服務器收到后以同樣的事務ID返回response;對於indication則由發送方自行選擇。

事務ID的主要功能是把request和response聯系起來,同時也在防止攻擊方面有一定作用。服務端也把事務ID當作一個Key來識別不同的STUN客戶端,因此必須格式化且隨機在0~2^(96-1)之間。

重發同樣的request請求時可以重用相同的事務ID,但是客戶端進行新的傳輸時,必須選擇一個新的事務ID。

(二)消息體

下面再看STUN Message Body 消息體,消息頭后有0或多個屬性。每個屬性都使用TLV(動態)編碼:Type,Length,Value

Length字段:

Value這個值是可以變化的,變化的程度怎么知道有多長呢?通過這個Length,這個Length標示了Value的長度,最終的消息是一個32位對齊的,如果最后不是32位對齊,要通過補0來達到對齊,這是整個Body。

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

Type字段:

為屬性的類型。任何屬性類型都有可能在一個STUN報文中出現超過一次。

除非特殊指定,否則其出現的順序是有意義的:即只有第一次出現的屬性會被接收端解析,而其余的將被忽略。為了以后版本的拓展和改進,屬性區域被分為兩個部分。

Type值在0x0000-0x7FFF之間的屬性被指定為強制理解,意思是STUN終端必須要理解此屬性,否則將返回錯誤信息;

而0x8000-0xFFFF之間的屬性為選擇性理解,即如果STUN終端不識別此屬性則將其忽略。

目前STUN的屬性類型由IANA維護。

這里列舉定義的屬性Type:

這里簡要介紹幾個常見屬性的Value結構:

1.MAPPED-ADDRESS

MAPPED-ADDRESS同時也是classic STUN的一個屬性,之所以還存在也是為了前向兼容。其包含了NAT客戶端的反射地址,
Family為IP類型,即IPV4(0x01)或IPV6(0x02),Port為端口,Address為32位或128位的IP地址。
注意高8位必須全部置零,而且接收端必須要將其忽略掉。

2.XOR-MAPPED-ADDRESS 

XOR-MAPPED-ADDRESS和MAPPED-ADDRESS基本相同,不同點是反射地址部分經過了一次異或(XOR)處理。對於X-Port字段,
是將NAT的映射端口以小端形式與magic cookie的高16位進行異或,再將結果轉換成大端形式而得到的,X-Address也是類似。
之所以要經過這么一次轉換,是因為在實踐中發現很多NAT會修改payload中自身公網IP的32位數據,從而導致NAT打洞失敗。

3.ERROR-CODE

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

另外,錯誤代碼在語義上還與SIP和HTTP協議保持一致。比如:

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),服務器遇到臨時錯誤,客戶端應該再次嘗試。

此外還有很多屬性,如USERNAME,NONCE,REALM,SOFTWARE等,具體可以翻閱RFC3489

屬性的使用時機:(與具體有出入,以抓包內容為主)

M:必須
O:可選
N/A:沒有
C:客戶端使用

表示很無語.......


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM