服务无法使用公共 IP 连接到自身,NAT 问题

服务无法使用公共 IP 连接到自身,NAT 问题

我有一台来自 serverloft.eu 的专用服务器,但由于某些网络安全问题,我无法在服务器上使用桥接网络。因此,我已将所有 IP 设置为主 eth0,并使用 NAT 将流量从主 eth0 转发到内部网络。但我遇到了一个问题,我的虚拟服务器上的服务无法使用公共 IP 连接到自身,即 telnet 192.168.122.3 80 工作正常,但 telnet pub.lic.ip.xx 80 超时。(当在 ip 为 192.168.122.3 的虚拟机上输入时)

我的 iptables 脚本如下所示:

#!bin/sh

iptables -F

iptables -t nat -F

iptables -P FORWARD ACCEPT
iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE

PORTS="22 25 110 143 587 993 995"
for port in $PORTS;
do
  iptables -t nat -A PREROUTING -p tcp -d xx.xx.xx.189 --dport $port -j DNAT --to 192.168.122.2:$port
done

PORTS="22 80 443"
for port in $PORTS;
do
  iptables -t nat -A PREROUTING -p tcp -d xx.xx.xx.173 --dport $port -j DNAT --to 192.168.122.3:$port
done

PORTS="22 3306 5432"
for port in $PORTS;
do
  iptables -t nat -A PREROUTING -p tcp -d xx.xx.xx.174 --dport $port -j DNAT --to 192.168.122.4:$port
  iptables -t nat -A PREROUTING -p udp -d xx.xx.xx.174 --dport $port -j DNAT --to 192.168.122.4:$port
done

我错过了什么?

答案1

使用伪装 NAT(无论是 iptables 中的 NAT 还是消费者路由器/防火墙中的简单 NAT),都不可能从内部网络到达外部 IP。在这种情况下,地址转换将最终产生一个具有相同源地址和目标地址的数据包,并且永远不会通过过滤器将其地址转换回原始内部 IP。

我知道如果您在一台机器内部使用虚拟网络,这并不是一个可行的解决方案,但我通常通过使用分割水平 DNS 来解决这个问题,其中 NATed(内部)IP 用于内部视图,外部 IP 用于外部视图。

答案2

经过大量的阅读和测试,我最终找到了一个解决方案,我将我的 iptables 脚本修改为:

#!/bin/sh

iptables -t nat -F
iptables -F
iptables -P FORWARD ACCEPT
iptables -P OUTPUT ACCEPT
iptables -P INPUT ACCEPT

iptables -t nat -A POSTROUTING -o eth0 -s 192.168.122.0/24 ! -d 192.168.122.0/24 -j MASQUERADE
iptables -A FORWARD -s 192.168.122.0/24 -j ACCEPT
iptables -A FORWARD -d 192.168.122.0/24 -j ACCEPT
iptables -A FORWARD -s ! 192.168.122.0/24 -j DROP

PORTS="22 25 110 143 587 993 995"
for port in $PORTS;
do
  iptables -t nat -A PREROUTING -p tcp -d xx.xx.xx.189 --dport $port -j DNAT --to 192.168.122.2:$port
done
iptables -t nat -A POSTROUTING -s 192.168.122.2 -j SNAT --to xx.xx.xx.189

PORTS="22 80 443"
for port in $PORTS;
do
  iptables -t nat -A PREROUTING -p tcp -d xx.xx.xx.173 --dport $port -j DNAT --to 192.168.122.3:$port
done
iptables -t nat -A POSTROUTING -s 192.168.122.3 -j SNAT --to xx.xx.xx.173

PORTS="22 3306 5432"
for port in $PORTS;
do
  iptables -t nat -A PREROUTING -p tcp -d xx.xx.xx.174 --dport $port -j DNAT --to 192.168.122.4:$port
  iptables -t nat -A PREROUTING -p udp -d xx.xx.xx.174 --dport $port -j DNAT --to 192.168.122.4:$port
done
iptables -t nat -A POSTROUTING -s 192.168.122.4 -j SNAT --to xx.xx.xx.174

我所做的是,从他们的内部 IP 添加-j SNAT到他们的外部 IP。

答案3

一个更好的解决方案是编写一条规则,将公共 IP 地址 ( x.x.x.x) 重写为 localhost:

iptables -t nat -A OUTPUT -d x.x.x.x/32 -p tcp -m tcp --dport 80 \
         -j DNAT --to-destination 127.0.0.1:80

相关内容