可能是目前最全的講 NAT 的文章

對於 NAT,你想知道的,可能包括以下幾點:

  • NAT 是啥

  • 爲啥需要 NAT

  • NAT 的分類

  • NAT 是怎麼實現的

  • NAT 有什麼問題

  • 防火牆與 NAT

01 NAT 是啥

NAT,全稱叫 Network Address Translation,網絡地址轉換/翻譯,簡單講就是能將私有地址和公有地址進行轉換的一個技術。NAT 功能通常會被集成到路由器、防火牆、或獨立的 NAT 設備中。

02 爲啥需要 NAT

爲什麼需要轉換私有地址和公有地址,以及什麼是私有地址和公有地址?

我們知道,由於歷史原因,IPv4 地址起初設計的時候,長度只有 32 位,所以只能提供大約 40 億個地址。這造成了 IPv4 地址的耗盡危機。雖然後面 IPv6 地址被設計出來,能夠提供更多的 IP 地址。

但 IPv4 和 IPv6 並不兼容,IPv4 向 IPv6 遷移也並不容易。在遷移的這段時間內,急需一些替代技術來緩解 IPv4 地址的稀缺。NAT 就是其中一種,另外還有 CIDR。

理論上,每個 IP 地址代表了 Internet 上的一個設備,但有一些地址被保留,用作私有的 IP 地址,如下面的三段:

From             To
10.0.0.0         10.255.255.255
172.16.0.0        172.31.255.255
192.168.0.0        192.168.255.255

私有地址只用於局域網內部通信,與之對應的就是公有地址。理論上,私有地址不應該在互聯網被看到,而公有地址正恰好相反。由於互聯網上有通信需求的設備衆多,所以公有地址就顯得格外稀缺而珍貴,這個時候,如果說能將私有地址在不同的私有網絡中重複使用,那將大大緩解公有地址的使用耗盡。

NAT 就是提出來爲私有網絡服務的。在私有網絡中的主機使用私有 IP 地址,當需要與外部 Internet 通信時,網關路由器執行 NAT 功能,將私有 IP 地址轉爲公有地址。這就可以緩解設備對公有 IP 地址的需求。

03 NAT 的分類

NAT 從概念上說很簡單,就是進行私有地址和公有地址的轉換,但是怎麼轉換的,一對一,還是多對一?不同的方法對公網 IP 地址的節省都不一樣,根據使用公網 IP 地址數量的不同, NAT 分爲以下三類:

① 靜態 NAT

這個是最基本的,一對一 NAT,就是靜態配置一個私有地址對應一個公網地址,但是問題也很明顯,基本沒有緩解對公網 IP 地址的使用。

內網 IP外網 IP
192.168.1.10219.152.168.222
192.168.1.11219.152.168.223
192.168.1.12219.152.168.224

② 動態 NAT

也叫地址池 NAT,網關路由器維護一個動態變化的 NAT 地址池,當有私網設備要訪問公網時,會得到一個臨時的公有 IP 地址,若該設備在一定時間內沒有和公網通信,這個臨時地址就會被釋放,給其他設備用,有關它的 IP 映射關係也會從 NAT table 中刪除。

通常來說,一個局域網中只有少數設備處於開機狀態,且有訪問外網的需求,動態 NAT 就非常適用,它可以極大減少公有 IP 地址的分配和使用。但這樣還不夠,公有地址分配還是相對較多,且管理上不夠靈活,所以就有了下面這種方式。

NAPT

全稱叫 Network Address and Port Translation,網絡地址和端口轉換,它比前面的方式多利用了 Port 層面的信息進行轉換,可以實現多對一,即多個私有地址映射一個公有地址的需求,更能節省地址且管理更靈活。

其實更爲準確的理解應該是 IP + session 的轉換,session 是更爲通用的一種說法,指代的是能夠對不同類型的數據進行標識的特定字段,比如 TCP/UDP 報文,session=port,ICMP 報文,session=ICMP Indentifier。下面顯示一個帶 IP+端口號的 NAT 表:

內網 IP外網 IP
192.168.1.10:5566219.152.168.222:9200
192.168.1.11:80219.152.168.222:9201
192.168.1.12:4465219.152.168.222:9202

可以看到,只用了一個 公網 IP,即可完成三個內網 IP 的轉換。

以上方法是根據使用公網 IP 地址數量進行分類,也有一種分類是根據 NAT 的數據流向進行分類,將 NAT 分爲:

  • SNAT :數據流從私網訪問公網,到達 NAT 網關進行 SNAT,根據配置的 NAT 表,將數據包的 src_ip 改爲對應的公網地址,如果 port 有記錄,也要相應修改

  • DNAT :數據流從公網訪問私網,由於不知道私網地址,所以數據包的 dst_ip 是 NAT 網關對外的公網地址,到達 NAT 網關進行 DNAT,同理將數據包 dst_ip 改爲對應的私網地址,同樣 port 有記錄也做修改

04 NAT 是怎麼實現的

囉嗦這麼多,想必大家應該都知道 NAT 是怎麼實現的了,無非就是網關設備或者專用 NAT 設備維護一個 NAT 映射表來完成 NAT 的轉換工作,這個過程我們重點注意兩點:

  • 連接跟蹤

  • checksum 修改

在 NAT 網關收到響應包的時候,它是如何知道要傳給內部的具體哪個主機呢?這裏主要用到的技術就是連接跟蹤。

在 NAT 網關收到內部主機的請求包之後,會做 SNAT ,然後把本次連接記錄保存到一個連接跟蹤表(Track Table)裏,當收到響應包之後,就可以根據 Track table 確定目標主機,然後做 DNAT,轉發給主機。

如果是存在端口轉換的情況,即 NAPT,那麼需要在 Track table 里加入端口信息區分,這樣來回的 NAT 轉換也就不會有問題。

圖片來源ref1

checksum 的修改就是很自然的,源目的 IP (NAPT 還有端口)改變了,包頭中有關聯的字段也要相應改變,其中關聯的就是 checksum 字段。

checksum 字段存在於 IP 頭部和 TCP/UDP 頭部(UDP 頭部是可選的),IP 頭部 checksum 的校驗範圍只在頭部,TCP/UDP checksum 則包括一個僞首部+TCP/UDP header + TCP/UDP payload,僞首部就包含了 IP 地址信息,所以當 IP 改變了,IP 頭部和 TCP/UDP 頭部(如果有)的 checksum 都需要相應改變。

另外,還需要注意的是,其他的一些協議,比如說 ICMP、FTP、DNS 等,它們的數據中如果有攜帶 IP 和 TCP port 信息的,也需要修改 checksum 的字段。

05 NAT 有什麼問題

看很多資料上,羅列了好幾種 NAT 的問題,比如說 “違反 IP 的體系結構、分層原則,網關設備變重等等”,這些問題在我看來有點雞蛋裏挑骨頭,要減緩公網 IP 地址的使用,這是必然的做法。

要說問題,可能就在於兩點:

1)從性能上來說,地址轉換增加了延遲,這個也有點挑,對於高性能的應用來說,能直接轉必然也不會考慮 NAT。

2)有些嵌入 IP 地址或端口的應用可能工作會比較麻煩。典型的比如 FTP,它的 payload 中會嵌入一些 IP 地址和端口號的信息,這種情況下除了需要 NAT 轉換表負責轉換包頭的 IP 和端口字段外,還需要額外的程序來處理 payload 中關聯的字段,就會給網關設備帶來更加繁重的處理壓力。

06 NAT 與防火牆

NAT 將網絡劃分爲內部網絡和外部網絡這個特性,基本就是實現一個防火牆的功能了。它隱藏了主機自己的真實 IP,僅通過端口複用來與外網通信。所以我們也看到,Linux系統實現的內部防火牆 iptables 中就有 NAT 的實現。

下面就來看看 iptables 中的 NAT 是如何做到防護的。

我們都知道,iptables 有 4 表 5 鏈的防護體系,NAT 就是其中的一張表,它可以作用在 PREROUTING、OUTPUT、POSTROUTING 這 3 條鏈上(有些系統還包含INPUT 鏈,不是必須的),如下圖所示:

其中,SNAT 因爲要負責轉換出本機的包,所以是作用在 OUTPUT 和 POSTROUTING 兩條鏈上,OUTPUT 負責從本機發出的包的 NAT,POSTROUTING 負責非本機轉發的包的 NAT(也就是經過 FORWARD 鏈轉發的包);

而 DNAT 則是負責轉換進入主機的包,所以作用在 PREROUTING 鏈上。

通過 iptables 的命令,我們可以配置下面的 SNAT 和 DNAT 命令來實現地址的轉換。

1. 首先配置 SNAT,我們配到 POSTROUTING 鏈上:

iptables -t nat -A POSTROUTING -s 10.10.0.0/16 -j SNAT --to-source 公網IP

這條命令的意思是將來自 10.10.0.0/16 網段的報文的源地址改爲公司的公網 IP 地址。

  • -t nat:表示 NAT 表

  • -A POSTROUTING:表示將該條規則添加到 POSTROUTING 鏈的末尾,A 就是 append。

  • -j SNAT:表示使用 SNAT 動作

  • --to-source:表示將報文的源 IP 修改爲哪個公網 IP 地址

2. 然後配置 DNAT,配到 PREROUTING 鏈上:

iptables -t nat -I PREROUTING -d 公網IP -p tcp --dport 公網端口 -j DNAT --to-destination 私網IP:端口號

這條命令的意思是將來自公網IP:端口號的報文的目的地址改爲私網IP:端口,可以看到這裏多了端口的信息。原因是要區分公網訪問的是私網的那個服務,所以需要明確到端口層級,才能精確送到客戶端。而 SNAT 不需要端口信息也可以完成正確轉發。

  • -I PREROUTING:表示將該條規則插入到 PREROUTING 的首部,I 就是 insert

  • --to-destination:表示將報文的目的 IP:端口修改爲哪個私網IP:端口

06 總結

NAT 的分類,現在主要的應用都是 NAPT

SNAT、DNAT,NAT 與防火牆的實現

IPv6 也有 NAT 的版本,叫 NAT6,爲什麼 IPv6 也需要 NAT 呢?大家可以思考一下。

參考:

https://www.cnblogs.com/dongzhuangdian/p/5105844.html

http://www.zsythink.net/archives/1764


後臺回覆“加羣”,帶你進入高手如雲交流羣

推薦閱讀:

什麼是物聯網?這裏有你需要了解的一切

網絡通信中的幾種握手

【趣圖】程序員一樂!

Kubernetes的架構爲什麼是這個樣的?

任何人都能看得懂的網絡協議之ARP

用好你的網絡瑞士軍刀netcat

一次Linux系統被攻擊的分析過程

Linux下刪除大量文件效率對比

130 個相見恨晚的神器網站

分享20個Linux命令小貼士與技巧

一文帶你徹底理解文件系統

5G與Wi-Fi6空口技術對

牛逼的Linux性能剖析—perf

HTTPS 的 7 次握手以及 9 倍時延

一文搞定 UDP 和 TCP 高頻面試題!


喜歡,就給我一個“在看”


10T 技術資源大放送!包括但不限於:雲計算、虛擬化、微服務、大數據、網絡、Linux、Docker、Kubernetes、Python、Go、C/C++、Shell、PPT 等。在公衆號內回覆「1024」,即可免費獲取!!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章