NAT介紹以及穿透各種類型nat的技術實現包括對稱型nat


穿透各種類型nat的技術實現包括對稱型nat,對於對稱型nat,我們采用猜端口方式確定彼此nat后的分配所得端口號,測試數據可達95%以上的成功率。

NAT介紹

NAT(Network Address Translation)即網絡地址轉換技術。是為了解決IP地址不夠用而產生的路由器解決方案。路由器內部的局域網內的設備訪問外部網絡時,路由器將用自己從isp處分配而來的公網ip來替換這次訪問請求包的源ip,並根據不同的nat類型算法來用一新的端口號來替換請求包的源端口號。這樣在外面看來,這個請求包就是這個路由器設備發出來的,外部設備在TCP/IP消息頭里並不會發現關於一點這台內網計算機的內網地址信息。當遠程服務端返回消息包時,所返回的消息包也是把路由器的公網ip和端口作為目標地址的。當路由器收到這個回包,將會到自己的緩存中查找到之前給那台內網主機的替換ip和端口時的記錄也可稱這種記錄為內外地址關系映射表。

根據映射表的不同,我們可以將nat算法大體上分為兩大類,錐型和對稱型nat。

錐型NAT

錐型NAT根據安全策略權限的不同又可以分為3類分別是全錐型(Full Cone),IP限制錐型(IP Restricted Cone),端口受限錐型(Port Restricted Cone)。

其中安全策略限制也是由弱到強的。

全錐型nat當路由器收到外網發過來的數據包時,其根據路由器內部緩存的映射表查找目的ip與port,找到了就把包向內網轉發,找不到就丟棄。

ip限制錐型,某外網主機ip向此類型的路由器發送數據包時,路由器在只有先由內網某個計算機已經先向該外網主機ip發送過數據包的前題條件下,路由器才會把此外網主機ip發送過來的數據包向內網轉發,否則直接丟棄。且一般來說,先向外網ip發送數據包的操作不能太舊了,一旦超時了路由器緩存就被自動刪除了。即會導致路由器在緩存里找不到內網對外網ip的發送記錄。我們測試數據來看,這個超時間一般在2分鍾左右,不同廠商實現的路由器這個時間設定可能不同。

端口限制錐型,外網主機發過來的數據包的源地址ip:port,如果此數據包要想成功通過路由器進入內網。那么必須是在之前先有內網主機向此外網地址ip:port發送過數據包才可以。而ip限制型的前題條件是向此外網ip發送過數據包,也就是說如果是ip限制型外網在收到請求包后,可以通過另一個端口來回應數據包。對應到socket編程里就是可以通過另一個socket來回送數據,他們所使用的源端口可以是不一樣的。然而對於端口限制型,則一定是收到消息的這個socket本身進行回復。

對稱型NAT

對稱型(Symmetric),對稱型nat在安全策略上即在對收到外網發送過來的數據所做的操作與端口限制型是一樣的。它與端口限制錐型主要的區別就是當內網對外網發送包時,在對內網地址進行轉換時對不同目的外網地址ip:port,分配不同的端口。如下圖所示:

還有些NAT不屬於這四種中的任何一種,就不在本文的討論范圍了。

NAT類型判斷

路由器nat類型判斷可以用排除法按下面幾個步驟來實現。 首先我們應該明確IETF提供的標准一共有4種常見NAT。分別是:

  • 全錐型(full cone nat)
  • 地址限制錐型(ip restrict cone nat)
  • 端口限制錐型(port restrict cone nat)
  • 對稱型(symmetric nat) 對於市場上面一些廠商自已實現其它的nat我們不做過多的探討,以實際測試經驗來看,這類nat的路由器非不的少,但也不是不存在,我們過往測試中也發現過。比如中國移動在給寬帶用戶安裝寬帶時使用了一種集成了光貓和路由功能的盒子。他的安全性像全錐型,即外來連接消息包都允許進來,但對外端口映射時又表現為對稱型。

NAT類型判斷算法整體流程大至是,先判斷防火牆是否阻止所有udp包進來,再判斷是否是公網ip,再判斷是否為全錐型,然后判斷是否是對稱型,最后判斷是否是端口或地址限制型。

下面描述詳細的判斷過程,過程中需要與3台具有不同IP的服務器交互輔助。我們把這3台服務器稱之為“協調服務器”,分別稱為s1,s2,s3。

  1. 判斷路由器防火牆是否防止所有UDP包進入 客戶端向s1:30017發送一UDP包,s1收到后直接返回一udp數據包,如果客記端收不到s1的回包,那么判定為阻止所有udp,判斷結束,否則進入一下判斷。為了降低udp在網絡中丟失,此過程可以重復多次。
  2. 判斷主機是否直連公網 客戶端收到s1回復,s1在處理時取出客戶端的ip放入回復包里,客戶商解析出數據區的ip與本機本地取出的所有ip對比,看是否存在匹配。存在匹配即認定當前主機是直接連接在公網上的,中間沒有經過任何網關路由器,判斷結束,否則進入一下判斷。
  3. 判斷當前網絡的網關路由器是否為全錐型 客戶端向s1:30017端口發送消息請求s1通知s3從不同於30017端口回一個udp消息包,如果客戶端能收到s3的回復。那判定為全錐型nat,否則進入下一步判斷。
  4. 判斷是否為對稱型nat 客戶端分別向s1:30018,s2:30018發送udp消息,s1,s2收到包后,取出客戶端的ip:port放入數據包發送回給客戶端。客戶端這樣就取回自己的兩份公網ip:port數據,客戶端對比這兩個地址,如果這兩ip:port不一樣那么就是客戶端網關就是對稱型。否則就是錐型,要么是地址限制型,要么是端口限制型。就需要繼續向下判斷了。
  5. 判斷是地址限制型還是端口限制型nat 客戶端向s1:30018發消息,請求s1從另一個端口回復一個消息比如端口6000。如果客戶端收到了s1所回復的消息,那么判定為地址限制型而非端口限制型。否則收不到回復就判定為端口限制型。因為s1從非30018端口回復消息補路由器阻止了。


p2pcpp 程序的安裝與使用

p2pcpp版本分為國內版本和海外版本。兩個版本主要不同在於所使用的協調服務器部署地不一樣,搭建海外版本是因為海外社區用戶經常連接不上國內服務器(可能是因為國家防火牆的原因)。

國內版本客戶端運行說明: p2pcpp 運行說明:(macos版本) 1.在系統設置->安全與隱私->防火牆,暫時關閉防火牆 2.復制下面命令行粘貼到終端里自動執行 curl http://40.73.35.128:7656/download/p2pcpp/shell/download_and_run.sh | bash

p2pcpp 運行說明:(win10版本) 1.下載windows10最新版本的二進制包: http://40.73.35.128:7656/download/p2pcpp/binary/p2pcpp_v1.2.6.win10.tar.gz 2.右擊p2pcpp/bin/allow_firewall.bat腳本,選擇"以管理員身份運行"來設置防火牆添加網絡訪問(每次下載到新目錄解壓后只需執行一次); 3.雙擊 p2pcpp/bin/tester_client.bat腳本來獲取公網nat信息。

海外版本客戶端運行說明: p2pcpp 運行說明:(macos版本) 1.在系統設置->安全與隱私->防火牆,暫時關閉防火牆 2.復制下面命令行粘貼到終端里自動執行 curl http://40.73.35.128:7656/download/p2pcpp/shell/download_and_run_oversea.sh | bash

p2pcpp 運行說明:(win10版本) 1.下載windows10最新版本的二進制包: http://40.73.35.128:7656/download/p2pcpp/binary/p2pcpp_v1.2.6.win10.oversea.tar.gz 2.右擊p2pcpp_v1.2.6.win10.oversea/bin/allow_firewall.bat腳本,選擇"以管理員身份運行"來設置防火牆添加網絡訪問(每次下載到新目錄解壓后只需執行一次); 3.雙擊p2pcpp_v1.2.6.win10.oversea/bin/tester_client.bat腳本來獲取公網nat信息。

p2pcpp程序結構

p2pcpp程序模塊結構如下圖所示:

p2pcpp底層使用boost asio進行網絡通訊。主要流程都是使用異步讀寫接口進行數據收發。

net網絡封裝接口

uat::net類的聲明

namespace unat
{  class net  {  public:  using callback = unat::callback_net;  using id_t = unat::callback_net::id_t;   public:  net();  ~net();   public:  //handler_t is: std::function<std::string (unat::event & evt)>;  callback::id_t add(unsigned short port,  const callback::handler_t & handler,  const std::string & comment);   void erase(callback::id_t id);  bool exist(callback::id_t id) const;  size_t size() const;   callback::sp_socket_t get_sp_socket(callback::id_t id) const;  }; }

net類以id,boost socket映射表為數據結構管理核心。提供add對本機端口注冊監聽以及回調函數。erase函數根據id來刪除監聽以及內部所創建的socket。exist判斷某個id是否存在。 size返回內部 所存儲的socket大小。

使用示例:

auto id = _sp_net->add(port,get_handler_by_callback(cb),"add multiple port");
auto ret_socket = _sp_net->get_sp_socket(id);

所有的服務端業務層功能邏輯實現都在service_nat目錄中。

 


端口預測

      這一部分是nat穿透的核心算法。對於兩個要通信的計算機節點都在對稱型nat的路由器后面,那這兩個節點在路由器端的對應公共端口是存在一定隨機性的,這就需要兩個計算機相互猜測對方所被分配到的公網端口。為了提高猜中的概率,作為客戶端的一方連續向對端發送大時udp包,且這些數據包從本地不同的端口發出。它們的目的端口,就是本節點猜對端的公網地址。

                                                                  p2pcpp端口預測時序圖

端口預測邏輯中都使用UDP包進行數據交互,所以為了應對UDP不可避免的網絡丟包問題。程序中在本地維護了一套主機狀態。在不同的運行階段,將會在不同的狀態這間切換。

enum status_t
{  _min_default = 1000,  online,  ready_to_predict,  predict,  as_server_listen,  as_client_send,  failed_end,  succeed_end,  end, //1009   offline,  idle,  waiting, //1010  client_waiting,  client_busy,  server_idle,  server_busy,  server_return_hello_world,  _max_default };

p2pcpp進程通過定時器每2秒與協調服務器端進行一次數據交互,把自身主機狀態通過UDP數據報文上報給協調服務器端。協調服務器根據主機上報過來的狀態,進行配對算法。決定將哪兩台主機配對進行端口互猜。並將結果下發給主機,主機 進行相關響應。

 

                                                                               p2pcpp狀態轉換圖

 

 


------------------------------------------------
交流QQ號:1175372067
電話:18551717618(同微信)
元幾科技.軟件3部
邁開步伐去探索
南京元幾科技有限公司
元幾社區: https://www.cnblogs.com/colin-vio
元幾官網: http://www.yuanji.tech:9900
------------------------------------------------

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM