TCP/UCP打洞原理

Internet的迅速發展以及IPv4 地址數量的限制使得網絡地址翻譯(NAT,Network Address Trans2lation)設備獲得普遍應用。NAT設備容許處於同一NAT後的多臺主機共享一個公網(本文將處於同一NAT後的網絡稱爲私網,處於NAT前的網絡稱爲公網) IP 地址。一個私網IP 地址經過NAT設備與公網的其餘主機通訊。公網和私網IP地址域,以下圖所示: 服務器

  

  廣域網與私網示意圖 網絡

  通常來講都是由私網內主機(例如上圖中「電腦A-01」)主動發起鏈接,數據包通過NAT地址轉換後送給公網上的服務器(例如上圖中的「Server」),鏈接創建之後可雙向傳送數據,NAT設備容許私網內主機主動向公網內主機發送數據,但卻禁止反方向的主動傳遞,但在一些特殊的場合須要不一樣私網內的主機進行互聯(例如P2P軟件、網絡會議、視頻傳輸等),TCP穿越NAT的問題必須解決。網上關於UDP穿越NAT的文章不少,並且還有配套源代碼,可是我我的認爲UDP數據雖然速度快,可是沒有保障,並且NAT爲UDP準備的臨時端口號有生命週期的限制,使用起來不夠方便,在須要保證傳輸質量的應用上TCP鏈接仍是首選(例如:文件傳輸)。 併發

  網上也有很多關於TCP穿越NAT(即TCP打洞)的介紹文章,但不幸我還沒找到相關的源代碼能夠參考,我利用空餘時間寫了一個能夠實現TCP穿越NAT,讓不一樣的私網內主機創建直接的TCP通訊的源代碼。 翻譯

  這裏須要介紹一下NAT的類型: 視頻

  NAT設備的類型對於TCP穿越NAT,有着十分重要的影響,根據端口映射方式,NAT可分爲以下4類,前3種NAT類型可統稱爲cone類型。 生命週期

  (1)全克隆( Full Cone) : NAT把全部來自相同內部IP地址和端口的請求映射到相同的外部IP地址和端口。任何一個外部主機都可經過該映射發送IP包到該內部主機。 路由

  (2)限制性克隆(Restricted Cone) : NAT把全部來自相同內部IP地址和端口的請求映射到相同的外部IP地址和端口。可是,只有當內部主機先給IP地址爲X的外部主機發送IP包,該外部主機才能向該內部主機發送IP包。 io

  (3)端口限制性克隆( Port Restricted Cone) :端口限制性克隆與限制性克隆相似,只是多了端口號的限制,即只有內部主機先向IP地址爲X,端口號爲P的外部主機發送1個IP包,該外部主機纔可以把源端口號爲P的IP包發送給該內部主機。 軟件

  (4)對稱式NAT ( Symmetric NAT) :這種類型的NAT與上述3種類型的不一樣,在於當同一內部主機使用相同的端口與不一樣地址的外部主機進行通訊時, NAT對該內部主機的映射會有所不一樣。對稱式NAT不保證全部會話中的私有地址和公開IP之間綁定的一致性。相反,它爲每一個新的會話分配一個新的端口號。 路由器

  咱們先假設一下:有一個服務器S在公網上有一個IP,兩個私網分別由NAT-A和NAT-B鏈接到公網,NAT-A後面有一臺客戶端A,NAT-B後面有一臺客戶端B,如今,咱們須要藉助S將A和B創建直接的TCP鏈接,即由B向A打一個洞,讓A能夠沿這個洞直接鏈接到B主機,就好像NAT-B不存在同樣。

  實現過程以下(請參照源代碼):

  一、 S啓動兩個網絡偵聽,一個叫【主鏈接】偵聽,一個叫【協助打洞】的偵聽。

  二、 A和B分別與S的【主鏈接】保持聯繫。

  三、 當A須要和B創建直接的TCP鏈接時,首先鏈接S的【協助打洞】端口,併發送協助鏈接申請。同時在該端口號上啓動偵聽。注意因爲要在相同的網絡終端上綁定到不一樣的套接字上,因此必須爲這些套接字設置 SO_REUSEADDR 屬性(即容許重用),不然偵聽會失敗。

  四、 S的【協助打洞】鏈接收到A的申請後經過【主鏈接】通知B,並將A通過NAT-A轉換後的公網IP地址和端口等信息告訴B。

  五、 B收到S的鏈接通知後首先與S的【協助打洞】端口鏈接,隨便發送一些數據後當即斷開,這樣作的目的是讓S能知道B通過NAT-B轉換後的公網IP和端口號。

六、 B嘗試與A的通過NAT-A轉換後的公網IP地址和端口進行connect,根據不一樣的路由器會有不一樣的結果,有些路由器在這個操做就能創建鏈接(例如我用的TPLink R402),大多數路由器對於不請自到的SYN請求包直接丟棄而致使connect失敗,但NAT-A會紀錄這次鏈接的源地址和端口號,爲接下來真正的鏈接作好了準備,這就是所謂的打洞,即B向A打了一個洞,下次A就能直接鏈接到B剛纔使用的端口號了。

  七、 客戶端B打洞的同時在相同的端口上啓動偵聽。B在一切準備就緒之後經過與S的【主鏈接】回覆消息「我已經準備好」,S在收到之後將B通過NAT-B轉換後的公網IP和端口號告訴給A。

  八、 A收到S回覆的B的公網IP和端口號等信息之後,開始鏈接到B公網IP和端口號,因爲在步驟6中B曾經嘗試鏈接過A的公網IP地址和端口,NAT-A紀錄了這次鏈接的信息,因此當A主動鏈接B時,NAT-B會認爲是合法的SYN數據,並容許經過,從而直接的TCP鏈接創建起來了。

相關文章
相關標籤/搜索