I’ve previously written about using OpenVPN to escape Xplornet’s double NAT. Every now and then I’ll set up a new server (following the steps there) and inevitably run into some firewall configuration problem. I’ve really never taken the time to understand how to use iptables. I understand that they’re theoretically simple, but amazingly I always have a hard time with them. To that end, I’ve used ufw to try and help.
The number one piece of advice for securing anything connected to the internet is to reduce the attack surface. Great:
sudo ufw default deny incoming sudo ufw allow ssh
and now nothing works. Attack surface minimized!
Before going to far, I use the nuclear option for new or new-ish servers to ensure I know what I’m dealing with (NOTE: this leaves your server WIDE open, don’t stop here!):
// Reset ufw and disable sudo ufw reset // Flush all iptables rules sudo iptables -F sudo iptables -X sudo iptables -t nat -F sudo iptables -t nat -X sudo iptables -t mangle -F sudo iptables -t mangle -X sudo iptables -P INPUT ACCEPT sudo iptables -P FORWARD ACCEPT sudo iptables -P OUTPUT ACCEPT
This leaves me with:
$ sudo iptables -L Chain INPUT (policy ACCEPT) target prot opt source destination Chain FORWARD (policy ACCEPT) target prot opt source destination Chain OUTPUT (policy ACCEPT) target prot opt source destination $ sudo ufw status verbose Status: inactive
Awesome. Clean slate! Starting from the beginning again:
$ sudo ufw default deny incoming Default incoming policy changed to 'deny' (be sure to update your rules accordingly) $ sudo ufw allow ssh Rules updated $ sudo ufw enable Command may disrupt existing ssh connections. Proceed with operation (y|n)? y Firewall is active and enabled on system startup $ sudo ufw status verbose Status: active Logging: on (low) Default: deny (incoming), allow (outgoing), allow (routed) New profiles: skip To Action From -- ------ ---- 22/tcp ALLOW IN Anywhere
For the whole OpenVPN set up to work, the VPN client needs to actually be able to connect to the server. We’ll need to allow traffic on 1194 (or whatever port you’ve configured OpenVPN to use).
$ sudo ufw allow 1194 Rule added
You’ll also need to allow traffic to whatever port it is you’re forwarding. For example, if I want port 3000 to be what I’m exposing to the public:
$ sudo ufw allow 3000 Rule added
Leaving us with:
$ sudo ufw status verbose Status: active Logging: on (low) Default: deny (incoming), allow (outgoing), allow (routed) New profiles: skip To Action From -- ------ ---- 22/tcp ALLOW IN Anywhere 1194 ALLOW IN Anywhere 3000 ALLOW IN Anywhere
That’s about it for the more intuitive parts. The server is relatively locked down, although if you are using a fixed VPN client it may be worthwhile to white-list that single address. To allow the forwarding that the OpenVPN set up relies on, we’ll need to change the ufw default forward policy. Edit
/etc/default/ufw and change the value of
$ sudo nano /etc/default/ufw ... # Set the default output policy to ACCEPT, DROP, or REJECT. Please note that if # you change this you will most likely want to adjust your rules. DEFAULT_OUTPUT_POLICY="ACCEPT"
Then disable and re-enable ufw to update it:
$ sudo ufw disable && sudo ufw enable
Finally, adding the iptables rules used in the previous post (I’m sure there’s a way to do this with ufw, I just don’t know it):
$ sudo iptables -t nat -A PREROUTING -d 18.104.22.168 -p tcp --dport 3000 -j DNAT --to-dest 10.8.0.2:3000 $ sudo iptables -t nat -A POSTROUTING -d 10.8.0.2 -p tcp --dport 3000 -j SNAT --to-source 10.8.0.1
Et voilà! A relatively locked down server that plays nicely with OpenVPN and forwarding traffic.