Service can't connect to self using public IP, NAT problem

With masquerade NAT (whether NAT in iptables or simple NAT in a consumer router/firewall) it's impossible to reach the external IP from the internal network. In this case, the address translation would end up with a packet with the same source and destination address, and would never make it back through the filter to have its' address translated back to the original inside IP.

I know it's not really a viable solution if you're using virtual networking internal to one machine, but I've generally gotten around this by using split-horizon DNS with NATed (internal) IPs for the inside view and the external IP for the outside view.


After a lot of reading and testing, I final found a solution, I have modified my iptables script to this:

#!/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

What I have done is that I have added a -j SNAT from their internal ip to their external ip.