Linux 中的快速路由和 NAT

隨著 IPv4 位址的耗盡,許多電信業者都面臨使用位址轉換為其客戶提供網路存取的需求。 在本文中,我將告訴您如何在商用伺服器上獲得運營商級 NAT 效能。

歷史上的位

IPv4 位址空間耗盡的話題不再是新鮮事。 在某個時候,RIPE 中出現了等待名單,然後出現了交易所,在這些交易所上進行地址區塊的交易並達成租賃這些地址的交易。 逐漸地,電信業者開始使用位址和連接埠轉換來提供網路存取服務。 有些人無法獲得足夠的地址來向每個訂閱者發放「白色」地址,而另一些人則開始透過拒絕在二級市場上購買地址來省錢。 網路設備製造商支持這個想法,因為此功能通常需要額外的擴充模組或授權。 例如,在 Juniper 的 MX 路由器系列中(最新的 MX104 和 MX204 除外),您可以在單獨的 MS-MIC 服務卡上執行 NAPT,Cisco ASR1k 需要 CGN 許可證,Cisco ASR9k 需要單獨的 A9K-ISM-100 模組以及他的A9K-CGN 許可證-LIC。 一般來說,這種樂趣要花很多錢。

iptables的

執行 NAT 的任務不需要專門的運算資源;它可以透過安裝在例如任何家庭路由器中的通用處理器來解決。 在電信業者的規模上,可以使用執行 FreeBSD (ipfw/pf) 或 GNU/Linux (iptables) 的商品伺服器來解決這個問題。 我們不會考慮 FreeBSD,因為… 我很久以前就不再使用這個作業系統了,所以我們將堅持使用 GNU/Linux。

啟用地址轉換並不困難。 首先需要在 iptables 的 nat 表中註冊一條規則:

iptables -t nat -A POSTROUTING -s 100.64.0.0/10 -j SNAT --to <pool_start_addr>-<pool_end_addr> --persistent

作業系統將載入 nf_conntrack 模組,該模組將監視所有活動連接並執行必要的轉換。 這裡有幾個微妙之處。 首先,由於我們討論的是電信業者規模的 NAT,因此有必要調整逾時,因為使用預設值時,轉換表的大小將迅速成長到災難性的值。 以下是我在伺服器上使用的設定範例:

net.ipv4.ip_forward = 1
net.ipv4.ip_local_port_range = 8192 65535

net.netfilter.nf_conntrack_generic_timeout = 300
net.netfilter.nf_conntrack_tcp_timeout_syn_sent = 60
net.netfilter.nf_conntrack_tcp_timeout_syn_recv = 60
net.netfilter.nf_conntrack_tcp_timeout_established = 600
net.netfilter.nf_conntrack_tcp_timeout_fin_wait = 60
net.netfilter.nf_conntrack_tcp_timeout_close_wait = 45
net.netfilter.nf_conntrack_tcp_timeout_last_ack = 30
net.netfilter.nf_conntrack_tcp_timeout_time_wait = 120
net.netfilter.nf_conntrack_tcp_timeout_close = 10
net.netfilter.nf_conntrack_tcp_timeout_max_retrans = 300
net.netfilter.nf_conntrack_tcp_timeout_unacknowledged = 300
net.netfilter.nf_conntrack_udp_timeout = 30
net.netfilter.nf_conntrack_udp_timeout_stream = 60
net.netfilter.nf_conntrack_icmpv6_timeout = 30
net.netfilter.nf_conntrack_icmp_timeout = 30
net.netfilter.nf_conntrack_events_retry_timeout = 15
net.netfilter.nf_conntrack_checksum=0

其次,由於轉換表的預設大小不適用於電信業者的條件,因此需要增加:

net.netfilter.nf_conntrack_max = 3145728

還需要增加儲存所有廣播的雜湊表的桶數(這是 nf_conntrack 模組中的一個選項):

options nf_conntrack hashsize=1572864

經過這些簡單的操作後,就獲得了一個完整的工作設計,可以將大量客戶端位址轉換為外部位址池。 然而,該解決方案的性能還有很多不足之處。 在我第一次嘗試使用 GNU/Linux 進行 NAT 時(大約 2013 年),我能夠以每台伺服器 7Mpps 的速度獲得大約 0.8Gbit/s 的效能 (Xeon E5-1650v2)。 從那時起,GNU/Linux 內核網路堆疊進行了許多不同的優化,同一硬體上一台伺服器的效能已提高到幾乎 18-19 Gbit/s、1.8-1.9 Mpps(這些是最大值) ,但對一台伺服器處理的流量的需求成長得更快。 因此,開發了一些方案來平衡不同伺服器上的負載,但這一切都增加了設定、維護和維護所提供服務品質的複雜性。

NF表

如今,「移包」軟體的一個流行趨勢是使用DPDK和XDP。 關於這個主題已經寫了很多文章,做了很多不同的演講,商業產品正在出現(例如 VasExperts 的 SKAT)。 但考慮到電信業者的程式資源有限,基於這些框架自行創建任何「產品」是相當有問題的。 未來操作這樣的解決方案將會更加困難;特別是必須開發診斷工具。 例如,具有 DPDK 的標準 tcpdump 不會像那樣工作,並且它不會「看到」使用 XDP 傳送迴線路的封包。 在所有關於將資料包轉發到用戶空間的新技術的討論中,它們都沒有被注意到 報告 и 文章 Pablo Neira Ayuso,iptables 維護者,關於 nftables 中流量卸載的開發。 讓我們更詳細地看看這個機制。

主要想法是,如果路由器在流的兩個方向上傳遞來自一個會話的資料包(TCP 會話進入 ESTABLISHED 狀態),則無需通過所有防火牆規則傳遞該會話的後續資料包,因為所有這些檢查仍然會隨著封包進一步傳輸到路由而結束。 我們實際上不需要選擇路由 - 我們已經知道我們需要在此會話中將封包傳送到哪個介面以及哪個主機。 剩下的就是儲存這些資訊並在資料包處理的早期階段將其用於路由。 進行NAT時,需要額外儲存nf_conntrack模組翻譯的位址和連接埠變化資訊。 是的,當然,在這種情況下,iptables 中的各種監管器和其他資訊和統計規則將停止工作,但在單獨的常設 NAT 或邊界的任務框架內,這並不那麼重要,因為服務分佈在各個設備上。

組態

要使用這個功能我們需要:

  • 使用新鮮的內核。 儘管該功能本身出現在內核 4.16 中,但在相當長的一段時間內它都非常“原始”,並且經常引起內核恐慌。 2019 年 4.19.90 月左右,當 LTS 核心 5.4.5 和 XNUMX 發佈時,一切都穩定下來。
  • 使用 nftables 的最新版本以 nftables 格式重寫 iptables 規則。 與 0.9.0 版本完全相容

如果第一點原則上的一切都很清楚,最主要的是不要忘記在組裝期間將模組包含在配置中(CONFIG_NFT_FLOW_OFFLOAD = m),那麼第二點需要解釋。 nftables 規則的描述與 iptables 中的規則完全不同。 Документация 揭示了幾乎所有的點,也有特殊的 轉換器 從 iptables 到 nftables 的規則。 因此,我僅給出設定 NAT 和流量卸載的範例。 一個小傳說例如: , - 這些是流量通過的網路介面;實際上可以有兩個以上。 , —「白色」位址範圍的起始和結束位址。

NAT配置非常簡單:

#! /usr/sbin/nft -f

table nat {
        chain postrouting {
                type nat hook postrouting priority 100;
                oif <o_if> snat to <pool_addr_start>-<pool_addr_end> persistent
        }
}

對於流量卸載,情況稍微複雜一些,但很容易理解:

#! /usr/sbin/nft -f

table inet filter {
        flowtable fastnat {
                hook ingress priority 0
                devices = { <i_if>, <o_if> }
        }

        chain forward {
                type filter hook forward priority 0; policy accept;
                ip protocol { tcp , udp } flow offload @fastnat;
        }
}

事實上,這就是整個設定。 現在,所有 TCP/UDP 流量都將落入 fastnat 表中,並且處理速度會更快。

Результаты

為了清楚地說明這有多“快”,我將附上兩台真實伺服器上的負載螢幕截圖,具有相同的硬體(Xeon E5-1650v2)、相同的配置、使用相同的Linux 內核,但在iptables 中執行NAT (NAT4) 和 nftables (NAT5)。

Linux 中的快速路由和 NAT

螢幕截圖中沒有每秒資料包的圖表,但在這些伺服器的負載設定檔中,平均資料包大小約為 800 字節,因此該值高達 1.5Mpps。 可以看到,帶有nftables的伺服器有巨大的效能儲備。 目前,該伺服器在 30Mpps 下的處理速度高達 3Gbit/s,顯然能夠滿足 40Gbps 的實體網路限制,同時擁有空閒的 CPU 資源。

我希望這份資料對試圖提高伺服器效能的網路工程師有用。

來源: www.habr.com

添加評論