具有多個 NIC 和公共 IP 地址的 iptables 源 NAT 不起作用
我只是在多個 NIC 和 IP 地址伺服器上遇到問題。我已經為我的 Cent OS 7 伺服器配置了一個屬於 eth1 的額外公共 IP 地址。啟用 iptables 源 NAT 後,只有額外的 IP 地址無法使用。
在這篇文章中,兩個公共 IP 地址分別用 99.0.1.100 (eth0) 和 99.0.2.100 (eth1) 表示。99.0.2.100 的子網遮罩為 255.255.254.0,預設網關設置正確(99.0.1.1 為 99.0.1.100,99.0.2.1 為 99.0.2.100)。
以下是
/etc/sysconfig/network-scripts/ifcfg-eth1
. (HWADDR 被審查)DEVICE=eth1 TYPE=Ethernet HWADDR=**:**:**:**:**:** ONBOOT=yes NM_CONTROLLED=no BOOTPROTO=static IPADDR=99.0.2.100 NETMASK=255.255.254.0
下面是 的輸出
ip route
。default via 99.0.1.1 dev eth0 proto static metric 100 99.0.1.0/23 dev eth0 proto kernel scope link src 99.0.1.100 metric 100 99.0.2.0/23 dev eth1 proto kernel scope link src 99.0.2.100
下面是 的輸出
ip rule
。0: from all lookup local 32765: from 99.0.2.100 lookup subroute-eth1 32766: from all lookup main 32767: from all lookup default
以下是
/etc/sysconfig/network-scripts/route-eth1
.default via 99.0.2.1 table subroute-eth1
以下是
/etc/sysconfig/network-scripts/rule-eth1
.from 99.0.2.100 table subroute-eth1
然後,以下請求已正確發送,並以字元串形式響應每個公共 IP 地址的正確 IP 地址。
# curl --interface eth0 api.ipify.org # outputs 99.0.1.100 # curl --interface eth1 api.ipify.org # outputs 99.0.2.100
在這裡,我希望系統的每個使用者使用不同的公共 IP 地址。因此應用了以下 iptables 源 NAT。其中 uid=1000 為 A,uid=1001 分別為 B。
# iptables -t nat -m owner --uid-owner 1000 -A POSTROUTING -j SNAT --to-source 99.0.1.100 # iptables -t nat -m owner --uid-owner 1001 -A POSTROUTING -j SNAT --to-source 99.0.2.100
在這種情況下,eth0 工作正常,但 eth1 已超時。
# curl api.ipify.org # outputs 99.0.1.100 # sudo -u A curl api.ipify.org # outputs 99.0.1.100 # sudo -u B curl api.ipify.org # **time out**
由於缺乏網路經驗,我不知道出了什麼問題。如果有人有想法,請幫助我。請注意,在這種情況下,
ssh root@99.0.2.100
從 Internet 仍然可以正常工作。編輯:下面是輸出
ip route show table subroute-eth1
default via 99.0.2.1 dev eth1
uid 應該觸發路由更改以使用
eth1
而不是eth0
.nat/POSTROUTING
的 SNAT(雖然仍然需要)為此來得太晚了,因為正如 POSTROUTING 的名稱所暗示的那樣,它發生在路由決策之後:網路介面被選擇並且不會再改變。對於本地流量,規則必須在
mangle/OUTPUT
鏈中發生以更改路由,通過使用可以觸發ip rule
查找的標記:# iptables -t mangle -A OUTPUT -m owner --uid-owner 1000 -j MARK --set-mark 1000 # iptables -t mangle -A OUTPUT -m owner --uid-owner 1001 -j MARK --set-mark 1001
然後通過 重用資訊
ip rule
。甚至必須考慮 1000(處理uid1000$ curl --interface eth1 http://api.ipify.org/
不應使用條目 32765 的特定情況):ip rule add fwmark 1000 lookup main ip rule add fwmark 1001 lookup subroute-eth1
請注意,之前選擇了初始預設 IP:仍然需要 SNAT 將其修復為新的正確 IP。既然已經有規則了,為什麼要使用這個標記
from 99.0.2.100 lookup subroute-eth1
呢?同樣,這是因為網路堆棧中各種評估的順序,正如Netfilter 和通用網路示意圖中的此數據包流所總結的那樣:只有更改mangle/OUTPUT
才能觸發示意圖中看到的重新路由檢查,而此時 IP 還沒有已更正為 99.0.2.100。在反向路徑中,一些網元無論如何都不會及時知道這些路由表,必須在 rp_filter 上設置鬆散模式,
eth1
否則返回的數據包將被丟棄:# echo 2 > /proc/sys/net/ipv4/conf/eth1/rp_filter
eth0
處理上述 uid 1000 的特定情況相同(uid1000$ curl --interface eth1 http://api.ipify.org/
):# echo 2 > /proc/sys/net/ipv4/conf/eth0/rp_filter
有了這個,它應該主要工作。但實際上,一些數據包不屬於 uid 1001:
TCP RST
,最後ACK
一次是程序結束,或者對於 UDP,相關的 ICMP 錯誤……只屬於核心。它們與 uid 1001 不匹配,將在錯誤的介面上發送(在這個錯誤的介面上使用錯誤的 IP),這將在連接結束時產生一些超時,更可能是在遠端端而不是本地端。這可以通過kill -KILL
在客戶端上執行與使用者 1001 建立的更改連接來查看eth1
,並見證幾個重試ACK
數據包,其中源 99.0.2.100 發送通過eth0
(而不是eth1
)確認FIN
從遠端接收多次eth1
。因此,所有這些都必須重新設計,
CONNMARK
以跟踪使用者發起的流,而不是使用者發起的數據包(這裡有一些解釋)。nat
不必更改,因為只有第一個處於NEW
狀態的數據包無論如何都會通過 iptables 規則,並且它已經在跟踪流。讓我們重新開始:# iptables -t mangle -F # iptables -t mangle -A PREROUTING -j CONNMARK --restore-mark # iptables -t mangle -A OUTPUT -j CONNMARK --restore-mark # iptables -t mangle -A OUTPUT -m owner --uid-owner 1000 -j MARK --set-mark 1000 # iptables -t mangle -A OUTPUT -m owner --uid-owner 1001 -j MARK --set-mark 1001 # iptables -t mangle -A OUTPUT -j CONNMARK --save-mark
現在一切都應該正常執行。
最後說明:雖然您的設置中不需要它,但 eth1 的連結本地路由應該在 table 上複製
subroute-eth1
,否則eth1
從 uid 1001 訪問的 LAN 會產生奇怪的結果,因為規則 32765 在規則 32766 之前讀取,所以贏了’永遠不是定義的連結本地路由,因為此命令的結果顯示:# ip route get 99.0.2.55 mark 1001 99.0.2.55 via 99.0.2.1 dev eth1 table subroute-eth1 src 99.0.2.100 mark 0x3e9 uid 0 \ cache
它可能會阻止對除網關之外的所有 LAN 的訪問。
您應該添加(或根據需要放入系統配置文件中):
ip route add table subroute-eth1 99.0.2.0/23 dev eth1 scope link src 99.0.2.100
然後前面的
ip route get
命令將給出正確的:99.0.2.55 dev eth1 table subroute-eth1 src 99.0.2.100 mark 0x3e9 uid 0 \ cache