Iptables – Bridged networking on VM host and hairpin NAT

iptablesnat;networkingvirtual-machines

I have one host running Proxmox VE.

I set up 3 virtual bridges vmbr[0-2] to handle my networking needs: vmbr0 runs directly on the main interface for VMs with public IPs, vmbr1 allows for NATed VMs, and vmbr2 is a host-only network.
Let's say my main public IP is 12.34.56.78.

For the NAT to work, I set up the following iptables ruleset:

-A PREROUTING -d 12.34.56.78 -i vmbr0 -p tcp -m multiport --dports 80,443 -j DNAT --to-destination 192.168.1.101
# and other rules like this one for different ports to different local IPs

-A POSTROUTING -s 192.168.10.0/24 -o vmbr0 -j SNAT --to-source 12.34.56.78

Now let's say I have a VM on vmbr1 with IP 192.168.1.102.

This machine cannot access the webserver at 192.168.1.101 using the public IP 12.34.56.78.

I initially thought that the POSTROUTING directive above was enough for hairpin NAT to work.

Having read the canonical Loopback to forwarded Public IP address from local network – Hairpin NAT and multiple other answers on the same variant, I tried :

  • setting -P [INPUT|FORWARD|OUTPUT] ACCEPT temporarily on the host to check if it could be caused by some filtering rules

  • adding -A POSTROUTING -d 192.168.1.101 -p tcp --dport 80 -j MASQUERADE to the ruleset, trying it both before and after the current POSTROUTING rule

but still, it does not work.

Ideas?

Thanks.

Best Answer

To do the hairpin NAT method you will need to enter the commands below.

iptables -t nat -A PREROUTING -d 12.34.56.78 -i vmbr1 -p tcp -m multiport --dports 80,443 -j DNAT \
    --to-destination 192.168.1.101   
iptables -t nat -A POSTROUTING -s 192.168.10.0/24 -o vmbr1 -d 192.168.1.254 -p tcp \
    --dport 80 -j SNAT --to-source 192.168.1.101