Linux

Linux:使來自同一主機的流量看起來來自不同的 IP 地址

  • January 24, 2022

我正在使用客戶端庫(https://github.com/Beckhoff/ADS)通過 TCP 從 Linux 機器連接到 PLC。但是,該庫只能在 PLC 的源 IP 和目標 IP 地址之間執行單一連接。我的目標是連接到具有多個客戶端的遠端 IP/PLC,即遠端 PLC 必須能夠根據客戶端的(不同)IP 地址區分客戶端連接。

我希望通過一些巧妙的iptables規則來實現這一點;或者,也許 Linux 網路命名空間也可以工作。

對於iptables路由(雙關語?),我的計劃是為 Linux 機器上的同一個 NIC 分配多個 IP 地址。由於遠端服務偵聽單個埠 (48898),因此我不能簡單地在iptables規則中使用不同的目標埠。因此,我在想這樣的事情:

遠端 PLC:192.168.1.10/24

Linux PC:192.168.1.20/24(ip addr add 192.168.1.20/24 dev enp2s0)

Linux PC:192.168.1.21/24(ip addr add 192.168.1.21/24 dev enp2s0)

  • Client-A 只是從 192.168.1.20 連接到 192.168.1.10
  • Client-A 簡單地從 192.168.1.21 連接到(虛擬)192.168.1.11

通過為遠端 PLC 使用“虛擬”IP 地址,我希望能夠區分 TCP 連接,因此我知道哪些數據包來自客戶端 A,哪些數據包來自客戶端 B。現在我需要做一些iptables魔術:

  1. 傳出:如果目標 IP 地址 == 192.168.1.11 1.1 -> 重寫為目標 IP 地址 192.168.1.10 1.1 -> 重寫/確保源 IP 地址為 192.168.1.21
  2. 傳入:如果目標 IP 地址 == 192.168.1.21 2.1 -> 將源 IP 地址重寫為 192.168.1.11(遠端 PLC 的虛擬 IP)

也許甚至可以“標記” TCP 連接,以便更容易區分哪個是哪個(步驟 2)。

對於這種情況,conntrack的 NAT 足以正確更改、標記和處理連接的回复流量。可以同時使用 DNAT 和 SNAT 並將它們的使用結合在一起,或者混合使用 DNAT 和適當的路由。

DNAT

此目標僅在 nat 表、PREROUTING **and OUTPUT**鍊和僅從這些鏈呼叫的使用者定義鏈中有效。它指定應該修改數據包的目標地址(並且此連接中的所有未來數據包也將被破壞),並且應該停止檢查規則。

$$ … $$

SNAT

此目標僅在 nat 表、andPOSTROUTINGINPUT和僅從這些鏈呼叫的使用者定義鏈中有效。它指定應該修改數據包的源地址(並且此連接中的所有未來數據包也將被破壞),並且應該停止檢查規則。

$$ … $$

iptables -t nat -A OUTPUT -d 192.168.1.11 -j DNAT --to-destination 192.168.1.10
iptables -t nat -A OUTPUT -d 192.168.1.12 -j DNAT --to-destination 192.168.1.10
iptables -t nat -A OUTPUT -d 192.168.1.13 -j DNAT --to-destination 192.168.1.10
iptables -t nat -A OUTPUT -d 192.168.1.14 -j DNAT --to-destination 192.168.1.10

在客戶端設置額外的源地址:

ip address add 192.168.1.21/24 dev enp2s0
ip address add 192.168.1.22/24 dev enp2s0
ip address add 192.168.1.23/24 dev enp2s0
ip address add 192.168.1.24/24 dev enp2s0
  • 並且要麼有條件地將 SNAT 操作綁定到初始目標地址(在 DNAT 完成之前),使用適當的過濾器和iptables匹配conntrack
iptables -t nat -A POSTROUTING -m conntrack --ctorigdst 192.168.1.11 -j SNAT --to-source 192.168.1.21
iptables -t nat -A POSTROUTING -m conntrack --ctorigdst 192.168.1.12 -j SNAT --to-source 192.168.1.22
iptables -t nat -A POSTROUTING -m conntrack --ctorigdst 192.168.1.13 -j SNAT --to-source 192.168.1.23
iptables -t nat -A POSTROUTING -m conntrack --ctorigdst 192.168.1.14 -j SNAT --to-source 192.168.1.24
  • 或者代替 SNAT,更簡潔,使用直接提示每個目的地的預期源地址的路由(即使 nat/OUTPUT 重新路由,源地址一旦設置就不會再改變)。這將允許客戶和客戶ss -tn dport == 48898知道並顯示正確的源地址。這變成:
ip route add 192.168.1.11/32 dev enp2s0 src 192.168.1.21
ip route add 192.168.1.12/32 dev enp2s0 src 192.168.1.22
ip route add 192.168.1.13/32 dev enp2s0 src 192.168.1.23
ip route add 192.168.1.14/32 dev enp2s0 src 192.168.1.24

這必須像這樣完成:一次一個地址(DNAT 可以被簡化/分解,但不是處理源的第二部分)。

與實際192.168.1.10地址的連接保持不變。

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