Iptables

iptable 的 ip 轉發導致奇怪的行為

  • October 26, 2022

我的目標很簡單:使用 IP 轉發建構一個大容量、快速、低延遲的軟交換機。我有一個伺服器測試“伺服器”和 2 個測試客戶端:“客戶端 1”和“客戶端 2”。“Client1:c1”正在向“Server:s1”發送 udp 數據包,“Client2:c2”正在向“Server:s2”發送 udp 數據包。我只想將“客戶端:c1”數據包轉發到“客戶端:c2”,反之亦然。不介意這是否可能僅使用伺服器中的 1 個埠。‘Client1’ & ‘Client2’ 目前是一個簡單的 udp 發送者執行緒,它不斷地發送 udp 數據包。現在我正在應用規則:

sudo iptables --table nat --append PREROUTING --protocol udp --destination 'Server' --dport 's1' --jump DNAT --to-destination 'Client2:c2'

sudo iptables --table nat --append PREROUTING --protocol udp --destination 'Server' --dport 's2' --jump DNAT --to-destination 'Client1:c1'

sudo iptables --table nat --append POSTROUTING --protocol udp --destination 'Client2' --dport 'c2' --jump SNAT --to-source 'Server:s0'

sudo iptables --table nat --append POSTROUTING --protocol udp --destination 'Client1' --dport 'c1' --jump SNAT --to-source 'Server:s0' 

如果我立即應用此規則,然後同時啟動“Client1”和“Client2”執行緒,它就可以正常工作。即使我一次刪除所有規則,它也可以正常工作,但是如果我在“Client1”和“Client2”不斷發送數據的時候開始逐個添加/刪除此規則,問題就開始了。

行為1:‘Client1’和’Client2’正在執行(沒有任何規則被應用)然後我一次將4個規則應用到’Server’,然後它應該像以前一樣工作,但不是……現在’Server ’ 只是將 ‘Client1’ 數據包轉發到 ‘Client2’ ,甚至 SNAT 也不起作用。儘管經過一段時間後它仍然有效。其他行為就是這樣,當我將某些規則應用於“伺服器”iptable 時,如果“客戶端1”和“客戶端2”正在執行,則該規則不會立即生效。

行為 2:我也碰巧刷新了 nat 表並且伺服器仍在轉發一段時間。

行為 3:當 ‘Client1’ 和 ‘Client2’ 仍在發送/接收時,按規則 1 按 1 應用/刪除時,它不會隨機生效

我在幾篇文章中搜尋並發現 iptables 規則立即生效,但對於我們的情況,它不是,特別是一些規則有效,有些不是突然,我們在這裡做錯了什麼?是否有某種記憶體“伺服器”iptable 維護或是否需要重新載入,但我發現沒有重新載入選項?**我對“socat”不感興趣,因為它將數據包帶到使用者空間,這對大容量數據包有瓶頸。**在此先感謝您的幫助..!

以下將重定向任何從client1:port1server:ports被傳遞到 的東西client2:port2,它顯示為來自server:ports

iptables -t nat -A PREROUTING -p udp -s client1 --sport port1 -d server --dport ports -j DNAT --to-destination client2:port2
iptables -t nat -A POSTROUTING -p udp -s client1 --sport port1 -d client2 --dport port2 -j SNAT --to-source server:ports

第一條規則將目標從更改server:portsclient2:port2(因為它是DNAT規則),第二條規則將源從更改client1:port1server:ports。當數據包通過第二條規則時,它的目的地已經改變,但源沒有,所以規則中的匹配可能看起來很奇怪。回復將自動進行反向翻譯。

如果您希望在 client2 上發起的對話(而不是回复)以類似方式工作,則需要添加鏡像規則:

iptables -t nat -A PREROUTING -p udp -s client2 --sport port2 -d server --dport ports -j DNAT --to-destination client1:port1
iptables -t nat -A POSTROUTING -p udp -s client2 --sport port2 -d client1 --dport port1 -j SNAT --to-source server:ports

如果伺服器有任何過濾,您需要添加允許轉發數據包通過的規則:

iptables -t filter -A FORWARD -p udp -s client1 --sport port1 -d client2 --dport port2 -j ACCEPT
iptables -t filter -A FORWARD -p udp -s client2 --sport port2 -d client1 --dport port1 -j ACCEPT

地址在這裡也出現了半翻譯,因為數據包總是按以下順序穿過防火牆:PREROUTING, FORWARD, POSTROUTING.

現在,client1 將完全相信它正在與之交談server:ports(至少在網路級別上;當然數據包可能包含暗示誰在真正回答的內容)。client2 也是如此,他會確保它與server:ports.

還要記住,一旦對話開始,防火牆就會記住它的狀態;刪除或添加規則不會對已建立的連接產生任何直接影響,因為nat表始終僅由連接中的第一個數據包遍歷;翻譯結果儲存在狀態表中,用於翻譯回復和後續數據包。可以通過cat /proc/net/nf_conntrack或使用conntrack-tools包中的實用程序查看該狀態表。在 UDP 的情況下,“連接”由會話中的地址、埠和超時定義,並且在一段時間內(預設為 30 秒)在任何方向都沒有看到任何數據包時“結束”。

我還想清楚地說明這一點:iptables 永遠不會執行轉發或路由。無論是否存在任何 iptables 規則,都會根據路由策略數據庫規則和路由表內容執行路由和轉發。說“ iptables 的 ip 轉發”是完全不正確的,因為 iptables 只設置翻譯。它配置核心防火牆過濾規則以及網路地址和埠轉換規則,例如核心如何更改數據包中的地址,這顯然會影響其路由決策(因為路由決策是基於地址的)。

引用自:https://serverfault.com/questions/1114032