我觀察到,當在 conntrack 模組中建立連接時,netfilter 會更改來源連接埠。我需要阻止這種行為。
這是我為重現問題所做的操作:
- 我創建了一個 netfilter 規則,它將執行從連接埠 2002 到 2003 的 DNAT
sudo iptables -w -t nat -A OUTPUT -s 192.168.30.3 -d 192.168.30.1 -p udp --sport 2001 --dport 2002 -j DNAT --to-destination :2003
- 然後,我建立一個 conntrack 條目來模擬從 192.168.30.1:2001(我的電腦)到 192.168.30.1:2003 的連接
sudo /sbin/conntrack -I -s 192.168.30.1 -d 192.168.30.3 -p udp --sport 2003 --dport 2001 --timeout 100000
- 最終,我使用來源連接埠 2001 從我的電腦執行到 192.168.30.1:2002 的連線:
sudo nc -u -p 2001 192.168.30.1 2002
由於 netfilter DNAT 規則,我預計輸出資料包的目標連接埠為 2003,來源連接埠為 2001。我猜這是因為我的電腦認為連接埠 2001 上存在現有連接(由於 conntrack 條目),然後阻止來源連接埠為 2001(對嗎?)。但我不想要這種行為?如何強制使用連接埠號碼2001?
答案1
為了使 DNAT 發揮作用(從某種意義上說,為了使程式能夠識別回复),需要執行“反向 NAT”,將回復流量的來源連接埠從192.168.30.1
(to 192.168.30.3:2001
) 更改為2003
to 。2002
然而,當從 conntrack 的角度來看,來自該位址的流量不是 DNAT 的結果時(因為根據建立的 conntrack 條目,主機不是發起連接的主機),反向 NAT 將192.168.30.1:2003
不合適。192.168.30.3:2001
因此,netfilter「被迫」對符合 DNAT 規則的流量也執行 SNAT,以便它可以192.168.30.1:2003
透過目的地區分回覆流量(也來自 )192.168.30.3:$random
。
我假設 netfilter 要么在 SNAT 的反向 NAT(這是一個 DNAT)之前執行 DNAT 的反向 NAT(這是一個 SNAT),要么設法在 SNAT 的反向 NAT 之前使用目的地(即192.168.30.3:$random
)作為反向NAT 的匹配DNAT,否則強制SNAT就沒有意義了。 (然而,在非逆轉情況下,這兩種情況都不是真的,據我所知:DNAT 將在INPUT 中的SNAT 之前在PREROUTING 中執行,並且SNAT 規則中的目標匹配(如果有)將使用DNAT中產生的值)
問題是,上面的故事/你問題中的「問題」在現實中幾乎沒有任何意義。以雙主機wireguard VPN為例:假設您希望Endpoint=
在兩台主機上都進行設定(以便它們中的任何一個都可以發起通訊)並且不希望由於強制SNAT而意外“更新”值(假設實際上可能會被觸發),您應該做的只是一個“永遠在線”的SNAT,它“補充”DNAT / 相當於保留NAT:
iptables -t nat -A INPUT -s 192.168.30.1 -d 192.168.30.3 -p udp --sport 2003 --dport 2001 -j SNAT --to-source :2002
由於 DNAT 的自動反向 NAT,這在客戶端伺服器模型中通常是不必要的。
PS 你仍然不應該到達192.168.30.1:2003
,否則如果你在前者的 conntrack 條目被刪除之前192.168.30.1:2003
再次到達它,也會發生強制源 NAT 。 192.168.30.1:2002
INPUT 中的附加 SNAT 規則也不會給您帶來額外的麻煩。
答案2
您可以設定兩個通常會發生衝突的串流連線查找表(因此通常會觸發新流上的來源連接埠重寫以避免衝突)處於不同的位置連線區域。這個額外的區域屬性使得連線不與不同 conntrack 區域中的現有流匹配/衝突:不會發生來源埠重寫。
對於您的特定範例,這裡有一個特定規則,可以防止衝突,從而防止來源連接埠重寫:
iptables -t raw -A OUTPUT -s 192.168.30.3 -d 192.168.30.1 -p udp --sport 2001 --dport 2002 -j CT --zone-orig 1
通常根據用例,使用更合理的選擇器。它通常在 PREROUTING 鏈中使用,在路由時將傳入介面作為選擇器,並且通常與標記值關聯,因此路由也會受到影響。
使此選項出現的原始用例是連線在具有複雜路由設定的相同網路堆疊上(沒有額外的網路命名空間)(例如:使用相同IP 位址在4 個不同的專用LAN 之間進行路由。例如,在192.168.1.0/24 eth0 <-> eth1 10.1.0.0/24 之間,以及再次192.168.1.0/24 eth2 <-> 10.1.0.0/24 eth3) 可以看到具有相同位址/連接埠的兩個不相關的流。作為網路過濾器和連線對路由一無所知(連線查找表僅包含位址)必須教導他們透過手動新增與路由拓撲相關的區域屬性來單獨考慮這些流連線查找表。
(這是一個連結最初提出該功能時。