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

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

我正在使用客户端库(https://github.com/Beckhoff/ADS) 通过 TCP 从 Linux 机器连接到 PLC。但是,该库只能在源 IP 和 PLC 的目标 IP 地址之间执行单个连接。我的目标是使用多个客户端连接到远程 IP/PLC,即远程 PLC 必须能够根据客户端的(不同)IP 地址区分客户端连接。

我希望通过一些巧妙的iptables规则来实现这一点;或者,Linux 网络命名空间也许也可以发挥作用。

对于iptables路由(双关语?),我的计划是将多个 IP 地址分配给 Linux 机器上的同一 NIC。由于远程服务侦听单个端口(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)

  • 客户端 A 只需从 192.168.1.20 连接到 192.168.1.10
  • 客户端 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)。

答案1

对于这种情况,连接跟踪的 NAT 足以正确更改、标记和处理连接的回复流量。可以同时使用 DNAT 和 SNAT 并将它们绑定在一起使用,或者混合使用 DNAT 和适当的路由。

DNAT

此目标仅在 nat 表中有效,在PREROUTING OUTPUT链,以及仅从这些链中调用的用户定义链。它指定应该修改数据包的目标地址(并且此连接中的所有未来数据包也将被破坏),并且应该停止审查规则。[...]

SNAT

此目标仅在 nat 表中有效,在里面POSTROUTINGINPUT链,以及仅从这些链中调用的用户定义链。它指定数据包的源地址应该被修改(并且此连接中的所有未来数据包也将被破坏),并且应该停止审查规则。[...]

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完成之前),使用适当的过滤器iptablesconntrack匹配:

    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保持不变。

相关内容