內網穿透原理及實現一:C/S模式,P2P模式原理

1.前言

最近一陣子在研究內網穿透,查了很多資料,因此今天就聊聊兩種不一樣的穿透方式的原理,以及基於java的netty框架的實現,代碼也已在個人github。html

原由:忽然花這麼大力氣研究這個雖然是頭腦發熱所爲,但動機源於跟小夥伴聯機打遊戲,原來用nat123之類的作遠程端口轉發在最近一陣子巨慢無比,又沒找好的替代方案,前一陣子公司同事又分享過nio,網絡編程的知識又被過了遍,一拍腦子本身造輪子得了,正好本身又有個阿里雲能夠當中間節點,找了些參考文章就開搞了,陸陸續續摸索了三個週末,基本能夠用了,這兩篇文章就當總結了。java

2.問題由來

在通常的網絡應用中,簡單拓撲模型以下
git

server有公網ip,server應用直接監聽公網ip及端口,client訪問可直接經過ip:port 直接創建連接,進行請求響應。github

但若是服務端經過路由連接Internet,沒有直接暴露公網ip就不一樣了,如如下拓撲算法

server在內網,沒有公網ip,路由有公網ip,經過路由連接Internet,client請求抵達server路由後,除非在路由定義端口轉發規則,不然數據將被拋棄,但不少時候路由的轉發規則是沒法被改的。編程

這樣的模型能夠細分爲四種狀況安全

  1. client有公網ip,server在內網;
  2. client在內網,server在公網;
  3. client,server均在公網;
  4. client,server均在內網。

對於server在公網的狀況,client能夠主動連接;但server在內網時,咱們便須要內網穿透了。接下文章將以最複雜的第4種狀況進行分析。服務器

3.內網穿透原理

3.1 基於TCP的C/S模式

對於client和server均在內網的狀況,直連是不行的,但若是咱們有另一臺具備公網ip的服務器充當中間節點,即可以進行間接訪問了,拓撲以下網絡

中間服務器咱們暫稱爲forwarder
咱們詳細描述下請求響應過程 框架

  1. client由本機777端口經過路由向forward 11.11.11.11:666發起請求,路由分配公網ip及端口12.12.12.12:45464給client,這裏的端口是隨機分配的,也就內網機器能夠訪問Internet應用的緣由。
  2. client連上forwarder後,對應forwarder來講,它獲取到的客戶端是12.12.12.12:45464,全部client的777端口的請求都會由路由的45464端口發送給forwarder,同時Forwarder對client的響應實際上是發往路由的45464端口,再由路由轉發給client的777端口;
  3. server的80端口經它的路由13.13.13.13:12454也一樣與forwarder創建鏈接;
  4. 這時forwarder只須要將client發送請求數據轉發給server的路由12454端口,而後server的響應也經server的路由,發給forwarder,forwarder再轉發給client的路由,最後發送至client的777端口,這樣就完成了一次穿透兩個內網的請求與響應;
  5. 重複過程4,內網穿透也就成功了。

咱們能夠看到內網機器能訪問Internet的緣由在於它的路由爲其分配了一個隨機的公網端口。這裏順帶解釋概念 端口映射,此時的公網端口12.12.12.12:45464邏輯上能夠認爲就是內網機器777端口的映射。再抽象一點,對於client來講,forwarder的666端口其實也能夠認爲是server 80端口的映射,這個即是遠程端口映射,所以,遠程端口映射跟內網穿透,描述雖不一樣本質上是一致的。

這種模式很是簡單直接,只要client和server能連上Internet,就能穿透彼此的內網相互訪問。
諸如nat123的端口轉發機制,穿透內網的遠控軟件TeamViewer,咱們玩一些對戰遊戲的平臺,甚至各類網絡遊戲均可以當作這種模型的實現。

它的優勢在於forwarder服務器存在,能夠協助穿透任何形式的內網,簡單穩定,但一樣因爲存在中間服務器,網絡上不只受客戶端網絡限制,一樣也受forwarder的網絡限制,若是forwarder帶寬不行,或者傳輸幾g的大文件,效率就慢了。爲了解決這個問題,基於P2P的機制也就提出來了。

3.2基於UDP的P2P模式

先回頭看下C/S模式的網絡拓撲

C跟S最終仍是由各自路由隨機分配的公網端口進行Internet訪問,這樣的話,若是它們能彼此知道對方的公網ip和端口,好比經forwarder將ip端口發給對方,是否是就能夠直接TCP實現P2P訪問呢,答案是比較困難的。

緣由在於TCP是一種先鏈接後傳輸的通訊協議,分配給client的45464只能與forwarder的666端口傳輸數據,這是在鏈接創建時肯定的,若是client再想連接server的路由,此時的端口將是從新分配的。而且由於安全等問題考慮,端口是隨機分配,沒法固定。也有一些資料說能夠經過某些算法猜想到公網端口從而實現基於TCP的P2P傳輸,但實現起來比較困難。咱們這裏就經過UDP來實現,由於它跟TCP不一樣,是在發送數據時指定目標ip端口。

下面來看看基於UDP的P2P模式的網絡拓撲

如下是請求響應過程

  1. client開始向forwarder發送請求,因爲使用udp,咱們不須要創建鏈接,路由分配ip,端口後,數據包直接發往forwarder;
  2. forwarder由此能夠獲得client的公網ip及端口12.12.12.12:45464;
  3. 一樣的forwarder獲得server的公網ip及端口13.13.13.13:12454;
  4. forwarder將包含server的ip:端口的數據包發給client,將client的發給server;
  5. 因爲是UDP,此時client能夠直接將包含請求的數據包改成獲得的server地址,直接發往server路由,server一樣能夠直接發給client了。
  6. 雙方接受到對方數據後,能夠認爲一個虛擬的P2P鏈接就已經創建了, 至此內網穿透便實現了。

P2P方案優勢也就明顯的,數據傳輸不依賴於中間服務器,在鏈接創建後就再也不受其限制,但一樣因爲UDP的特性,數據可靠性難以保證,因此得容忍偏差,或者實現一些校驗機制,並且對於Symmetric NAT,P2P是沒法創建的,仍是隻能走C/S模式的穿透。

它的應用最普遍的就是各類BT客戶端了,畢竟大數據的傳輸不須要通過中間服務器,效率會高不少,而後一些P2P的聊天,視頻,遊戲對戰軟件也能夠用到。

至此,兩種實現模式的原理已經說明了,下一篇將講講基於java netty框架造的兩個輪子。

參考文檔

內網穿透並非一個新話題,已經有不少成熟的協議和框架實現了,好比這個,但學習,仍是本身造輪子得好。

NAT穿透解決方案介紹

做者:chulung

原文連接:https://chulung.com/article/36

本文由MetaCLBlog於2017-02-25 17:39:27自動同步至cnblogs

本文基於 知識共享-署名-非商業性使用-禁止演繹 4.0 國際許可協議發佈,轉載必須保留署名及連接。

 

出處:http://www.cnblogs.com/chulung/p/5657073.html

相關文章
相關標籤/搜索