天天看點

STUN操作過程和資訊結構

STUN Binding Request使用UDP協定發送到STUN伺服器,當Binding Request消息到達伺服器的時候它可能經過了一個或者多個NAT。結果是STUN伺服器收到的request消息的源IP位址被映射成最靠近STUN伺服器的NAT的IP位址,STUN伺服器把這個源IP位址和端口号複制到一個Bind Response消息中,通過發送回擁有這個IP位址和端口号的用戶端,對于上面提到的所有類型的NAT,這個消息都會到達用戶端。

當STUN用戶端收到STUN Binding Response消息之後,它會将自己發送Request時bind的本地IP位址和端口号同Response消息中的IP位址端口号進行比較,如果不比對,就表示用戶端正處于一個或者多個NAT的前面。在Full-Cone NAT的情況下,在STUN Response消息中的IP位址和端口是屬于公網的,公網上的任何主機都可以使用這個IP位址和端口号向這個應用程式發送資料包,應用程式隻需要在剛才發送STUN Binding Request的IP位址和端口上監聽即可。

當然,主機可能并不在一個full-core NAT的前面,實際上,它并不知道自己在一個什麼類型的NAT的前面。為了确定NAT的類型,用戶端使用附加的STUN Binding Request.具體過程是很靈活的,但一般都會像下面這樣工作。用戶端再發送一個STUN Binding Request,這次發往另一個IP位址,但是使用的是跟上一次同一個源IP位址和源端口号,如果傳回的資料包裡面的IP位址和端口号和第一次傳回的資料包中的不同,用戶端就會知道它是在一個對稱NAT的前面。用戶端為了确定自己是否在一個完全錐形NAT的前面,用戶端可以發送一個帶有标志的STUN Binding Request,這個标志告訴STUN Server另一個IP位址和端口發送Response,這個IP位址和端口要和剛才收到Request的IP位址和端口不同。換句話說,如果用戶端使用x:y的IP位址:端口對向A:B的IP位址:端口對發送Binding Request,STUN Server會使用源IP位址和源端口号為C:D的位址對向X:Y發送Response.如果用戶端收到了這個Response,它就知道它是在一個Full-Cone NAT前面。

STUN協定允許用戶端請求伺服器從收到Request的IP位址往回發Binding Response,但是要使用不同的端口号。這可以用來檢查用戶端是在Port Restricted Cone NAT的前面還是在Restricted Cone NAT的前面。

STUN 消息是使用大端位元組流編碼的TLV(type-length-value).所有的STUN消息都以一個STUN頭開始,緊跟着STUN的載核資料(Payload)。Payload是一系列的STUN屬性集合,它們取決于STUN消息的類型。STUN消息的type可以是Binding Request,Binding Response,Binding ERROR Response, Shared Secret Request,Shared Secrect Response 或 Shared Secret Error Response.

Transaction ID的作用是将請求(Request)和響應(Response)聯系起來。長度字段代表STUN Payload資料的整個長度。Shared Secret Requests一直都是承載于TCP之上發送的(實際上,是使用了承載于TCP這上的TLS發送的)。

STUN協定也定義了很多的STUN屬性。第一個是MAPPED-ADDRESS屬性,它是一個IP位址和端口對,Binding Response裡面一直都有它,它代表了伺服器在Binding Request中看到的源IP位址和源端口号。還有一個RESPONSE-ADDRESS屬性,包含一個IP位址和端口。RESPONSE-ADDRESS可以被放到Binding Request中,它告訴伺服器Binding Request将會被發送到哪裡。它是可選的,當不填寫的時候,Binding Request會被卧發送到Binding Request的源IP位址和源端口号。

第三個屬性是CHANGE-REQUEST 屬性,它包含了兩個flag,這兩個flag控制用來發送Response的IP位址和端口号。這兩個标志被稱為“change IP”和“change port”标志,CHANGE-REQUEST标志隻允許在Binding Request中出現,在确定用戶端是在Restricted Cone NAT之前還是Port Restricted Cone NAT之前的時候,這兩個标志是很有用的。它們訓示Server從不同的源位址和源端口發送Binding Response。在Binding Request中CHANGE-REQUEST屬性是可選的。

第四個屬性是CHANGED-ADDRESS屬性,它出現在Binding Response中。如果用戶端請求使用”change IP”和”change port”行為,它會通知用戶端将會使用的源IP位址和源端口号。

第五個屬性是SOURCE-ADDRESS屬性,它隻出現在Binding Response中,它訓示發送Response的源IP位址和源端口号,它在檢測兩個NAT配置的時候是很有用的。

第五個是USERNAME,它隻在Shared Secret Response中出現,忽略了…

第六個屬性是ERROR-CODE屬性,它出現在Binding Error Response和Shared Secret Error Response中,它指出發生的錯誤。

忽略了三四個屬性…..

消息頭:

所有的STUN消息都包含20個位元組的消息頭:

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

+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

|

+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

Message Type可以取下面這些值:

0×0001 : Binding Request

0×0101 : Binding Response

0×0111 : Binding Error Response

0×0002 : Shared Secret Request

0×0102 : Shared Secret Response

0×0112 : Shared Secret Error Response

Message Length是載核資料的位元組長度,不包含消息頭的長度。

Transaction ID是一個128位的辨別符,可以随機生成。

消息屬性

STUN消息頭後面跟着0個或多個屬性,所有的屬性都是TLV形式的,包含16位的類型,16位的長度,和變長的值。

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 ….

+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

下面是類型的定義:

0×0001: MAPPED-ADDRESS

0×0002: RESPONSE-ADDRESS

0×0003: CHANGE-REQUEST

0×0004: SOURCE-ADDRESS

0×0005: CHANGED-ADDRESS

0×0006: USERNAME

0×0007: PASSWORD

0×0008: MESSAGE-INTEGRITY

0×0009: ERROR-CODE

0x000a: UNKNOWN-ATTRIBUTES

0x000b: REFLECTED-FROM

MAPPED-ADDRESS

這個屬性表示映射的IP位址和端口。

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 |

+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

Family一般都是0×01,表示IPV4

STUN 的簡單操作過程:

發送請求。請求分為兩種

1.Binding Requests, sent over UDP,

 用來發現NAT的公網位址,和MAPPING後的端口

 2.  Binding Response,

伺服器産生Binding Response,并把得到的MAPPINGIP 和端口,傳回到用戶端, 用戶端比較MAPPING位址是否和本機位址相同,如果是說明是本機也是公網,否則判斷NAT的類型(判斷方法:client uses additional STUN Binding Requests)

3.Binding Error,

4.Shared Secret Requests, sent over TLS [2] over TCP.

這個請求要求伺服器傳回一臨時使用者名和密碼,用來下一步的Binding Requests/ Response,用來驗證資訊的完整性

5.Shared Secret Response,

6 Shared Secret Error Response。

STUN 資訊結構

STUN 由以後資料結構構成:STUN頭+STUN有效載荷

STUN頭結構如下: 存儲的值都是以網絡順序存放

字段    類型  

STUN message type    Short int    消息類型

Length    Short int    有效載荷長度,不包含頭長度

transaction ID    octet[16]    連接配接的ID值,檢查Request,和Response

STUN的有效載荷

SHUN的有效載荷是一些STUN的屬性構成,屬性的類型由資訊的類型來決定。

STUN的屬性是定義好了的,屬性清單(attribute)如下:

MAPPED-ADDRESS    必選    用在Binding Response,(添入MAPING IP 和PORT)

RESPONSEADDRESS    可選    用在Binding Request,指定Response,發送到哪裡

如果沒有指定,Response發送到MAPING IP 和 PORT

CHANGE-REQUEST    可選    用在Binding Request。用來決定,CLIENT的NAT類型是

制NAT,還是端口限制NAT,(指令伺服器從不同的源端口/IP,Response請求)

CHANGED-ADDRESS    可選    用在Binding Responses告訴Client改變的端口和IP

SOURCE-ADDRESS    必選    隻用在Binding Responses,标記資訊的源PORT HE IP

USERNAME    可選    Shared Secret Response/ Binding Requests

PASSWORD,    必選    SharedSecret Response

ESSAGEINTEGRITY    可選    用在Binding Responses, Binding Request記錄資訊的完整性

ERROR-CODE        Binding Error Response and Shared Secret Error Response.

UNKNOWN-ATTRIBUTES      

REFLECTED-FROM        Binding Responses.用于追溯和防止DDOS

 穿透的方法和過程

繼續閱讀