Nat穿透一

轉載地址:http://www.360doc.com/content/13/0708/19/9523427_298537379.shtml

1.NET簡介

NAT(Network Address Translation,網絡地址轉換)是一種廣泛應用的解決IP短缺的

有效方法,NAT將內網地址轉和端口號換成合法的公網地址和端口號,建立一個會話,與公網主機進行通信。

1.1NET分類

NAT從表面上看有三種類型:靜態NAT、動態地址NAT、地址端口轉換NAPT。  

(1)靜態NAT:靜態地址轉換將內部私網地址與合法公網地址進行一對一的轉換,且每個內部地址的轉換都是確定的。

    (2)動態NAT:動態地址轉換也是將內部本地地址與內部合法地址一對一的轉換,但是動態地址轉換是從合法地址池中動態選擇一個未使用的地址來對內部私有地址進行轉換。

    (3)NAPT:它也是一種動態轉換,而且多個內部地址被轉換成同一個合法公網地址,使用不同的端口號來區分不同的主機,不同的進程。

從實現的技術角度,又可以將NAT分成如下幾類:全錐NAT(Full Cone NAT)、限制性錐NAT(Restricted Cone NAT)、端口限制性錐NAT( PortRestricted Cone NAT)、對稱NAT ( Symmetric NAT)。其中完全錐形的穿透性最好,而對稱形的安全性最高

wKiom1QjssvhPTkGAAETRG52J5g377.jpg


(1)全錐NAT:全錐NAT把所有來自相同內部IP地址和端口的請求映射到相同的外部IP地址和端口。任何一個外部主機均可通過該映射發送數據包到該內部主機。

(2)限制性錐NAT:限制性錐NAT把所有來自相同內部IP地址和端口的請求映射到相同的外部IP地址和端口。但是,和全錐NAT不同的是:只有當內部主機先給外部主機發送數據包,該外部主機才能向該內部主機發送數據包。

(3)端口限制性錐NAT:端口限制性錐NAT與限制性錐NAT類似,只是多了端口號的限制,即只有內部主機先向外部地址:端口號對發送數據包,該外部主機才能使用特定的端口號向內部主機發送數據包。

(4)對稱NAT:對稱NAT與上述3種類型都不同,不管是全錐NAT,限制性錐NAT還是端口限制性錐NAT,它們都屬於錐NAT(ConeNAT)。當同一內部主機使用相同的端口與不同地址的外部主機進行通信時, 對稱NAT會重新建立一個Session,爲這個Session分配不同的端口號,或許還會改變IP地址。

1.2NET的作用

    NAT不僅實現地址轉換,同時還起到防火牆的作用,隱藏內部網絡的拓撲結構,保護內部主機。NAT不僅完美地解決了lP地址不足的問題,而且還能夠有效地避免來自網絡外部的攻擊,隱藏並保護網絡內部的計算機。這樣對於外部主機來說,內部主機是不可見的。但是,對於P2P應用來說,卻要求能夠建立端到端的連接,所以如何穿透NAT也是P2P技術中的一個關鍵。

 

 

2.P2P穿透NET

要讓處於NAT設備之後的擁有私有IP地址的主機之間建立P2P連接,就必須想辦法穿

透NAT,現在常用的傳輸層協議主要有TCP和UDP,下面就是用這兩種協議來介紹穿透NAT的策略。

2.1.網絡拓撲結構

下面假設有如圖1所示網絡拓撲結構圖。


 

圖1.網絡拓撲結構圖

Server(129.208.12.38)是公網上的服務器,NAT-A和NAT-B是兩個NAT設備(可能是集成NAT功能的路由器,防火牆等),它們具有若干個合法公網IP,在NAT-A阻隔的私有網絡中有若干臺主機【ClientA-1,ClientA-N】,在NAT-B阻隔的私有網絡中也有若干臺主機【ClientB-1,ClientB-N】。爲了以後說明問題方便,只討論主機ClientA-1和ClientB-1。

假設主機ClientA-1和主機ClientB-1都和服務器Server建立了“連接”,如圖2所示。


圖2.ClientA-1,ClientB-1和Server之間通信

    由於NAT的透明性,所以ClientA-1和ClientB-1不用關心和Server通信的過程,它們只需要知道Server開放服務的地址和端口號即可。根據圖1,假設在ClientA-1中有進程使用socket(192.168.0.2:7000)和Server通信,在ClientB-1中有進程使用socket(192.168.1.12:8000)和Server通信。它們通過各自的NAT轉換後分別變成了socket(202.103.142.29:5000)和socket(221.10.145.84:6000)。

2.2.使用UDP穿透NAT

通常情況下,當進程使用UDP和外部主機通信時,NAT會建立一個Session,這個Session能夠保留多久並沒有標準,或許幾秒,幾分鐘,幾個小時。假設ClientA-1在應用程序中看到了ClientB-1在線,並且想和ClientB-1通信,一種辦法是Server作爲中間人,負責轉發ClientA-1和ClientB-1之間的消息,但是這樣服務器太累,會吃不消。另一種方法就是讓ClientA-1何ClientB-1建立端到端的連接,然後他們自己通信。這也就是P2P連接。根據不同類型的NAT,下面分別講解。

(1)全錐NAT,穿透全錐型NAT很容易,根本稱不上穿透,因爲全錐型NAT將內部主機的映射到確定的地址,不會阻止從外部發送的連接請求,所以可以不用任何輔助手段就可以建立連接。

(2)限制性錐NAT和端口限制性錐NAT(簡稱限制性NAT),穿透限制性錐NAT會丟棄它未知的源地址發向內部主機的數據包。所以如果現在ClientA-1直接發送UDP數據包到ClientB-1,那麼數據包將會被NAT-B無情的丟棄。所以採用下面的方法來建立ClientA-1和ClientB-1之間的通信。

1.ClientA-1(202.103.142.29:5000)發送數據包給Server,請求和ClientB-1(221.10.145.84:6000)通信。

2. Server將ClientA-1的地址和端口(202.103.142.29:5000)發送給ClientB-1,告訴ClientB-1,ClientA-1想和它通信。

3. ClientB-1向ClientA-1(202.103.142.29:5000)發送UDP數據包,當然這個包在到達NAT-A的時候,還是會被丟棄,這並不是關鍵的,因爲發送這個UDP包只是爲了讓NAT-B記住這次通信的目的地址:端口號,當下次以這個地址和端口爲源的數據到達的時候就不會被NAT-B丟棄,這樣就在NAT-B上打了一個從ClientB-1到ClientA-1的孔。

4. 爲了讓ClientA-1知道什麼時候纔可以向ClientB-1發送數據,所以ClientB-1在向ClientA-1(202.103.142.29:5000)打孔之後還要向Server發送一個消息,告訴Server它已經準備好了。

5. Server發送一個消息給ClientA-1,內容爲:ClientB-1已經準備好了,你可以向ClientB-1發送消息了。

6. ClientA-1向ClientB-1發送UDP數據包。這個數據包不會被NAT-B丟棄,以後ClientB-1向ClientA-1發送的數據包也不會被ClientA-1丟棄,因爲NAT-A已經知道是ClientA-1首先發起的通信。至此,ClientA-1和ClientB-1就可以進行通信了。

2.3.使用TCP穿透NAT

使用TCP協議穿透NAT的方式和使用UDP協議穿透NAT的方式幾乎一樣,沒有什麼本質上的區別,只是將無連接的UDP變成了面向連接的TCP。值得注意是:

1.    ClientB-1在向ClientA-1打孔時,發送的SYN數據包,而且同樣會被NAT-A丟棄。同時,ClientB-1需要在原來的socket上監聽,由於重用socket,所以需要將socket屬性設置爲SO_REUSEADDR。

2.    ClientA-1向ClientB-1發送連接請求。同樣,由於ClientB-1到ClientA-1方向的孔已經打好,所以連接會成功,經過3次握手後,ClientA-1到ClientB-1之間的連接就建立起來了。

2.4.穿透對稱NAT

    上面討論的都是怎樣穿透錐(Cone)NAT,對稱NAT和錐NAT很不一樣。對於對稱NAT,當一個私網內主機和外部多個不同主機通信時,對稱NAT並不會像錐(Cone,全錐,限制性錐,端口限制性錐)NAT那樣分配同一個端口。而是會新建立一個Session,重新分配一個端口。參考上面穿透限制性錐NAT的過程,在步驟3時:ClientB-1(221.10.145.84:?)向ClientA-1打孔的時候,對稱NAT將給ClientB-1重新分配一個端口號,而這個端口號對於Server、ClientB-1、ClientA-1來說都是未知的。同樣, ClientA-1根本不會收到這個消息,同時在步驟4,ClientB-1發送給Server的通知消息中,ClientB-1的socket依舊是(221.10.145.84:6000)。而且,在步驟6時:ClientA-1向它所知道但錯誤的ClientB-1發送數據包時,NAT-1也會重新給ClientA-1分配端口號。所以,穿透對稱NAT的機會很小。下面是兩種有可能穿透對稱NAT的策略。

2.4.1.同時開放TCP(SimultaneousTCP open)策略

如果一個對稱NAT接收到一個來自本地私有網絡外面的TCP SYN 包,這個包想發起一個“引入”的 TCP 連接,一般來說,NAT會拒絕這個連接請求並扔掉這個SYN包,或者回送一個TCP RST(connection reset,重建連接)包給請求方。但是,有一種情況卻會接受這個“引入”連接。

RFC規定:對於對稱NAT,當這個接收到的SYN包中的源IP地址:端口、目標IP地址:端口都與NAT登記的一個已經激活的TCP會話中的地址信息相符時,NAT將會放行這個SYN 包。需要特別指出的是:怎樣纔是一個已經激活的TCP連接?除了真正已經建立完成的TCP連接外,RFC規範指出:如果NAT恰好看到一個剛剛發送出去的一個SYN包和隨之接收到的SYN包中的地址:端口信息相符合的話,那麼NAT將會認爲這個TCP連接已經被激活,並將允許這個方向的SYN包進入NAT內部。同時開放TCP策略就是利用這個時機來建立連接的。

如果 Client A-1和 Client B-1能夠彼此正確的預知對方的NAT將會給下一個TCP連接分配的公網TCP端口,並且兩個客戶端能夠同時地發起一個面向對方的“外出”的TCP連接請求,並在對方的 SYN 包到達之前,自己剛發送出去的SYN包都能順利的穿過自己的NAT的話,一條端對端的TCP連接就能成功地建立了。

2.4.3.UDP端口猜測策略

同時開放TCP策略非常依賴於猜測對方的下一個端口,而且強烈依賴於發送連接請求的時機,而且還有網絡的不確定性,所以能夠建立的機會很小,即使Server充當同步時鐘的角色。下面是一種通過UDP穿透的方法,由於UDP不需要建立連接,所以也就不需要考慮“同時開放”的問題。

爲了介紹ClientB-1的詭計,先介紹一下STUN協議。STUN(SimpleTraversal of UDP Through NATs)協議是一個輕量級協議,用來探測被NAT映射後的地址:端口。STUN採用C/S結構,需要探測自己被NAT轉換後的地址:端口的Client向Server發送請求,Server返回Client轉換後的地址:端口。

參考4.2節中穿透NAT的步驟2,當ClientB-1收到Server發送給它的消息後,ClientB-1即打開3個socket。socket-0向STUN Server發送請求,收到回覆後,假設得知它被轉換後的地址:端口(221.10.145.84:6005),socket-1向ClientA-1發送一個UDP包,socket-2再次向另一個STUNServer發送請求,假設得到它被轉換後的地址:端口(221.10.145.84:6020)。通常,對稱NAT分配端口有兩種策略,一種是按順序增加,一種是隨機分配。如果這裏對稱NAT使用順序增加策略,那麼,ClientB-1將兩次收到的地址:端口發送給Server後,Server就可以通知ClientA-1在這個端口範圍內猜測剛纔ClientB-1發送給它的socket-1中被NAT映射後的地址:端口,ClientA-1很有可能在孔有效期內成功猜測到端口號,從而和ClientB-1成功通信。

2.4.4.問題總結

    從上面兩種穿透對稱NAT的方法來看,都建立在了嚴格的假設條件下。但是現實中多數的NAT都是錐NAT,因爲資源畢竟很重要,反觀對稱NAT,由於太不節約端口號所以相對來說成本較高。所以,不管是穿透錐NAT,還是對稱NAT,現實中都是可以辦到的。除非對稱NAT真的使用隨機算法來分配可用的端口。


發佈了46 篇原創文章 · 獲贊 11 · 訪問量 23萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章