將介面的公共 IP “給予”給具有本地 IP 的另一台主機
我有一台機器(執行 openSUSE Leap 15.3),它有多個公共 IP 地址,用作一些額外主機的網關。我需要讓網關上的一個公共 IP 就像它屬於連接到它的一台機器一樣(流量被透明地轉發)。
我
iptables-save
目前的輸出如下(包括一些不相關的 Docker 規則,但敏感部分已編輯):# Generated by iptables-save v1.8.7 *filter :INPUT ACCEPT [9747976:4527721149] :FORWARD ACCEPT [12638879:4423560060] :OUTPUT ACCEPT [8913992:2531503118] :DOCKER - [0:0] :DOCKER-ISOLATION-STAGE-1 - [0:0] :DOCKER-ISOLATION-STAGE-2 - [0:0] :DOCKER-USER - [0:0] -A FORWARD -j DOCKER-USER -A FORWARD -j DOCKER-ISOLATION-STAGE-1 -A FORWARD -o docker0 -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT -A FORWARD -o docker0 -j DOCKER -A FORWARD -i docker0 ! -o docker0 -j ACCEPT -A FORWARD -i docker0 -o docker0 -j ACCEPT -A DOCKER-ISOLATION-STAGE-1 -i docker0 ! -o docker0 -j DOCKER-ISOLATION-STAGE-2 -A DOCKER-ISOLATION-STAGE-1 -j RETURN -A DOCKER-ISOLATION-STAGE-2 -o docker0 -j DROP -A DOCKER-ISOLATION-STAGE-2 -j RETURN -A DOCKER-USER -j RETURN COMMIT # Completed # Generated by iptables-save v1.8.7 *nat :PREROUTING ACCEPT [480085:188100350] :INPUT ACCEPT [62951:4107383] :OUTPUT ACCEPT [150:9857] :POSTROUTING ACCEPT [0:0] :DOCKER - [0:0] -A PREROUTING -d <REDACTED_FORWARDING_IP>/32 -i eth0 -j DNAT --to-destination 10.125.0.2 -A PREROUTING -m addrtype --dst-type LOCAL -j DOCKER -A OUTPUT ! -d 127.0.0.0/8 -m addrtype --dst-type LOCAL -j DOCKER -A POSTROUTING -s 172.17.0.0/16 ! -o docker0 -j MASQUERADE -A POSTROUTING -j MASQUERADE -A DOCKER -i docker0 -j RETURN COMMIT # Completed
據我所知,唯一相關的部分是:
-A PREROUTING -d <REDACTED_FORWARDING_IP>/32 -i eth0 -j DNAT --to-destination 10.125.0.2 -A POSTROUTING -j MASQUERADE
這仍然存在許多問題:
- 當內部機器啟動出站連接時,它的 IP 被 NAT 為網關的主地址,而不是我試圖給它的地址。
- 接收連接時,它們似乎來自網關的本地 IP,而不是原始 IP(應該有解決方法,因為這是預設網關)。
- 如果服務
0.0.0.0
在網關上偵聽,則該埠上的連接不會被重定向,它們會轉到該服務。我試圖將其他一些問題的答案拼接在一起,例如:
- https://superuser.com/q/1130250
- https://superuser.com/q/1513820
- iptables 將所有流量轉發到指定埠,到另一台設備
- 使用 iptables 將來自輔助公共 IP 的所有傳入流量重定向到內部 IP 地址
- 使用 iptables 將來自輔助公共 IP 的所有傳入流量重定向到內部 IP 地址
- https://superuser.com/q/681705
- https://unix.stackexchange.com/q/395008/381510
但是由於我缺乏重要的 iptables 經驗,我無法解決我的問題,或者解決了一些只是為了讓其他人彈出。
任何人都可以提出一些規則來達到這種效果嗎?或者也許有一種方法可以在沒有 iptables 的情況下做到這一點?
當內部機器啟動出站連接時,它的 IP 被 NAT 為網關的主地址,而不是我試圖給它的地址。
這應該通過以下方式解決:
iptables -t nat -I POSTROUTING 1 -s 10.125.0.2 -o eth0 -j SNAT --to-source <FORWARD_IP>
它被添加到前面,因此它會首先觸發,檢測數據包來自該系統並將其轉換為指定的 IP,而不是從介面中選擇地址。
接收連接時,它們似乎來自網關的本地 IP,而不是原始 IP(應該有解決方法,因為這是預設網關)。
此問題與以下 SNAT 規則有關:
iptables -t nat -A POSTROUTING -j MASQUERADE
它太寬了*。您正在對每個方向的**所有內容*進行 SNAT ,這既不高效也不安全。它匹配所有內容,包括您的 DNATed 數據包。它們首先被目標轉換為私有地址,然後它們的源被此規則轉換為從分配了 10.xxx 地址的私有介面中挑選的地址。
我懷疑您正試圖用一條規則覆蓋所有公共介面和所有專用網路。雖然 Linux(IP 集)中有地址列表,但沒有介面列表,因此僅使用一條規則無法正確執行此操作。
至少使用源地址過濾它(例如要源翻譯哪些地址):
iptables -t nat -A POSTROUTING -s 10.125.0.0/24 -j MASQUERADE
如果您有多個專用網路,請添加更多此類規則。
我認為最好為每個公共介面創建一個單獨的規則,這樣通過私有介面發出的數據包永遠不會得到原始碼轉換,無論它們擁有什麼源地址,例如
iptables -t nat -A POSTROUTING -s 10.125.0.0/24 -o eth0 -j MASQUERADE
等等。這樣從 10.xxx 到 172.xxx 的數據包也不會被轉換,並且您在兩個網路中的服務將直接看到彼此的 IP,仍然可以在 FORWARD 過濾器鏈中選擇性地過濾它們。如果服務正在網關上的 0.0.0.0 上偵聽,則該埠上的連接不會被重定向,它們會轉到該服務。
最後,我不完全理解這一點。我在評論裡問,你沒有回答。哪些連接,來自哪裡,源 IP 是什麼?
DNAT 處理髮生在路由決策之前,這就是為什麼鏈被稱為“PREROUTING”的原因。它從不檢查是否有某個本地程序在該埠上偵聽。本地服務有機會回答的唯一方法是讓數據包通過 INPUT 鏈。為此,路由程式碼必須決定它是發往本地機器的,因此它必須是乙太不翻譯或翻譯成該系統分配的某個地址。
根據目前規則,從私有網路發送到公共 IP 的數據包不應被轉換,因為它們不是通過
eth0
. 因此,他們將由當地服務機構提供服務。但這並不取決於本地服務是否正在執行;如果不是,您將收到“連接被拒絕”。如果您需要從 LAN 到 <FORWARD_IP> 的數據包按照相同的 DNAT 規則進行轉換,請丟棄該
-i eth0
匹配項:iptables -A PREROUTING -d <REDACTED_FORWARDING_IP>/32 -j DNAT --to-destination 10.125.0.2
但是,我反對如此廣泛的規則。在我看來,DNAT 規則最好盡可能嚴格,因此您最好通過 protos (tcp/udp) 和您在 10.125.0.2 上執行的服務的埠進行過濾。如果那是一個 web 伺服器,只轉發 tcp/80 和 tcp/443,像這樣:
iptables -A PREROUTING -d <REDACTED_FORWARDING_IP>/32 -p tcp -m multiport --dports 80,443 -j DNAT --to-destination 10.125.0.2
.有什麼問題?說,您正在使用 ping 檢查某些內容。此 ping 結果將取決於此內部系統狀態,它是您實際 ping 的系統。這令人困惑。這不是大多數係統管理員在 ping 路由器時期望看到的行為。所以最好讓 ping 由主機回答。