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 -j MASQUERADE

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

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

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

The outpout of iptables -t nat -L:

target     prot opt source               destination
DNAT       tcp  --  anywhere             anywhere             tcp dpt:https to:
DNAT       udp  --  anywhere             ip-172-16-0-213.eu-west-1.compute.internal  udp dpt:openvpn to:
DNAT       tcp  --  anywhere             anywhere             tcp dpt:943 to:

Chain INPUT (policy ACCEPT)
target     prot opt source               destination

Chain OUTPUT (policy ACCEPT)
target     prot opt source               destination

target     prot opt source               destination
SNAT       tcp  --  anywhere             ip-172-16-0-213.eu-west-1.compute.internal  tcp dpt:https to:
SNAT       tcp  --  anywhere             ip-172-16-0-213.eu-west-1.compute.internal  tcp dpt:943 to:
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!

  • You need to organize your question in a better way. Show all your iptables rules in a consistent order. Describe your setup and the interfaces you have on your server, etc. – Khaled Mar 30 '17 at 9:54
  • These are all my rules. I am using debian, which has one network interface. And using iptables, as you can see. – Sigmar Muuga Mar 30 '17 at 9:59
  • Is it mandatory for you to have the VPN listening to port 443? – Tero Kilkanen Mar 30 '17 at 12:27
  • I was thinking about using alternative ports as well but I'd rather have a solution that works with standard ports, as users are otherwise going to be needing some extra assistance. – Sigmar Muuga Mar 30 '17 at 14:44

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 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.

  • my openvpn-as is running on a separate machine though. – Sigmar Muuga Mar 30 '17 at 11:32
  • Clarify your network layout in your question. Preferably with a diagram. – Andrew Domaszek Mar 30 '17 at 11:38
  • I hope it clarifies... ibb.co/dVK5MF – Sigmar Muuga Mar 30 '17 at 11:51
iptables -t nat -I PREROUTING  -i eth1 -p tcp --dport 443 -j DNAT --to
iptables -t nat -I POSTROUTING -o eth1 -p tcp -d --dport 943 -j MASQUERADE

Substitute 443 with the public port to listen to, with your other server and 943 with the other server's listening port. Replace eth1 with your interface. Be aware that some configs have virtual interfaces, so something like vlan1 or ppp0 could be required.

The first line is the basic rule forwarding the packets. But since the packets would have the source address intact, it would result in asymmetric routing which would break with this stateful netfilter. Hence comes the second line - replace the source address of the packet with one of this server. This gives the connection a little detour forcing it to go twice through this server, but it does get rid of the asymmetry allowing this to work.

This solution relies on the ports used to tell which connections from the first rule are used by the second one. This will be fine with your simple setup, but for anyone trying to implement this in a router also having users behind it trying to access the same resource, it's worth noting that the MARK feature of netfilter should be used to tell the second MASQUERADE line which packets it should handle instead of just the port. Having MASQUERADE applied to everything could introduce unwanted behavior.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.