Iptables + NAT and port forward loop with one network interface

iptablesnat;networkingopenvpnvpn

I am setting an OpenVPN Access Server behind my NAT server in AWS. Currently, my NAT server has one network interface and I am trying to forward some ports to OpenVPN Access Server.

Port forwarding works and I can connect to my OpenVPN Access Server either via browser or OpenVPN Client (establish the VPN connection).

Now the problem is that OpenVPN Access Server is using ports 443 and 943 for HTTPS. But when I try to access HTTPS websites while connect to VPN, HTTPS certs get all invalidated as the HTTPS connection gets redirected back to the OpenVPN AS.

Here are my IPTABLES rules:

iptables -t nat -A POSTROUTING -o eth0 -s 172.16.0.0/24 -j MASQUERADE

iptables -A FORWARD -m state -p tcp -d 172.16.0.213 --dport 943 --state NEW,ESTABLISHED,RELATED -j ACCEPT
iptables -t nat -A PREROUTING -p tcp --dport 943 -j DNAT --to-destination 172.16.0.213:943
iptables -t nat -A POSTROUTING -p tcp -d 172.16.0.213 --dport 943 -j SNAT --to-source 172.16.0.213

iptables -A FORWARD -m state -p tcp -d 172.16.0.213 --dport 443 --state NEW,ESTABLISHED,RELATED -j ACCEPT
iptables -t nat -A PREROUTING -p tcp --dport 443 -j DNAT --to-destination 172.16.0.213:443
iptables -t nat -A POSTROUTING -p tcp -d 172.16.0.213 --dport 443 -j SNAT --to-source 172.16.0.213

iptables -t nat -A PREROUTING -p udp -i eth0 -d 172.16.0.213 --dport 1194 -j DNAT --to-destination 172.16.0.213:1194

The outpout of iptables -t nat -L:

Chain PREROUTING (policy ACCEPT)
target     prot opt source               destination
DNAT       tcp  --  anywhere             anywhere             tcp dpt:https to:172.16.0.213:443
DNAT       udp  --  anywhere             ip-172-16-0-213.eu-west-1.compute.internal  udp dpt:openvpn to:172.16.0.213:1194
DNAT       tcp  --  anywhere             anywhere             tcp dpt:943 to:172.16.0.213:943

Chain INPUT (policy ACCEPT)
target     prot opt source               destination

Chain OUTPUT (policy ACCEPT)
target     prot opt source               destination

Chain POSTROUTING (policy ACCEPT)
target     prot opt source               destination
SNAT       tcp  --  anywhere             ip-172-16-0-213.eu-west-1.compute.internal  tcp dpt:https to:172.16.0.213
SNAT       tcp  --  anywhere             ip-172-16-0-213.eu-west-1.compute.internal  tcp dpt:943 to:172.16.0.213
MASQUERADE  all  --  ip-172-16-0-0.eu-west-1.compute.internal/24  anywhere

Is it still possible to do this with one network interface and solve it with iptables?

Basically, I want to tell that "iptables, please do not do any port forwarding from inside to the outside", currently the port forwarding goes into "loop".

Thanks for any help and ideas!

Best Answer

You should reconsider whether any of the DNAT rules are required. You haven't provided a reason for it. Same with the SNAT rules, as they're forcing all of the connections to appear local for no clear reason.

If the DNATs are required, use connmark to mark and restore packets coming from the openvpn-as tun interface in the PREROUTING chain of the mangle table, and add a -m mark ! --mark <the mark you set> condition on your nat PREROUTING port 443 DNAT rule. This will prevent outgoing connections from being DNAT'd back to your device.


Edited based on your network:

Remove all SNAT rules. You can't audit connections on the openvpn-as server with this in place.

Make sure the openvpn-as server is routing connections back through your gateway. Either set the default route to the gateway (simple), or policy route (complex).

Change all of your DNAT rules to ignore your local source range, ie ! -s 172.16.0.0/24. If openvpn-as isn't also performing MASQUERADE or SNAT, you may need to add the VPN IP ranges as well as additional ! -s base/mask per range.