Networking

具有多個 NIC 和公共 IP 地址的 iptables 源 NAT 不起作用

  • August 16, 2018

我只是在多個 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 

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