NAT(NAPT)機制及應用


UDP/TCP的差異 TCP的模擬 模擬TCP的現實意義

本章內容分為三部分:

  • NAT(NAPT)機制及應用
  • TCP協議的特性
  • 使用UDP模擬TCP實現TCP協議中的主要特性

NAT(NATP)

我們已經學習過UDPTCP協議(伯克利socket接口函數)的使用,無論是sendto還是send,我們的目標IP地址都是公網IP,而不是局域網IP(本機通信或者局域網通信除外)。

當我們想要將流量發送到公網(廣域網)上時,目標IP地址必須是公網IP。

以上是網絡編程的基礎常識。

那么,為什么我主機上的釘釘能夠能跟你主機上的釘釘通信呢?我們兩台主機都在不同的局域網中,都位於網關(路由器)后面。

似乎道理也很簡單,因為釘釘服務器的存在,我們不過是將消息發送給了釘釘的公網服務器,然后服務器進行了轉發。那么,一台網關設備后面有若干台主機,每台主機上都有釘釘,那網關是怎么准確無誤的指導需要將釘釘消息發送到哪台主機呢?

最關鍵的問題是,我們的局域網IP地址192.168.0.1怎么就能與一個局域網后面的192.168.0.2主機通信呢?服務器的存在?為啥公網服務器就能與局域網IP通信呢?

要回答這個問題,就要知道,NAT機制。

為了緩解IP地址的緊張,現在網關都具備NAT功能,能夠只通過一個公網IP地址就能讓N台主機與外界通信。

NAT的全稱是Network Address Translation網絡地址轉換。

image.png

局域網地址之所以能訪問遠程公網服務器的原因在於在網關(路由器)設備中,有一個nat模塊專門用來處理局域網地址與公網地址的映射關系:

image.png

真的的秘密在於每台主機的流量到達網關后,其內網IP地址以及端口都會被改寫。

改寫為這個網關的外網IP地址和一個新的端口號因此內網IP:端口1外網IP:端口2形成了一個1對1的新映射,這個映射的組成元素一共有4個,任何一個元素不同都是一條新的映射。

其實注意到,並不是簡單的內網IP與外網IP組成一條映射,還包括端口這一元素,因此NAT又被稱為NAPT(P = Port)

因此,真實的通信就變成了這樣子:

image.png

NAT還未形成一個標准方案,不同的設備廠商都有自己的實現,不過大致說了現行的NAT有4種不同的類型:

  • 完全圓錐形NAT類型
  • 受限圓錐形NAT類型
  • 端口受限圓錐形NAT類型
  • 對稱NAT類型

從名字上看不出任何端倪,甚至有些莫名其妙。

image.png

當主機通過網關(路由器)訪問遠程服務器server-1時,流量經過網關前往server-1服務器時,便會建立一個NAT映射,將內部地址LocalIP:LocalPort映射到了外部地址WideIP:WidePort,此時通過WideIP:WidePort這個點就能訪問server-1服務器,而server-1也能講流量發送到WideIP:WidePort這個點,然后通過查NAT映射關系,網關將流量轉發到局域網主機上。不僅如此,即使之前沒有與主機通信過的server-2服務器此時也能直接通過WideIP:WidePort將流量發送到局域網內部主機,即server-2也能直接與局域網主機通信,而這一切得益於NAT表映射關系的建立

映射建立完成后,對目標主機的IP和端口都無限制,的這種類型,就是所謂的完全圓錐形NAT類型


image-20201126152448961

主機LocalIP:LocalPort訪問server-1時,NAT設備會創建一個NAT表映射,得到一個WideIP:WidePort,通過這個地址訪問主機server-1,此后server-1就能通過NAT設備將流量傳輸給主機了,與上面(完全圓錐形NAT類型)類型不同的是,此時server-2不能通過這個WideIP:WidePort訪問主機,而必須要是內部主機先與外部主機通信,然后外部主機才能將流量傳輸給內部主機。比如內部主機通過LocalIP:LocalPort先訪問了server-3后,此時server-3才能訪問內部主機(通過NAT設備)。

而對外部主機的地址要求是theWideHostIP:AnyPort。必須要是已經通過信的那個外部主機IP,而對外部主機的端口,不做要求。

映射建立完成后,對目標主機的IP有限定,對目標主機端口無限制,的這種類型,就是所謂的受限圓錐形NAT類型


當在『受限圓錐形NAT類型』的基礎上加一個端口限制后,就成了第三種NAT類型,即所謂的『端口受限圓錐形NAT類型

這意味着,只有主機先與外部server通信后,外部server才能與主機通信,並且前提還有,並不是只要外部主機IP地址符合要求就好,還必須要求外部主機的端口也不能變,如圖:

image.png

而最后一種類型就是『對稱NAT』,這種類型的限制最多。

image.png

只有先當內部主機訪問外部主機(服務器)后,外部主機(服務器)才能訪問內部主機,並且,只能沿着原路返回數據,也就是說,通過網關設備出去的外部地址都是一個唯一的點,通過這個點,只能訪問一對IP:端口號(注意,不是說只能訪問一台主機)

到目前為止,我們已經討論完了NAT的4種類型,路由器就是一個NAT設備。那么有個這個知識儲備后,有什么用呢?

主機之間的通信

C-S模型的架構是非常經典的並且占據互聯網大部分流量的一種模型,幾乎我們常說的網絡編程就是在使用C-S架構(及其變種)

image.png

這是經典的C-S通信架構,通過公網服務器,每一個客戶端都能訪問到這台服務器,而無論客戶端是否位於NAT后面(是否處於局域網中),這種設計的好處是明顯的:

  • 保證兩台主機之間肯定可以進行通信
  • 讓兩台主機實現通信的邏輯變得簡單
  • 很多時候業務邏輯並不要求兩台主機進行通信,而是服務器只作為資源的提供者,這種模式下C-S架構天生適合

以上都是這種架構的優勢。但這種架構並不適合所有場景(其實,沒有任何一種架構能包治百病),比如即時聊天軟件直接的通信就是主機與主機的通信了,那么在需要端與端的通信時,C-S模式的架構就不是最優的了(只是從技術上講,不從政策上講。因為政策上而言,服務器必須介入主機與主機的通信,用來保存通信內容供government查閱,這種情況下必須C-S架構,而某些主打隱私安全的設計就不是采用這種架構)

image.png

我們對C-S-C模式能夠理解,但是我們需要討論下p2p(peer to peer)可行的理由。(這部分只是在我們實際工作中可能不會使用上,但是對理解掌握網絡的完整性是個必不可少的一部分,甚至日后理解所謂的反射、隧道等都大有裨益)

image.png

根據圖示,兩台NAT之間的流量是可以直達的,但這是否意味這局域網主機1和局域網主機2就能因此而流量直達了呢?

答案是肯定的,但是還有幾個問題要解決:

  • 主機需要知道自己的公網IP地址(端口)
  • 主機需要讓另一台主機知道自己的公網IP地址(端口),且,自己也需要知道對方的

那么,怎么解決呢?

image.png

引入一個公網服務器,完美解決以上2個問題。

這個服務器通常被稱為『打洞服務器』,這個『洞』就是給NAT挖了個洞,讓流量可以穿透過去。那么這個打洞服務器做了幾個什么事情呢?

  • 識別局域網主機1和局域網主機2的外網地址以及端口
  • 相互交換對方的外網地址(端口)信息

這樣,局域網主機1里的相關進程就知道了局域網主機2的外網地址(端口),反之同理。這樣局域網主機1 、2里的某個相關進程都掌握了對方的外網地址(端口)。

那這樣是不是就意味着局域網主機1、2能直接通信了呢?

答案是不一定。

回顧我們上面討論的NAT的4種類型,會發現一種NAT類型是絕對無法打洞成功的。在此之前,我們來理一下正常情況下,是如何打洞的,步驟是什么。

1、主機A訪問打洞服務器

2、主機B訪問打洞服務器

3、打洞服務器交換兩個主機的外網地址信息(端口)

4、主機A訪問B的外網地址,此時NAT會記錄B的外網地址,當流量到達主機B的NAT設備后,因為NAT設備『不認識』(沒記錄過A主機,也不知道這個流量要轉發給那個主機),所以直接丟棄這個包,數據並不會到主機B,但是,此時B主機的NAT設備會記錄A的外網地址。

5、此時,打洞服務器會通知主機B,讓B主機馬上把流量發送到主機A的外網地址,此時因為在第4步時主機A的NAT設備記錄了主機B的外網信息,因此主機A的NAT設備會讓主機B的流量通過,並且會把B的流量准確的轉發給主機A。

6、此時,主機A會馬上訪問主機B的外網地址,因為在第4步時,主機B的NAT設備記錄了主機A的外網地址,同時在第5步時也記錄了主機B要訪問主機A的外網地址的信息,因此,主機B的NAT設備會讓主機A的流量通過,並且准確的轉發到主機B上

經過以上6步,就能建立主機A與主機B之間的端到端的通信了。

至此事情似乎都很完美,但是回頭看看我們上面所說的NAT類型的第四個,也就是『對稱NAT類型』,在這種類型的NAT面前,此路不通了。我們來推演一下:

當此時NAT類型是第4中類型(對稱NAT)時:

1、主機A訪問打洞服務器;NAT-A設備記錄映射(192.168.0.1:556643.250.201.20:6789),遠程服務器記錄A的外網地址為43.250.201.20:6789

2、主機B訪問打洞服務器;NAT-B設備記錄映射(192.168.0.2:7788113.250.201.20:4567),遠程服務器記錄B的外網地址為113.250.201.20:4567

3、交換2個外網地址信息

4、主機A訪問B的外網地址,113.250.201.20:4567 ,NAT直接拒絕,並且不會留下任何記錄。理由很簡單,這個外網地址建立的訪問路徑是本機地址-外網IP:端口1-打洞服務器地址 ,流量只能在這條路徑上傳輸,打洞服務器能與外網IP:端口1通信,但是當別的外網地址訪問這個B的地址時,直接被拒。也就是說在對稱NAT的類型中,本機地址-NAT外網地址-遠程外網地址 三者構成了獨一無二的通信鏈路,其他節點無法加入。

需要再三說明的是,這里的地址是指IP地址:端口號這一對組合

image.png

有NAT設備的地方,就有NAT類型。因此兩端其實有10種兩兩組合的情況。

我們不能簡單的說端口受限型NAT可以打洞,對稱型NAT不能打洞,而是要看雙方的組合是什么。

比如 對稱型-對稱型,這就是不能打洞的。而如果是受限錐型-對稱型則可能可以。

那么,用來打洞的通常是UDP流量,還是TCP流量呢?答案是UDP流量。

答案很簡單,並非TCP不行,而是用TCP打洞太難太難,操作手法復雜,而用UDP則相對簡單很多。

為什么?

回想一下打洞過程:

主機A的某進程需要通過socket訪問打洞服務器,為了讓主機端口固定,使用bind,將某個固定端口綁定到本機,此后又要創建一個socket訪問遠程主機B,使用TCP無法創建2個本機IP和綁定端口一致的socket

UDP就沒有這樣的問題。

這算是『非面向鏈接』協議的一點點『好處』吧。

遠程控制既可以通過C-S模式實現,或者p2p模式實現,至於那種方案更優,相信大家有自己的判斷。(在p2p的打洞中,如果打不通,會切換成C-S模式)。當然,C-S的實現模型更簡單,而NAT是可以嵌套的,因此情況會更復雜。

以上,就是有關NAT的相關內容。


免責聲明!

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



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