41 | 案例篇:如何優化 NAT 性能?(上)


上一節,探究了網絡延遲增大問題的分析方法,並通過一個案例,掌握了如何用 hping3、tcpdump、Wireshark、strace 等工具,來排查和定位問題的根源。
簡單回顧一下,網絡延遲是最核心的網絡性能指標。由於網絡傳輸、網絡包處理等各種因素的影響,網絡延遲不可避免。但過大的網絡延遲,會直接影響用戶的體驗。
所以,在發現網絡延遲增大的情況后,你可以先從路由、網絡包的收發、網絡包的處理,再到應用程序等,從各個層級分析網絡延遲,等到找出網絡延遲的來源層級后,再深入定位瓶頸所在。
今天,來看看,另一個可能導致網絡延遲的因素,即網絡地址轉換(Network Address Translation),縮寫為 NAT。
接下來,我們先來學習 NAT 的工作原理,並弄清楚如何優化 NAT 帶來的潛在性能問題。

NAT 原理

NAT 技術可以重寫 IP 數據包的源 IP 或者目的 IP,被普遍地用來解決公網 IP 地址短缺的問題。它的主要原理就是,網絡中的多台主機,通過共享同一個公網 IP 地址,來訪問外網資源。同時,由於 NAT 屏蔽了內網網絡,自然也就為局域網中的機器提供了安全隔離。

你既可以在支持網絡地址轉換的路由器(稱為 NAT 網關)中配置 NAT,也可以在 Linux 服務器中配置 NAT。如果采用第二種方式,Linux 服務器實際上充當的是“軟”路由器的角色。

NAT 的主要目的,是實現地址轉換。根據實現方式的不同,NAT 可以分為三類:
  • 靜態 NAT,即內網 IP 與公網 IP 是一對一的永久映射關系;
  • 動態 NAT,即內網 IP 從公網 IP 池中,動態選擇一個進行映射;
  • 網絡地址端口轉換 NAPT(Network Address and Port Translation),即把內網 IP 映射到公網 IP 的不同端口上,讓多個內網 IP 可以共享同一個公網 IP 地址。

NAPT 是目前最流行的 NAT 類型,我們在 Linux 中配置的 NAT 也是這種類型。而根據轉換方式的不同,我們又可以把 NAPT 分為三類。
  • 第一類是源地址轉換 SNAT,即目的地址不變,只替換源 IP 或源端口。SNAT 主要用於,多個內網 IP 共享同一個公網 IP ,來訪問外網資源的場景。
  • 第二類是目的地址轉換 DNAT,即源 IP 保持不變,只替換目的 IP 或者目的端口。DNAT 主要通過公網 IP 的不同端口號,來訪問內網的多種服務,同時會隱藏后端服務器的真實 IP 地址。
  • 第三類是雙向地址轉換,即同時使用 SNAT 和 DNAT。當接收到網絡包時,執行 DNAT,把目的 IP 轉換為內網 IP;而在發送網絡包時,執行 SNAT,把源 IP 替換為外部 IP。

雙向地址轉換,其實就是外網 IP 與內網 IP 的一對一映射關系,所以常用在虛擬化環境中,為虛擬機分配浮動的公網 IP 地址。

為了幫你理解 NAPT,我畫了一張圖。我們假設:
  • 本地服務器的內網 IP 地址為 192.168.0.2;
  • NAT 網關中的公網 IP 地址為 100.100.100.100;
  • 要訪問的目的服務器 baidu.com 的地址為 123.125.115.110。

那么 SNAT 和 DNAT 的過程,就如下圖所示:
從圖中,你可以發現:

  • 當服務器訪問 baidu.com 時,NAT 網關會把源地址,從服務器的內網 IP 192.168.0.2 替換成公網 IP 地址 100.100.100.100,然后才發送給 baidu.com;
  • 當 baidu.com 發回響應包時,NAT 網關又會把目的地址,從公網 IP 地址 100.100.100.100 替換成服務器內網 IP 192.168.0.2,然后再發送給內網中的服務器。

了解了 NAT 的原理后,我們再來看看,如何在 Linux 中實現 NAT 的功能。

iptables 與 NAT

Linux 內核提供的 Netfilter 框架,允許對網絡數據包進行修改(比如 NAT)和過濾(比如防火牆)。在這個基礎上,iptables、ip6tables、ebtables 等工具,又提供了更易用的命令行接口,以便系統管理員配置和管理 NAT、防火牆的規則。

其中,iptables 就是最常用的一種配置工具。要掌握 iptables 的原理和使用方法,最核心的就是弄清楚,網絡數據包通過 Netfilter 時的工作流向,下面這張圖就展示了這一過程。
(圖片來自 Wikipedia)

在這張圖中,綠色背景的方框,表示表(table),用來管理鏈。Linux 支持 4 種表,包括 filter(用於過濾)、nat(用於 NAT)、mangle(用於修改分組數據) 和 raw(用於原始數據包)等。

跟 table 一起的白色背景方框,則表示鏈(chain),用來管理具體的 iptables 規則。每個表中可以包含多條鏈,比如:
  • filter 表中,內置 INPUT、OUTPUT 和 FORWARD 鏈;
  • nat 表中,內置 PREROUTING、POSTROUTING、OUTPUT 等。

當然,你也可以根據需要,創建你自己的鏈。

灰色的 conntrack,表示連接跟蹤模塊。它通過內核中的連接跟蹤表(也就是哈希表),記錄網絡連接的狀態,是 iptables 狀態過濾(-m state)和 NAT 的實現基礎。

iptables 的所有規則,就會放到這些表和鏈中,並按照圖中順序和規則的優先級順序來執行。

針對今天的主題,要實現 NAT 功能,主要是在 nat 表進行操作。而 nat 表內置了三個鏈:
  • PREROUTING,用於路由判斷前所執行的規則,比如,對接收到的數據包進行 DNAT。
  • POSTROUTING,用於路由判斷后所執行的規則,比如,對發送或轉發的數據包進行 SNAT 或 MASQUERADE。
  • OUTPUT,類似於 PREROUTING,但只處理從本機發送出去的包。

熟悉 iptables 中的表和鏈后,相應的 NAT 規則就比較簡單了。我們還以 NAPT 的三個分類為例,來具體解讀一下。

SNAT

根據剛才內容,我們知道,SNAT 需要在 nat 表的 POSTROUTING 鏈中配置。我們常用兩種方式來配置它。

第一種方法,是為一個子網統一配置 SNAT,並由 Linux 選擇默認的出口 IP。這實際上就是經常說的 MASQUERADE:
$ iptables -t nat -A POSTROUTING -s 192.168.0.0/16 -j MASQUERADE
第二種方法,是為具體的 IP 地址配置 SNAT,並指定轉換后的源地址:
$ iptables -t nat -A POSTROUTING -s 192.168.0.2 -j SNAT --to-source 100.100.100.100

DNAT

再來看 DNAT,顯然,DNAT 需要在 nat 表的 PREROUTING 或者 OUTPUT 鏈中配置,其中, PREROUTING 鏈更常用一些(因為它還可以用於轉發的包)。
$ iptables -t nat -A PREROUTING -d 100.100.100.100 -j DNAT --to-destination 192.168.0.2

雙向地址轉換

雙向地址轉換,就是同時添加 SNAT 和 DNAT 規則,為公網 IP 和內網 IP 實現一對一的映射關系,即:
iptables -t nat -A POSTROUTING -s 192.168.0.2 -j SNAT --to-source 100.100.100.100
iptables -t nat -A PREROUTING -d 100.100.100.100 -j DNAT --to-destination 192.168.0.2
在使用 iptables 配置 NAT 規則時,Linux 需要轉發來自其他 IP 的網絡包,所以你千萬不要忘記開啟 Linux 的 IP 轉發功能。
你可以執行下面的命令,查看這一功能是否開啟。如果輸出的結果是 1,就表示已經開啟了 IP 轉發:
sysctl net.ipv4.ip_forward
net.ipv4.ip_forward = 1
如果還沒開啟,你可以執行下面的命令,手動開啟:
sysctl -w net.ipv4.ip_forward=1
net.ipv4.ip_forward = 1
當然,為了避免重啟后配置丟失,不要忘記將配置寫入 /etc/sysctl.conf 文件中:
cat /etc/sysctl.conf | grep ip_forward
net.ipv4.ip_forward=1
講了這么多的原理,那當碰到 NAT 的性能問題時,又該怎么辦呢?結合我們今天學過的 NAT 原理,你先自己想想,動手試試,下節課我們繼續“分解”。

小結

今天,我們一起學習了 Linux 網絡地址轉換 NAT 的原理。
NAT 技術能夠重寫 IP 數據包的源 IP 或目的 IP,所以普遍用來解決公網 IP 地址短缺的問題。它可以讓網絡中的多台主機,通過共享同一個公網 IP 地址,來訪問外網資源。同時,由於 NAT 屏蔽了內網網絡,也為局域網中機器起到安全隔離的作用。
Linux 中的 NAT ,基於內核的連接跟蹤模塊實現。所以,它維護每個連接狀態的同時,也會帶來很高的性能成本。具體 NAT 性能問題的分析方法,我們將在下節課繼續學習。

思考
最后,給你留一個思考題。MASQUERADE 是最常用的一種 SNAT 規則,常用來為多個內網 IP 地址提供共享的出口 IP。
假設現在有一台 Linux 服務器,使用了 MASQUERADE 的方式,為內網的所有 IP 提供出口訪問功能。那么,
當多個內網 IP 地址的端口號相同時,MASQUERADE 還可以正常工作嗎?
如果內網 IP 地址數量或請求數比較多,這種方式有沒有什么隱患呢?
歡迎在留言區和我討論,也歡迎你把這篇文章分享給你的同事、朋友。我們一起在實戰中演練,在交流中進步。


免責聲明!

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



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