STUN和TURN技術淺析
在現實Internet網路環境中,大多數計算機主機都位於防火牆或NAT之後,只有少部分主機能夠直接接入Internet。很多時候,我們希望網路中的兩臺主機能夠直接進行通訊,即所謂的P2P通訊,而不需要其他公共伺服器的中轉。由於主機可能位於防火牆或NAT之後,在進行P2P通訊之前,我們需要進行檢測以確認它們之間能否進行P2P通訊以及如何通訊。這種技術通常稱為NAT穿透(NAT Traversal)。最常見的NAT穿透是基於UDP的技術,如RFC3489中定義的STUN協議。
STUN,首先在RFC3489中定義,作為一個完整的NAT穿透解決方案,英文全稱是Simple Traversal of UDP Through NATs,即簡單的用UDP穿透NAT。
在新的RFC5389修訂中把STUN協議定位於為穿透NAT提供工具,而不是一個完整的解決方案,英文全稱是Session Traversal Utilities for NAT,即NAT會話穿透效用。RFC5389與RFC3489除了名稱變化外,最大的區別是支援TCP穿透。
TURN,首先在RFC5766中定義,英文全稱是Traversal Using Relays around NAT:Relay Extensions to Session Traversal Utilities for NAT,即使用中繼穿透NAT:STUN的擴充套件。簡單的說,TURN與STURN的共同點都是通過修改應用層中的私網地址達到NAT穿透的效果,異同點是TURN是通過兩方通訊的“中間人”方式實現穿透。
1 STUN
瞭解STUN之前,我們需要了解NAT的種類。
NAT對待UDP的實現方式有4種,分別如下:
1. Full Cone NAT
完全錐形NAT,所有從同一個內網IP和埠號傳送過來的請求都會被對映成同一個外網IP和埠號,並且任何一個外網主機都可以通過這個對映的外網IP和埠號向這臺內網主機發送包。
2. Restricted Cone NAT
限制錐形NAT,它也是所有從同一個內網IP和埠號傳送過來的請求都會被對映成同一個外網IP和埠號。與完全錐形不同的是,外網主機只能夠向先前已經向它傳送過資料包的內網主機發送包。
3. Port Restricted Cone NAT
埠限制錐形NAT,與限制錐形NAT很相似,只不過它包括埠號。也就是說,一臺IP地址X和埠P的外網主機想給內網主機發送包,必須是這臺內網主機先前已經給這個IP地址X和埠P傳送過資料包。
4. Symmetric NAT
對稱NAT,所有從同一個內網IP和埠號傳送到一個特定的目的IP和埠號的請求,都會被對映到同一個IP和埠號。如果同一臺主機使用相同的源地址和埠號傳送包,但是發往不同的目的地,NAT將會使用不同的對映。此外,只有收到資料的外網主機才可以反過來向內網主機發送包。
1.1 RFC3489/STUN
STUN(Simple Traversal of User Datagram Protocol Through Network Address Translators),即簡單的用UDP穿透NAT,是個輕量級的協議,是基於UDP的完整的穿透NAT的解決方案。它允許應用程式發現它們與公共網際網路之間存在的NAT和防火牆及其他型別。它也可以讓應用程式確定NAT分配給它們的公網IP地址和埠號。STUN是一種Client/Server的協議,也是一種Request/Response的協議,預設埠號是3478。
1.1.1 報文結構
Ø 訊息頭
所有的STUN訊息都包含20個位元組的訊息頭,包括16位的訊息型別,16位的訊息長度和128位的事務ID。
位元組
0 1 2 3
訊息型別 |
訊息長度 |
事務ID |
訊息型別許可的值如下:
0x0001:捆綁請求
0x0101:捆綁響應
0x0111:捆綁錯誤響應
0x0002:共享私密請求
0x0102:共享私密響應
0x0112:共享私密錯誤響應
訊息長度,是訊息大小的位元組數,但不包括20位元組的頭部。
事務ID,128位的識別符號,用於隨機請求和響應,請求與其相應的所有響應具有相同的識別符號。
Ø 訊息屬性
訊息頭之後是0或多個屬性,每個屬性進行TLV編碼,包括16位的屬性型別、16位的屬性長度和變長屬性值。
位元組
0 1 2 3
屬性型別 |
屬性長度 |
屬性值 |
|
…… |
屬性型別定義如下:
MAPPED-ADDRESS
MAPPED-ADDRESS屬性表示對映過的IP地址和埠。它包括8位的地址族,16位的埠號及長度固定的IP地址。
RESPONSE-ADDRESS
RESPONSE-ADDRESS屬性表示響應的目的地址
CHASNGE-REQUEST
客戶使用32位的CHANGE-REQUEST屬性來請求伺服器使用不同的地址或埠號來發送響應。
SOURCE-ADDRESS
SOURCE-ADDRESS屬性出現在捆綁響應中,它表示伺服器傳送響應的源IP地址和埠。
CHANGED-ADDRESS
如果捆綁請求的CHANGE-REQUEST屬性中的“改變IP”和“改變埠”標誌設定了,則CHANGED-ADDRESS屬性表示響應發出的IP地址和埠號。
USERNAME
USERNAME屬性用於訊息的完整性檢查,用於訊息完整性檢查中標識共享私密。USERNAME通常出現在共享私密響應中,與PASSWORD一起。當使用訊息完整性檢查時,可有選擇地出現在捆綁請求中。
PASSWORD
PASSWORD屬性用在共享私密響應中,與USERNAME一起。PASSWORD的值是變長的,用作共享私密,它的長度必須是4位元組的倍數,以保證屬性與邊界對齊。
MESSAGE-INTEGRITY
MESSAGE-INTEGRITY屬性包含STUN訊息的HMAC-SHA1,它可以出現在捆綁請求或捆綁響應中;MESSAGE-INTEGRITY屬性必須是任何STUN訊息的最後一個屬性。它的內容決定了HMAC輸入的Key值。
ERROR-CODE
ERROR-CODE屬性出現在捆綁錯誤響應或共享私密錯誤響應中。它的響應號數值範圍從100到699。
下面的響應號,與它們預設的原因語句一起,目前定義如下:
400(錯誤請求):請求變形了。客戶在修改先前的嘗試前不應該重試該請求。
401(未授權):捆綁請求沒有包含MESSAGE-INTERITY屬性。
420(未知屬性):伺服器不認識請求中的強制屬性。
430(過期資格):捆綁請求沒有包含MESSAGE-INTEGRITY屬性,但它使用過期
的共享私密。客戶應該獲得新的共享私密並再次重試。
431(完整性檢查失敗):捆綁請求包含MESSAGE-INTEGRITY屬性,但HMAC驗
證失敗。這可能是潛在攻擊的表現,或者客戶端實現錯誤
432(丟失使用者名稱):捆綁請求包含MESSAGE-INTEGRITY屬性,但沒有
USERNAME屬性。完整性檢查中兩項都必須存在。
433(使用TLS):共享私密請求已經通過TLS(Transport Layer Security,即安全
傳輸層協議)傳送,但沒有在TLS上收到。
500(伺服器錯誤):伺服器遇到臨時錯誤,客戶應該再次嘗試。
600(全域性失敗):伺服器拒絕完成請求,客戶不應該重試。
UNKNOWN-ATTRIBUTES
UNKNOWN-ATTRIBUTES屬性只存在於其ERROR-CODE屬性中的響應號為420的捆綁錯誤響應或共享私密錯誤響應中。
REFLECTED-FROM
REFLECTED-FROM屬性只存在於其對應的捆綁請求包含RESPONSE-ADDRESS屬性的捆綁響應中。屬性包含請求發出的源IP地址,它的目的是提供跟蹤能力,這樣STUN就不能被用作DOS攻擊的反射器。
屬性空間分為可選部分與強制部分,值超過0x7fff的屬性是可選的,即客戶或伺服器即使不認識該屬性也能夠處理該訊息;值小於或等於0x7fff的屬性是強制理解的,即除非理解該屬性,否則客戶或伺服器就不能處理該訊息。
1.1.2 實現原理
圖1:STUN
STUN協議的完整互動過程如上,下面我們來介紹具體實現步驟。
一般情況下,客戶會配置STUN伺服器提供者的域名,該域名被解析為IP地址和SRV過程的埠號。伺服器名是“stun”,使用UDP協議傳送捆綁請求,使用TCP協議傳送共享私密請求。STUN協議的預設埠號為3478。
若要提供完整性檢查,STUN在客戶和伺服器間使用128位的共享私密,作為在捆綁請求和捆綁響應中的密匙。
首先,客戶通過發現過程獲得它將與之建立TCP連線的IP地址和埠號。客戶開啟該地址和埠的連線,開始TLS協商,驗證伺服器的標識。客戶傳送共享私密請求。該請求沒有屬性,只有頭。伺服器生成響應。
客戶會在該連線上生成多個請求,但在獲得使用者名稱和密碼後關閉該連線。
伺服器收到共享私密請求,驗證從TLS連線上到達的該請求;如果不是通過TLS收到的請求,則生成共享私密錯誤響應,並設定ERROR-CODE屬性為響應號433;這裡區分兩種情況:若通過TCP收到請求,則錯誤響應通過收到請求的相同連線傳送;若通過UDP收到請求,則錯誤響應傳送回請求送出的源IP和埠。
伺服器檢查請求中的任何屬性,當其中有不理解的小於或等於0x7fff的值,則生成共享私密錯誤響應,設定ERROR-CODE屬性為響應號420,幷包括UNKNOWN-ATTRIBUTE屬性,列出它不理解的小於或等於0x7fff的屬性的值。該錯誤響應通過TLS連線傳送。
若請求正確,伺服器建立共享私密響應,包含與請求中相同的事務ID,幷包含USERNAME和PASSWORD屬性。使用者名稱在10分鐘內有效。
共享私密響應通過與收到請求的相同的TLS連線傳送,伺服器保持連線開啟狀態,由客戶關閉它。
接著,客戶傳送捆綁請求,攜帶的屬性包括:
可選屬性:RESPONSE-ADDRESS屬性和CHANGE-REQUEST屬性;
強制屬性:MESSAGE-INTEGRITY屬性和USERNAME屬性。
客戶傳送捆綁請求,通過客戶重傳來提供可靠性。客戶開始用100ms的間隔重傳,每次
重傳間隔加倍,直至1.6秒。之間間隔1.6秒的重傳繼續,直到收到響應或總共已經發送了9次。因此,若9500ms後,還未收到響應,客戶認為傳輸已經失敗。
伺服器檢查捆綁請求的MESSAGE-INTEGRITY屬性,不存在則生成捆綁錯誤響應,設定ERROR-CODE屬性為響應號401;若存在,計算請求的HMACKey值。
伺服器檢查USERNAME屬性,不存在則生成捆綁錯誤響應,設定ERROR-CODE屬性為響應號432;若存在,但不認識該USERNAME的共享私密(例如,它超時了),生成捆綁錯誤響應,設定ERROR-CODE屬性為響應號430。
若伺服器知道該共享私密,但所計算的HMAC與請求的不同,生成捆綁錯誤響應,設定ERROR-CODE屬性為響應號431。
假設訊息完整性檢查通過了,伺服器檢查請求中的任何屬性的值,若遇到不理解的小於或等於0x7fff的值,生成捆綁錯誤響應,設定ERROR-CODE屬性為響應號420,該響應包含UNKNOWN-ATTRIBUTE屬性,並列出不理解的小於或等於0x7fff的屬性。
若請求正確,伺服器生成單個捆綁響應,包含與捆綁請求相同的事務ID。伺服器在捆綁響應中加入MAPPED-ADDRESS屬性,該屬性的IP地址和埠號為捆綁請求的源IP地址和埠號。
捆綁響應的源地址和埠號取決於捆綁請求中CHANGE-REQUEST屬性的值及捆綁請求收到的地址和埠號相關。總結如下:
標誌 |
源地址 |
源埠號 |
CHANGED-ADDRESS |
無 |
Da |
Dp |
Ca:Cp |
改變IP |
Ca |
Dp |
Ca:Cp |
改變埠號 |
Da |
Cp |
Ca:Cp |
改變IP且改變埠號 |
Ca |
Cp |
Ca:Cp |
表1:標誌對資料包源和CHANGED-ADDRESS的影響
伺服器在捆綁響應中加入SOURCE-ADDRESS屬性,包含用於傳送捆綁響應的源地址和埠號;加入CHANGED-ADDRESS屬性,包含源IP地址和埠號。
如果捆綁請求中包含了USERNAME和MESSAGE-INTEGRITY屬性,則伺服器在捆綁響應中加入MESSAGE-INTEGRITY屬性。
如果捆綁請求包含RESPONSE-ADDRESS屬性,則伺服器在捆綁響應中加入REFLECTED-FROM屬性:如果捆綁請求使用從共享私密請求獲得的使用者名稱進行認證,則REFLECTED-FROM屬性包含共享私密請求到達的源IP地址和埠號;若請求中的使用者名稱不是使用共享私密分配的,則REFLECTED-FROM屬性包含獲得該使用者名稱的實體的源IP地址和埠號;若請求中沒有使用者名稱,且伺服器願意處理該請求,則REFLECTED-FROM屬性包含請求發出的源IP地址和埠號。
伺服器不會重傳響應,可靠性通過客戶週期性地重發請求來保障,每個請求都會觸發伺服器進行響應。
客戶端判斷響應的型別是捆綁錯誤響應還是捆綁響應。捆綁錯誤響應通常在請求傳送的源地址和埠收到;捆綁響應通常在請求中的RESPONSE-ADDRESS屬性的地址和埠收到,若沒有該屬性,則捆綁響應將在請求傳送的源地址和埠號收到。
若是捆綁錯誤響應,客戶檢查響應中的ERROR-CODE屬性的響應號:400至499之間的未知屬性按屬性400處理,500至599之間的未知屬性按500處理,600至699之間的未知屬性按600處理。任何100和399之間的響應都會使請求重傳中止,但其他則忽略;若客戶收到響應的屬性型別大於0x7fff,則忽略該屬性,若小於或等於0x7fff,則請求重傳停止,並忽略整個響應;
若是捆綁響應,客戶檢查響應的MESSAGE-INTEGRITY屬性:如果不存在,客戶在請求中加入MESSAGE-INTEGRITY屬性,並放棄該響應;如果存在,客戶計算響應的HMAC。如果計算出的HMAC與響應中的不同,則放棄該響應,並警告客戶可能受到了攻擊;若計算出的HMAC與響應中的匹配,則過程繼續;
不論收到捆綁響應還是捆綁錯誤響應,都將中止該請求的重傳。客戶在第一次響應後繼續監聽捆綁請求的響應10秒鐘,如果這期間它收到任何訊息型別不同的響應或不同的MAPPED-ADDRESS屬性,它將警告使用者可能受到攻擊;並且,如果客戶收到的捆綁響應次數超過它傳送的捆綁請求數的兩倍,它將警告使用者可能受到攻擊;若捆綁響應經過認證,上述攻擊並未導致客戶丟棄MAPPED-ADDRESS,則客戶可以使用該MAPPED-ADDRESS和SOURCE-ADDRESS屬性。
1.1.3 STUN功能舉例
客戶通過帶外方式獲得STUN伺服器資訊後,就開啟對應的地址和埠的連線,並開始與STUN伺服器進行TLS協商。一旦打開了連線,客戶就通過TCP協議傳送共享私密請求,伺服器生成共享私密響應。STUN在客戶和伺服器間使用共享私密,用作捆綁請求和捆綁響應中的密匙。之後,客戶使用UDP協議向STUN伺服器傳送捆綁請求,當捆綁請求訊息到達伺服器的時候,它可能經過了一個或者多個NAT。結果是STUN伺服器收到的捆綁請求訊息的源IP地址被對映成最靠近STUN伺服器的NAT的IP地址,STUN伺服器把這個源IP地址和埠號複製到一個捆綁響應訊息中,傳送回擁有這個IP地址和埠號的客戶端。
當STUN客戶端收到捆綁響應訊息之後,它會將自己傳送捆綁請求時繫結的本地IP地址和埠號同捆綁響應訊息中的IP地址和埠號進行比較,如果不匹配,就表示客戶端正處於一個或者多個NAT的前面。
在Full-Cone NAT的情況下,在捆綁響應訊息中的IP地址和埠是屬於公網的,公網上的任何主機都可以使用這個IP地址和埠號向這個應用程式傳送資料包,應用程式只需要在剛才傳送捆綁請求的IP地址和埠上監聽即可。
當然,客戶可能並不在一個Full-Cone NAT的前面,實際上,它並不知道自己在一個什麼型別的NAT的前面。為了確定NAT的型別,客戶端使用附加的捆綁請求。具體過程是很靈活的,但一般都會像下面這樣工作:客戶端再發送一個捆綁請求,這次發往另一個IP地址,但是使用的是跟上一次同一個源IP地址和源埠號,如果返回的資料包裡面的IP地址和埠號和第一次返回的資料包中的不同,客戶端就會知道它是在一個對稱NAT的前面。客戶端為了確認自己是否在一個完全錐形NAT的前面,客戶端可以傳送一個帶有標誌的捆綁請求,這個標誌告訴伺服器使用另一個IP地址和埠傳送捆綁響應。換句話說,如果客戶端使X/Y的IP地址埠對向A/B的IP地址埠對傳送捆綁請求,伺服器就會使用源IP地址和源埠號為C/D的地址埠對向X/Y傳送捆綁響應。如果客戶端收到了這個響應,它就知道它是在一個Full-Cone NAT前面。
STUN協議允許客戶端請求伺服器從收到捆綁請求的IP地址往回發捆綁響應,但是要使用不同的埠號。這可以用來檢查客戶端是否在Port Restricted Cone NAT的前面還是在Restricted Cone NAT的前面。
1.2 RFC5389/STUN
STUN協議在RFC5389中被重新命名為Session Traversal Utilities for NAT,即NAT會話穿透效用。在這裡,NAT會話穿透效用被定位為一個用於其他解決NAT穿透問題協議的協議。它可以用於終端裝置檢查由NAT分配給終端的IP地址和埠號。同時,它也被用來檢查兩個終端之間的連線性,好比是一種維持NAT繫結表項的保活協議。STUN可以用於多種NAT型別,並不需要它們提供特殊的行為。
STUN本身不再是一種完整的NAT穿透解決方案,它相當於是一種NAT穿透解決方案中的工具。這是與RFC3489/STUN版本相比最重要的改變。
1.2.1 STUN用途
目前定義了三種STUN用途:
Interactive Connectivity Establishment(ICE)[MMUSIC-ICE],互動式連線建立
Client-initiated connections for SIP [SIP-OUTBOUND],用於SIP的客戶端初始化連線
NAT Behavior Discovery [BEHAVE-NAT],NAT行為發現
1.2.2 報文結構
Ø 訊息頭
STUN訊息頭為20位元組,後面緊跟0或多個屬性。STUN頭部包含一STUN訊息型別、magic cookie、事務ID和訊息長度。
0 1 2 3
00 |
STUN訊息型別 |
訊息長度 |
魔術字 |
||
事務ID(96位) |
每個STUN訊息的最高位前2位必須為0。當STUN協議為多個協議多路複用時若使用的是同一個埠,這可以用於與其他協議區分STUN資料包。
訊息型別確定訊息的類別(如請求、成功迴應、失敗迴應、標誌)。雖然這裡有四種訊息型別,但可以分為2類事務:請求/響應事務、標誌事務。
訊息型別欄位可進一步劃分為下面結構:
M11 |
M10 |
M9 |
M8 |
M7 |
C1 |
M6 |
M5 |
M4 |
C0 |
M3 |
M2 |
M1 |
M0 |
訊息型別定義如下:
0b00,表示請求
0b01,表示標誌
0b10,表示成功響應
0b11,表示錯誤響應
魔術字域必須包含固定的值0x2112A442。在RFC3489中,該域是事務ID的一部分。配置魔術字允許伺服器檢測客戶是否理解某些在改進的版本中增加的屬性。另外,還可用於STUN多路複用時與其他協議的包進行區分。
96位的事務ID用於唯一的識別STUN事務。對於請求/響應事務,事務ID由STUN客戶端來選擇;對於標誌事務,由代理(代理指支援STUN的客戶端或伺服器)來選擇併發送。它主要服務於與請求相關的響應,因此它也扮演著一個幫助阻止確定型別的攻擊的角色。伺服器使用事務ID來唯一的標識出所有客戶端的每一個事務。事務ID本身必須是唯一的,並且隨機的從0到2的96-1次方中選擇。重新發送相同的請求時,也必須使用新的事務ID。成功或錯誤響應必須攜帶與相對應的請求相同的事務ID。
訊息長度欄位不包括20位元組的STUN頭部。所有的STUN屬性必須填充為4位元組的倍數。訊息長度欄位的最後2位總是為0,這為區分STUN包與其他協議的包提供了另外一種方法。
Ø 訊息屬性
STUN頭之後是0或多個屬性。每個屬性都採用TLV編碼,16位的型別、16位的長度及可變長度的值。每個STUN屬性必須是4位元組邊界對齊。
位元組
0 1 2 3
屬性型別 |
屬性長度 |
屬性值 |
|
…… |
屬性空間被劃分為2個範圍。屬性的型別值在0x0000到0x7fff是強制理解屬性,這意味著除非STUN代理能夠理解這些屬性,否則將不能正常處理包含該屬性的訊息;屬性的型別值在0x8000到0xffff範圍是可選理解屬性,這意味著如果STUN代理不能理解它們的話這些屬性可以被忽略。
STUN屬性型別集由IANA維護。
MAPPED-ADDRESS
MAPPED-ADDRESS屬性標識了客戶端反向傳輸地址(對映後的地址),這個屬性只用於伺服器向後相容RFC3489的客戶端。
XOR-MAPPED-ADDRESS
XOR-MAPPED-ADDRESS屬性與MAPPED-ADDRESS屬性是相同的,除了這對映後的地址經過了異或處理。(注意,異或運算是其自身的逆運算,再異或一下就可以得出真實的MAPPED-ADDRESS)
USERNAME
USERNAME屬性用於訊息完整性。它採用USERNAME和PASSWORD組合方式用於訊息完整性檢查。
MESSAGE-INTEGRITY
MESSAGE-INTEGRITY屬性包含STUN訊息的HMAC-SHA1。它可以出現在任何型別的STUN訊息中。由於使用SHA1雜湊演算法,HMAC將會是20位元組。用作HMAC輸入的文字是STUN訊息,包括頭部,直到且包括MESSAGE-INTEGRITY屬性前面的屬性。除了FINGERPRINT屬性外,代理必須忽略其他出現在MESSAGE-INTEGRITY屬性後的任何屬性。
STUN訊息頭中的長度欄位的值必須包括直到MESSAGE-INTEGRITY屬性本身,但不包括任何在它之後的屬性。
FINGERPRINT
FINGERPRINT屬性可以存在於所有的STUN訊息中,提供輔助區分STUN資料包與其他協議資料包的功能。屬性的值為採用CRC32方式計算STUN訊息直到但不包括FINGERPRINT屬性的的結果,並與32位的值0x5354554e異或。
ERROR-CODE
ERROR-CODE屬性被用於錯誤響應訊息中。它包含一個在300至699範圍內的錯誤響應號。錯誤響應號定義如下:
300:嘗試代替,客戶端應該使用該請求聯絡一個代替的伺服器。這個錯誤響應僅在請求包括一個USERNAME屬性和一個有效的MESSAGE-INTEGRITY屬性時傳送;否則它不會被髮送,而是傳送錯誤程式碼為400的錯誤響應;
400:錯誤請求,請求是變形了,客戶在修改先前的嘗試前不應該重試該請求。
401:未授權,請求未包括正確的資格來繼續。客戶應該採用一個合適的資格來重試該請求。
420:未知屬性,伺服器收到一個STUN包包含一個強制理解的屬性但是它不會理解。伺服器必須將不認識的屬性放在錯誤響應的UNKNOWN-ATTRIBUTE屬性中。
438:過期Nonce,客戶使用的Nonce不再有效,客戶應該使用響應中提供的Nonce來重試。
500:伺服器錯誤,伺服器遇到臨時錯誤,客戶應該再次嘗試。
REALM
REALM屬性可能出現在請求和響應中。在請求中表示長期資格將在認證中使用。當在錯誤響應中出現表示伺服器希望客戶使用長期資格來進行認證。
NONCE
NONCE屬性可能出現在請求和響應訊息中。
UNKNOWN-ATTRIBUTES
UNKNOWN-ATTRIBUTES屬性只在錯誤程式碼為420的的錯誤響應中出現。
SOFTWARE
SOFTWARE屬性用於代理髮送訊息時包含版本的描述。它用於客戶端和伺服器。它的值包括製造商和版本號。該屬性對於協議的執行沒有任何影響,僅為診斷和除錯目的提供服務。SOFTWARE屬性是個可變長度的,採用UTF-8編碼的小於128個字元的序列號。
ALTERNATE-SERVER
ALTERNATE-SERVER屬性標識一個備份的傳輸地址表明一個STUN客戶可以嘗試的不同的STUN伺服器。屬性格式與MAPPED-ADDRESS相同。IP地址族必須與請求的源IP地址的相同。
1.3 RFC5389與RFC3489的區別
RFC5389與RFC3489的不同點如下:
去掉STUN是一種完整的NAT穿透方案的概念,現在是一種用於提供NAT穿透解決方案的工具。因而,協議的名稱變為NAT會話穿透效用;
定義了STUN的用途;
去掉了STUN關於NAT型別檢測和繫結生命期發現的用法,去掉了RESPONSE-ADDRESS、CHANGED-ADDRESS、CHANGE-REQUEST、SOURCE-ADDRESS和REFLECTED-FROM屬性;
增加了一個固定的32位的魔術字欄位,事務ID欄位減少了32位長度;
增加了XOR-MAPPED-ADDRESS屬性,若魔術字在捆綁請求中出現時,該屬性包括在捆綁響應中。否則,RFC3489中的行為是保留的(換句話說,捆綁響應中包括MAPPED-ADDRESS);
介紹了訊息型別欄位的正式結構,帶有一對明確的位來標識Request、Response、Error-Response或Indication訊息。因此,訊息型別欄位被劃分為類別和方法兩部分;
明確的指出了STUN的最高2位是0b00,當用於ICE時可以簡單的與RTP包區分開來;
增加指紋屬性來提供一種明確的方法來檢測當STUN協議多路複用時,STUN與其他協議之間的差異;
增加支援IPv6,IPv4客戶端可以獲取一個IPv6對映地址,反之亦然;
增加一個long-term-credential-based認證機制;
增加了SOFTWARE、REALM、NONCE和ALTERNATE-SERVER屬性;
去掉了共享密匙方法,因此PASSWORD屬性也去掉了;
去掉了使用連續10秒偵聽STUN響應來識別一個攻擊的做法;
改變事務計時器來增加TCP友好性;
去掉了STUN例子如集中分離控制和媒體面,代替的,在使用STUN協議時提供了更多的資訊;
定義了一類填充機制來改變長度屬性的說明;
REALM、SERVER、原因語句和NONCE限制在127個字元,USERNAME限制在513個位元組以內;
為TCP和TLS改變了DNS SRV規程,UDP仍然和以前保持一致;
1.4 新特性介紹
1.4.1 指紋機制
FINGERPRINT機制是一種可選的用於其他協議多路複用STUN時傳送給相同的傳輸地址時區分STUN資料包的機制,該機制不支援與RFC3489相相容。
在一些用途中,基於相同的傳輸地址時多個協議會多路複用STUN訊息,例如RTP協議。STUN訊息必須首先和應用報文分離開。目前,在STUN報頭中有3種固定的欄位可以用於該目的。儘管如此,在一些案例中,三種固定欄位仍然不能充分的區別開。
當擴充套件的指紋機制被使用時,STUN代理在傳送給其他STUN代理的訊息中包括FINGERPRINT屬性。當其他STUN代理收到時,除基本的檢查之外,還將檢查是否包含FINGERPRINT屬性及它是否包含正確的值,至此,它將相信這是一個STUN訊息。指紋機制幫助STUN代理檢查其他協議那些看起來像是STUN訊息的訊息。
1.4.2 通過DNS發現伺服器機制
STUN客戶端可以使用DNS來發現STUN伺服器的IP地址和埠。客戶端必須知道伺服器的域名。
當客戶端希望找出伺服器在公網上的位置就採用捆綁請求/響應事務,SRV(資源記錄表)中伺服器名稱是“stun”。當通過TLS會話採用捆綁請求/響應事務,SRV中伺服器名稱為“stuns”。STUN使用者可以定義額外的DNS資源記錄服務名稱。
STUN請求的預設埠是3478,用於TCP和UDP。STUN在TLS上的預設埠是5349。伺服器能夠在TLS上執行STUN與STUN在TCP上時使用相同的埠,只有伺服器軟體支援決定初始訊息是否是TLS或STUN訊息。
如果SRV中沒有記錄可查,客戶端執行A或AAAA記錄查詢域名。結果將會是1張IP地址表,每一個都可以使用TCP或UDP採用預設埠號連線。通常要求使用TLS,客戶端使用STUN在TLS上的預設埠號連線其中一個IP地址。
1.4.3 認證和訊息完整性機制
短期證書機制
短期證書機制假設在STUN事務之前,客戶端和伺服器已經使用了其他協議來交換了證書,以username和password形式。這個證書是有時間限制的。
例如,在ICE用途中,兩個終端使用帶外方式交換資訊來對username和password達成一致,並在媒體會話期間使用。
這個證書被用來進行訊息完整性檢查,用於每個請求和多個響應中。與長期證書機制相比,沒有挑戰和響應方式,因此,這種證書的時間限制特性的優點是可以阻止重播。
長期證書機制
長期證書機制依賴於一個長期證書,username和password在客戶端和伺服器中是共用的。這個證書從它提供給 使用者開始將一直是有效的,直到該使用者不再是該系統的使用者。
這本質上是一個提供給使用者username和password的傳統的登入方式。
客戶端初始傳送一個請求,沒有提供任何證書和任何完整性檢測。伺服器拒絕這個請求,並提供給使用者一個範圍(用於指導使用者或代理選擇username和password)和一個nonce。這個nonce提供重放保護。它是一個cookie,由伺服器選擇,以這樣一種方式來標示有效時間或客戶端身份是有效的。客戶端重試這個請求,這次包括它的username和realm和伺服器提供的nonce來回應。伺服器確認這個nonce和檢查這個message integrity。如果它們匹配,請求則通過認證。如果這個nonce不再有效,即過期了,伺服器就拒絕該請求,並提供一個新的nonce。
在隨後的到同一伺服器的請求,客戶端重新使用這個nonce、username和realm,和先前使用的password。這樣,隨後的請求不會被拒絕直到這個nonce變成無效的。
需要注意的是,長期證書機制不能用來保護Indications,由於Indications不能被改變,因此,使用Indications時要麼使用短期證書,要麼就省略認證和訊息完整性。
因為長期證書機制對離線字典攻擊敏感,部署的時候應該使用很難猜測的密碼。
1.4.4 備份伺服器機制
伺服器使用增強的重定向功能將一個客戶端轉向另一個伺服器,通過迴應一個錯誤響應號為300(嘗試備份)的錯誤響應。伺服器在錯誤響應中攜帶一個ALTERNATE-SERVER屬性。
客戶端收到錯誤響應號為300的錯誤響應後,在該響應中查詢ALTERNATE-SERVER屬性。若找到一個,客戶端就會將當前的事務作廢,並重新嘗試傳送請求到該屬性中列出的伺服器。請求報文若已經通過認證,則必須使用與先前傳送給執行重定向操作的伺服器同樣的證書。如果客戶端在最後5分鐘裡已經重試傳送請求時已經重定向到了一個伺服器,它必須忽略重定向操作並將當前的事務作廢,這是為了防止無限的重定向迴圈。
1.5 RFC5389與RFC3489的相容
在RFC3489中:
UDP是唯一支援的傳輸協議
RFC5389中的魔術字欄位是RFC3489中事務ID的一部分,事務ID長128位
沒有XOR-MAPPED-ADDRESS屬性,繫結方法是使用MAPPED-ADDRESS屬性代替
有3個需要強制理解的屬性,分別是:RESPONSE-ADDRESS、CHANGE-REQUEST、CHANGED-ADDRESS屬性,而RFC5389中不再支援這些屬性。
1.5.1 客戶端處理的改變
客戶端想要與RFC3489的伺服器互操作,應傳送一個使用繫結方法的請求訊息,不包含任何訊息,使用UDP協議傳送給伺服器。如果成功,將收到伺服器發回的包含MAPPED-ADDRESS屬性而不是XOR-MAPPED-ADDRESS屬性的成功響應。客戶端試圖與基於RFC3489的應用伺服器互操作必須準備好接收任意一個屬性。此外,客戶端必須忽略任何在響應中出現的保留的強制理解的屬性。RFC3489中規定保留屬性中的0x0002、0x0004、0x0005和0x000B可能出現在繫結響應中。
1.5.2 伺服器處理的改變
伺服器能夠察覺由RFC3489中的客戶端傳送的攜帶有不正確的魔術字的捆綁請求訊息。當伺服器察覺到RFC3489中的客戶端,它應該將捆綁請訊息中魔術字域中的值拷貝到捆綁響應中的魔術字欄位中,並且插入一個MAPPED-ADDRESS屬性代替XOR-MAPPED-ADDRESS屬性。
客戶端在極少的環境下可能包括RESPONSE-ADDRESS或CHANGE-REQUEST屬性中的一個。在這些情況下,伺服器把這些屬性看做是一個不認識的強制理解的屬性,並回應一個錯誤響應。
RFC3489版本中的STUN缺少魔術字和指紋屬性這兩種能夠高可靠性的正確標識其他協議多路複用時的STUN訊息。因此,STUN執行與RFC3489相容時不應該被用於多個協議。
2 TURN
2.1 RFC5766/TURN
TURN,在RFC5766中定義,英文全稱Traversal Using Relays around NAT(TURN):Relay Extensions to Session Traversal Utilities for NAT(STUN),即使用中繼穿透NAT:STUN的中繼擴充套件。簡單的說,TURN與STUN的共同點都是通過修改應用層中的私網地址達到NAT穿透的效果,異同點是TURN是通過兩方通訊的“中間人”方式實現穿透。
如果一個主機位於NAT的後面,在某些情況下它不能夠與其他主機點對點直接連線。在這些情況下,它需要使用中間網點提供的中繼連線服務。TURN協議就是用來允許主機控制中繼的操作並且使用中繼與對端交換資料。TURN與其他中繼控制協議不同的是它能夠允許一個客戶端使用一箇中繼地址與多個對端連線。
TURN協議被設計為ICE的一部分,用於NAT穿越,雖然如此,它也可以在沒有ICE的地方單獨使用。
2.1.1 操作概述
圖2:TURN
在一個典型組網中,一個TURN客戶端連線在一個私有網路中,通過一個或多個NAT來連線到公網。在公網中有一個TURN伺服器。在因特網的別處有一個或多個對端是這個TURN客戶端希望通訊的。這些對端也有可能是在一個或多個NAT的後面。該客戶端使用伺服器作為一箇中繼來發送資料包 到這些對端去,並且從這些對端接收資料包。
客戶端通過一個IP地址和埠的組合來與伺服器建立會話。客戶端使用TURN命令在伺服器上建立和操作一個ALLOCATION。一旦這個allocation建立好了,客戶端能夠在資料發往哪個對端的指示下發送應用資料到這個伺服器,伺服器將中繼這些資料到合適的對端。客戶端傳送的應用資料包含在TURN訊息中,伺服器將資料提取出來,並以UDP資料包方式傳送給對端。反向上,對端以UDP資料包方式傳送應用資料到這個allocation提供的中繼傳輸地址。因為TURN訊息總是包含客戶端與哪些對端通訊的指示,客戶端能夠使用單一的allocation來與多個對端通訊。
2.1.2 術語
TURN client:遵循RFC5766的STUN客戶端。
TURN server:遵循RFC5766的STUN伺服器。
Peer:TURN客戶端希望連線的主機。TURN伺服器為TURN客戶端和它的對端中繼流量,但Peer並不與TURN伺服器使用TURN協議進行互動,它接收從TURN伺服器傳送過來的資料,並向TURN伺服器傳送資料。
Transport Address:IP地址與埠號的組合。
Host Transport Address:客戶端或對端的傳輸地址。
Server-Reflexive Transport Address:NAT公網側的傳輸地址,該地址由NAT分配,相當於一個特定的主機傳輸地址。
Relayed Transport Address:TURN伺服器上的傳輸地址,用於客戶端和對端中繼資料。
TURN Server Transport Address:TURN伺服器上的傳輸地址,用於客戶端傳送STUN訊息給伺服器。
Peer Transport Address:伺服器看到的對端的傳輸地址,當對端是在NAT後面,則是對端的伺服器反射傳輸地址。
Allocation:通過Allocate請求將中繼傳輸地址提供給客戶端,除了中繼狀態外,還有許可和超時定時器等。
5-tuple:五元組,包括客戶端IP地址和埠,伺服器IP地址和埠和傳輸協議(包括UDP、TCP、TLS)的組合。
Channel:通道號與對端傳輸地址的關聯,一旦一個通道號與一個對端的傳輸地址繫結,客戶端和伺服器就能夠利用頻寬效應更大的通道資料訊息來交換資料。
Permission:一個對端允許使用它的IP地址和傳輸協議來發送資料到TURN伺服器,伺服器只為從對端發來的並且匹配一個已經存在的許可的流量中繼到相應的客戶端。
Realm:伺服器內用於描述伺服器或內容的一個字串,這個realm告訴客戶端哪些使用者名稱和密碼的組合可用於認證請求。
Nonce:伺服器隨機選擇的一個字串,包含在報文摘要中。為了防止中繼攻擊,伺服器應該有規律的改變這個nonce。
2.1.3 新的STUN方法
下面給出了新的STUN方法的編號:
0x003 Allocate
0x004 Refresh
0x006 Send
0x007 Data
0x008 CreatePermission
0x009 ChannelBind
2.1.4 新的STUN屬性
0x000c CHANNEL-NUMBER
0x000D LIFETIME
0x0010 Reserved (was BANDWIDTH)
0x0012 XOR-PEER-ADDRESS
0x0013 DATA
0x0016 XOR-RELAYED-ADDRESS
0x0018 EVEN-PORT
0x0019 REQUESTED-TRANSPORT
0x001A DON’T-FRAGMENT
0x0021 Reserved (was TIMER-VAL)
0x0022 RESERVATION-TOKEN
上面屬性中的部分屬性長度不是4位元組的倍數,採用STUN的規則,使用1~3個padding位元組來補齊。
CHANNEL-NUMBER
CHANNEL-NUMBER屬性包含通道的號碼。屬性長4位元組,包含16位元的無符號整數和2位元組的RFFU(Reserved For Future Use)欄位,該欄位必須設為0且在接收時被忽略。
位元組
0 1 2 3
Channel Number |
RFFU=0 |
LIFETIME
LIFETIME屬性表示伺服器在沒有收到refresh時維持一個allocation的持續時間。屬性長4位元組,包含一個32位元的無符號整數值,表示剩餘多少秒終止
XOR-PEER-ADDRESS
XOR-PEER-ADDRESS指定從TURN伺服器看到的對端的地址和埠,例如如果對端是在一個NAT後面,則為對端的server-reflexive傳輸地址。
DATA
DATA屬性存在於所有的Send和Data indications訊息中。屬性的值是可變長度的,包括應用資料。如果屬性的長度不上4位元組的倍數,必須進行填充。
XOR-RELAYED-ADDRESS
XOR-RELAYED-ADDRESS存在於所有的Allocate響應中。它指定了伺服器分配給客戶端的地址和埠。
位元組
0 1 2 3
00000000 |
地址族 |
埠號 |
IP地址(32位或128位) |
EVEN-PORT
這個屬性允許客戶端請求在中繼傳輸地址的埠為偶數,並且伺服器可選的保留緊跟著的下一個埠號。屬性的值長1位元組,結構如下:
位元組
0
R |
RFFU |
值包括一個1位元標誌欄位:
R:如果為1,伺服器被請求保留下一個更高的埠號(基於同一個IP地址)為隨後的allocation。如果為0,則不請求保留。屬性的其他7位元值必須設定為0,並且在接收時被忽略。因為屬性不是4位元組的倍數,必須進行填充。
REQUESTED-TRANSPORT
客戶端通過該屬性為已分配的傳輸地址請求一個特定的傳輸協議。屬性的值是4位元組長度的。
位元組
0 1 2 3
Protocol |
RFFU |
協議欄位指定了需求的協議。可以取自IPv4報頭中的協議欄位的值或IPv6報頭的下一個報頭欄位的協議號。目前僅允許設定為17,即UDP。RFFU欄位在傳輸時必須設定為0,並在接收時被忽略。保留用於未來使用。
DON’T-FRAGMENT
客戶端使用該屬性來請求伺服器設定IP報頭中的DF(不要分片)位,當中繼應用資料到對端時。該屬性沒有值,因此屬性長度欄位為0。
RESERVATION-TOKEN
RESERVATION-TOKEN屬性包含一個token來唯一的標識一箇中繼傳輸地址已經被伺服器保留。伺服器在一個成功響應中包含該屬性來告訴客戶端這個token,客戶端在接下來的Allocate請求中包括該屬性來請求伺服器為這個allocation使用那個中繼傳輸地址。屬性值是8位元組長。
2.1.5 新的STUN錯誤響應號
403(Forbidden):請求是有效的,但因管理或類似的規定而不能被執行。
437(Allocation Mismatch):伺服器接收到請求,要求在適當的位置的allocation,但沒有allocation存在,或者一個收到的請求不指定任何allocation,但是一個allocation存在。
441(Wrong Credentials):請求中的證書沒有匹配那些用來建立allocation的證書
442(不支援的傳輸協議):Allocate請求要求伺服器使用一個用於伺服器和對端的傳輸協議但是該伺服器不支援該傳輸協議。
486(Allocation Quota Reached):目前沒有更多的allocations資源使用相同的使用者名稱可被建立。
508(Insufficient Capacity):伺服器不能夠完成請求因為一些效能限制已經達到上限。在一個Allocate響應中,這可能因為伺服器此時已經沒有更多的中繼傳輸地址資源了,沒有更多的被請求的效能,或者相當於特定的保留的token不可用。
2.1.6 協議互動過程詳細舉例
以圖2為例進行講解,每個訊息中,多個屬性包含在訊息中並顯示它們的值。為了方便閱讀,值以人們可讀的格式來顯示。
客戶端使用10.1.1.2:49271作為傳輸地址向伺服器的傳輸地址傳送Allocate請求。客戶端隨機選擇一個96位的事務ID。該Allocate請求訊息包括SOFTWARE屬性來提供客戶端的軟體版本資訊;包括LIFETIME屬性,指明客戶端希望該allocation具有1小時的生命期而非預設的10分鐘;包括REQUESTED-TRANSPORT屬性來告訴伺服器與對端之間採用UDP協議來傳輸;包括DONT-FRAGMENT屬性因為客戶端希望在隨後的Send indications中使用DON’T-FRAGMENT屬性。
伺服器需要任何請求必須是經過認證的,因此伺服器拒絕了該最初的Allocation請求,並且迴應了攜帶有錯誤響應號為401(未授權)的Allocate錯誤響應;該響應包括一個REALM屬性,指明認證的域;還包括一個NONCE屬性和一個SOFTWARE屬性。
客戶端收到了錯誤響應號為401的Allocate錯誤響應,將重新嘗試傳送Allocate請求,此時將包括認證屬性。客戶端在新的請求中重新選擇一個新的事務ID。客戶端包括一個USERNAME屬性,使用從伺服器那收到的realm值來幫助它決定使用哪個值;請求還包括REALM和NONCE屬性,這兩個屬性是從收到的錯誤響應中拷貝出來的。最後,客戶端包括一個MESSAGE-INTEGRITY屬性。
伺服器收到認證的Allocate請求後,檢查每個屬性是否正確;然後,產生一個allocation,並給客戶端迴應Allocate成功響應。伺服器在該成功響應中攜帶一個LIFETIME屬性,本例中伺服器將客戶端請求的1小時生命期減小為20分鐘,這是因為這個特定的伺服器可能不允許超過20分鐘的生命期;該響應包括XOR-RELAYED-ADDRESS屬性,值為該allocation的中繼傳輸地址;該響應還包括XOR-MAPPED-ADDRESS屬性,值為客戶端的server-reflexive地址;該響應也包含一個SOFTWARE屬性;最後,包括一個MESSAGE-INTEGRITY屬性來證明該響應,確保它的完整性;
接著,客戶端為了準備向對端A傳送一些應用資料而建立一個permission。這裡通過一個CreatePermission請求來做到。該請求攜帶XOR-PEER-ADDRESS屬性包含有確定的請求的IP地址,這裡為對端A的地址;需要注意的是,屬性中地址的埠號被設定為0在CreatePermission請求中,並且客戶端使用的是對端A的server-reflexive地址而不是它的主機地址(私網地址);客戶端在該請求中攜帶與之前的Allocate請求中一樣的username、realm和nonce值,因此該請求被伺服器認可。此時在該請求中,客戶端沒有攜帶SOFTWARE屬性。
伺服器收到該CreatePermission請求,產生一個相應的許可,並以CreatePermission成功響應來回應。該響應中只包含了Transaction-ID和MESSAGE-INTEGRITY屬性。
現在客戶端使用Send indication來發送應用資料到對端A。對端的server-reflexive傳輸地址包含在XOR-PEER-ADDRESS屬性中,應用資料包含在DATA屬性中。客戶端已經在應用層上執行了路徑MTU發現功能,因此通過DON’T-FRAGMENT屬性來告知伺服器當通過UDP方式來向對端傳送資料時應設定DF位。Indications不能使用長期證書機制來認證,所以該訊息中沒有MESSAGE-INTEGRITY屬性。
伺服器收到Send indication後,提取出應用資料封裝成UDP格式發給對端A;UDP報文的源傳輸地址為中繼傳輸地址,並設定DF位。
對端A迴應它自己的包含有應用資料的UDP包給伺服器。目的地址為伺服器的中繼傳輸地址。當伺服器收到後,將生成Data indication訊息給客戶端,攜帶有XOR-PEER-ADDRESS屬性。應用資料包含在DATA屬性中。
客戶端現在若要繫結一個通道到對端B,將指定一個空閒的通道號(本例中為0x4000)包含在CHANNEL-NUMBER屬性中,對端B的傳輸地址包含在XOR-PEER-ADDRESS屬性中。與以前一樣,客戶端再次利用上次請求中的username、realm和nonce。
當伺服器收到該請求後,伺服器繫結這個對端的通道號,為對端B的IP地址安裝一個permission,然後給客戶端迴應一個ChannelBind成功響應訊息。
客戶端現在傳送一個ChannelData訊息給伺服器,攜帶有傳送給對端B的資料。這個訊息不是一個STUN訊息,因此沒有事務ID。它之有3個欄位:通道號、資料、資料長度;伺服器收到後,檢查通道號後發現當前已經綁定了,就以UDP方式傳送資料給對端B。
接著,對端B傳送UDP資料包迴應給伺服器的中繼傳輸地址。伺服器收到後,迴應給客戶端ChannelData訊息,包含UDP資料包中的資料。伺服器知道是給哪個客戶端傳送ChannelData訊息,這是因為收到的UDP資料包中的目的地址(即伺服器的中繼傳輸地址),並且知道使用的是哪個通道號,這是因為通道已經與相應的傳輸地址綁定了。
有時候,20分鐘的生命期已經到了,客戶端需要重新整理allocation。此時通過傳送Refresh請求來進行。該請求包含最後一次使用的username、realm和nonce,還包含SOFTWARE屬性。當伺服器收到這個Refresh請求時,它注意到這個nonce值已經超期了,則給客戶端迴應一個錯誤響應號為438(過期Nonce)的Refresh錯誤響應,並提供一個新的nonce值。可護端將重試該請求,此時攜帶新的nonce值。若第二次嘗試被接受,伺服器將回應一個成功響應。需要注意的是,此時客戶端在請求中沒有攜帶LIFETIME屬性,所以伺服器重新整理客戶端的allocation時採用預設的10分鐘生命期。
3 總結
在現實Internet網路環境中,大多數計算機主機都位於防火牆或NAT之後,只有少部分主機能夠直接接入Internet。很多時候,我們希望網路中的兩臺主機能夠直接進行通訊(即所謂的P2P通訊),而不需要其它公共伺服器的中轉。由於主機可能位於防火牆或NAT之後,在進行P2P通訊之前,我們需要進行檢測以確認它們之間能否進行P2P通訊以及如何通訊。這種技術通常被稱為NAT穿透(NAT Traversal)。
RFC3489中定義的STUN,即簡單地用UDP穿過NAT(STUN)是個輕量級的協議。它允許應用發現它們與公共網際網路之間存在的NAT和防火牆及其他型別。它還為應用提供判斷NAT給它們分配的公共網際協議(IP)地址。STUN可工作在許多現存NAT上,並且不需要它們做任何特別的行為。它允許廣泛的各類的應用穿越現存的NAT設施。
RFC5389中對STUN協議進行了修訂,將其定位於為穿透NAT提供工具,即NAT會話穿透效用是一個用於其他解決NAT穿透問題協議的協議。它可以用於終端裝置檢查由NAT分配給終端的IP地址和埠號。同時,它也被用來檢查兩個終端之間的連線性,好比是一種維持NAT繫結表項的保活協議。STUN本身並不是一種完整的NAT穿透解決方案。它相當於是一種NAT穿透解決方案中的工具。這是與先前的版本相比最重要的改變。之前的RFC3489中定義的STUN是一個完整的穿透NAT解決方案。此外,最大的區別是支援TCP穿透。
RFC5766中對STUN協議再次進行了擴充套件,即中繼穿透NAT:STUN的擴充套件。TURN與STUN的共同點都是通過修改應用層中的私網地址達到NAT穿透的效用,異同點是TUN採用了兩方通訊的“中間人”方式實現穿透,突破了原先STUN協議無法在兩臺主機不能夠點對點直接連線下提供作用的限制。
技術無止境,NAT穿透技術仍在不斷更新中,這裡只對STUN/TURN協議作了簡單的介紹,具體細節請參考RFC3489/5389/5766。