NAPT網路結構下TCP/UDP/ICMP存取外網原理思考

2023-01-31 06:00:08

背景

作為程式設計師,應該都聽說過NAT(Network Address Transfer,網路地址轉換)這一技術名詞,並或多或少大概知道其原理與作用--NAT是用於解決IPv4地址不夠用,保證我們能夠在IPv6普及前依然可以正常使用網際網路而廣泛使用的一個技術,其原理正如其名稱所示:其可以將私網IP通過閘道器(可以是路由器也可以是自身防火牆)轉換為公網IP而實現與網際網路的正常通訊。
粗看下來這個理解已經說透了NAT的用途與原理,但是如果進一步問出以下幾個問題,不少人(包括曾經的博主)就很難說清楚了,這裡記錄一下自己的思考總結,如有不對歡迎勘正。

NAT && NAPT之靈魂拷問

  1. NAT是將一個私網IP對映為一個公網IP與外網進行通訊,那一個公網IP可以對映繫結多個私網IP嗎?如果可以,怎麼識別目的為閘道器公網IP的網路包實際屬於哪個私網IP呢?
  2. NAT與NAPT是什麼關係?
  3. NAPT通過IP+port的方式解決私網IP到公網IP的多對一系結問題,但是port其實是傳輸層概念,對於TCP/UDP協定包我們很好理解可以根據其port實現單一公網IP到不同私網IP的繫結,那對於網路層協定如ICMP其並沒有port的概念,其目的地址僅由IP標識,那閘道器能夠識別出同一目的公網IP 的ICMP包對應的實際私網IP嗎?能的話又是怎麼做到的呢?

NAT

上面三個問題其實是層層遞進的關係,先來理清NAT到底是什麼,wikipedia上NAT定義如下:

網路地址轉換(英語:Network Address Translation,縮寫:NAT;又稱網路掩蔽、IP掩蔽)在計算機網路中是一種在IP封包通過路由器或防火牆時重寫來源IP地址或目的IP地址的技術。這種技術被普遍使用在有多臺主機但只通過一個公有IP地址存取網際網路的私有網路中。它是一個方便且得到了廣泛應用的技術。當然,NAT也讓主機之間的通訊變得複雜,導致了通訊效率的降低。

正如前面簡述,NAT本質上就是通過傳送時重寫來源IP(私網IP->公網IP),接收時重寫目的IP(公網IP->私網IP)實現多臺主機複用同一公網IP的目的。

Basic NAT

基本NAT(Basic NAT)只對IP地址進行了轉換,不支援埠對映,所以一個公網IP不能同時被兩個私網IP繫結,而只能被一個私網IP繫結,多個私網IP只能分不同時段獨佔式繫結同一公網IP。
Basic NAT又稱靜態NAT,實際對於解決IPv4地址不足並無助益,因為其支援同時上網的私有主機數最大也只能等於公網IP池的IP個數。

Basic NAT 使用場景

這種NAT的使用場景較少,目前能想到的實際應用場景是各雲廠商的彈性IP技術(EIP, Elastic IP)技術,其實質就是一個Basic NAT的使用。

NAPT

現在大家一般提到的NAT其實都是NAPT(Netwoard Address Port Transfer, 網路地址埠轉換),即同時會轉換IP+Port,這樣就可以做到多個私網IP同時使用一個公網IP對外通訊了--閘道器通過維護一個私網IP+port <->公網IP + Port的對映表來識別同一目的公網IP但不同Port對應的實際私網IP+port。

網路層協定怎麼Transfer?

正如問題3中提到的,Port是傳輸層才有的概念,多個私有主機IP的TCP、UDP連線通訊通過不同的IP+Port組合同時使用同一公網IP與網際網路進行通訊,但是網路層協定如ICMP是沒有Port的,NAPT怎麼處理這種情況呢?沒有Port難道不支援多個私有主機使用ICMP協定與公網通訊?
實際驗證當然是可以的,那麼NAPT是怎麼解決沒有Port的ICMP協定包的多個目的私有IP識別呢?
舉一個具體樣例如下:
私有主機Private0、Private1同時使用ping命令向公網IP 8.8.8.8 傳送ICMP回送請求包,在通過閘道器時對應私網Private0/1會被轉換成公網IP Public0, 當閘道器收到8.8.8.8的回包時,發現其目的IP的Public0,怎麼判定這個包到底是回給Private0還是Private1的呢?
仔細思考這一樣例,會發現其本質和同一臺主機上多個程序同時向8.8.8.8傳送ICMP回送請求包的場景本質上是一樣的,即:主機M0上開啟兩個程序Process0、Process1分別使用ping命令向8.8.8.8傳送ICMP回送請求,當M0收到來自8.8.8.8的回包時,怎麼判斷這個回包應該屬於Process0還是Process1?
要回答這個問題,需要從ICMP回送請求包的格式本身來尋找答案,ICMP包是封裝在IP包之中的,其完整的IP封包格式如下(以下圖片引自20 張圖解: ping 的工作原理, 感謝小林):

對應ICMP回送請求包其ICMP頭格式如下:

如上圖,ICMP回送請求包中包含一個識別符號欄位,用以區分是哪個應用程式發 ICMP 包,比如可以用程序 PID 作為識別符號,這樣當M0收到來自8.8.8.8的回包時,其根據識別符號就能知道該包到底屬於哪個程序了。
同理 公網閘道器在處理Private0、Private1的ICMP請求報時,也會根據識別符號欄位建立一個對映關係,當收到8.8.8.8的回包時,根據回包的識別符號就能在之前建立的對映關係中確定回包實際所屬的私網IP到底是Private0還是Private1了。
轉載請註明出處,原文地址: https://www.cnblogs.com/AcAc-t/p/nat_napt_icmp_thinking.html

參考

https://zh.wikipedia.org/wiki/網路地址轉換
https://www.cnblogs.com/xiaolincoding/p/12571184.html
https://www.cnblogs.com/AcAc-t/p/nat_napt_icmp_thinking.html
https://www.alibabacloud.com/help/zh/elastic-ip-address/latest/what-is-an-eip