This guide will help you use UFW (uncomplicated firewall) to block all traffic other than traffic coming via CloudFlare.

Why do this?

Why not? CloudFlare will protect your site from attacks, when routed through your hostname. It will not protect you from direct attacks. By closing ports down to everyone but CloudFlare, you will hopefully protect yourself further.

How can I do this?

First, you’ll need to be running Debian or Ubuntu. Cheeky plug: if you fancy a new VPS, I’d recommend (and use) DigitalOcean, as their speeds are above all others, and prices below. For $10 free credit (2 months on the cheapest tier), sign up using this link (I get $25 when you have spent $25).

Cheeky plug over.

Now, if UFW isn’t installed (it should be), install it. Obviously.

sudo apt-get install ufw

There’s no harm in running that anyway to check you’re running the latest version.

Now run this:

sudo ufw status

It likely returns Inactive. If it doesn’t, you’ll likely know what you’re doing.

If you don’t know what you’re doing, and it looks like this:

Status: active

To                         Action      From
--                         ------      ----
22                         ALLOW       Anywhere

Don’t panic! This means your UFW is set up and running. Make a note of the ports on the left. They may include 22, or your SSH port, and ports for FTP and other thingamabobs you are running.

Don’t note down ports 80 or 443 - these are the web ports, and we are going to fiddle with these ones.

First things first, disable the UFW and reset it, if it’s already got rules for ports 80 and 443:

sudo ufw disable
sudo ufw reset

The Massively Important Bit

Now before anything else, make sure you won’t lock yourself out like a numpty by opening up your SSH port:

sudo ufw allow ssh

If your SSH is not running on the default port 22 (if you don’t know, then it probably is running on 22), then run:

sudo ufw allow 1234/tcp

Replace 1234 with the SSH port number. Bad things will happen if you get that wrong.

Coolio! What next?

Now is the time to allow any other thingamabobs that run on your server, like FTP:

sudo ufw allow ftp

But not the web ports - we’re getting to that.

The Web Port Bit

Now is the time to whitelist CloudFlare.

CloudFlare publishes the IP addresses of its servers online. The following guide includes all of them as of August 1st, 2016. If CloudFlare’s IPs have changed, then do the same stuff, but using their new IPs. Oh, and tell me on Twitter, so I can update everything.

The basic principle is this:

sudo ufw allow from <ip address> to any port <port>

This allows all connections from <ip address>, to anything on port <port>.

Without further ado, copy and paste the following into your terminal:

sudo ufw allow from 103.21.244.0/22 to any port http
sudo ufw allow from 103.22.200.0/22 to any port http
sudo ufw allow from 103.31.4.0/22 to any port http
sudo ufw allow from 104.16.0.0/12 to any port http
sudo ufw allow from 108.162.192.0/18 to any port http
sudo ufw allow from 131.0.72.0/22 to any port http
sudo ufw allow from 141.101.64.0/18 to any port http
sudo ufw allow from 162.158.0.0/15 to any port http
sudo ufw allow from 172.64.0.0/13 to any port http
sudo ufw allow from 173.245.48.0/20 to any port http
sudo ufw allow from 188.114.96.0/20 to any port http
sudo ufw allow from 190.93.240.0/20 to any port http
sudo ufw allow from 197.234.240.0/22 to any port http
sudo ufw allow from 198.41.128.0/17 to any port http
sudo ufw allow from 199.27.128.0/21 to any port http

If you also use IPv6 (if you don’t know, there’s no harm in doing it anyway), also copy the following:

sudo ufw allow from 2400:cb00::/32 to any port http
sudo ufw allow from 2405:8100::/32 to any port http
sudo ufw allow from 2405:b500::/32 to any port http
sudo ufw allow from 2606:4700::/32 to any port http
sudo ufw allow from 2803:f800::/32 to any port http

If you use HTTPS, also do the following (also no harm in just adding this anyway):

sudo ufw allow from 103.21.244.0/22 to any port https
sudo ufw allow from 103.22.200.0/22 to any port https
sudo ufw allow from 103.31.4.0/22 to any port https
sudo ufw allow from 104.16.0.0/12 to any port https
sudo ufw allow from 108.162.192.0/18 to any port https
sudo ufw allow from 131.0.72.0/22 to any port https
sudo ufw allow from 141.101.64.0/18 to any port https
sudo ufw allow from 162.158.0.0/15 to any port https
sudo ufw allow from 172.64.0.0/13 to any port https
sudo ufw allow from 173.245.48.0/20 to any port https
sudo ufw allow from 188.114.96.0/20 to any port https
sudo ufw allow from 190.93.240.0/20 to any port https
sudo ufw allow from 197.234.240.0/22 to any port https
sudo ufw allow from 198.41.128.0/17 to any port https
sudo ufw allow from 199.27.128.0/21 to any port https

And for HTTPS and IPv6 (also no harm…):

sudo ufw allow from 2400:cb00::/32 to any port https
sudo ufw allow from 2405:8100::/32 to any port https
sudo ufw allow from 2405:b500::/32 to any port https
sudo ufw allow from 2606:4700::/32 to any port https
sudo ufw allow from 2803:f800::/32 to any port https

And before you ask, rather than typing everything out a million times, I used the multi-cursor package for Atom.

The Enabling Bit

Before you do anything else, think back - did you allow SSH? If you can’t remember, scroll up and do it again. If you did remember, you will be greeted with:

Skipping adding existing rule
Skipping adding existing rule (v6)

Phew! You aren’t a numpty. If you were a numpty, thank me for reminding you, you numpty. Bad things will happen if you forgot to do this.

Now, when you’re sure you aren’t a numpty, run the following to enable UFW:

sudo ufw enable

Type y, if you’re absolutely sure you aren’t a numpty.

If the SSH then suddenly drops, you’re a numpty.

If it doesn’t, huzzah! You have a running UFW!

Run this to check everything’s hunky dory:

	sudo ufw status

Which should look like this:

To                         Action      From
--                         ------      ----
22                         ALLOW       Anywhere
80                         ALLOW       103.21.244.0/22
80                         ALLOW       103.22.200.0/22
80                         ALLOW       103.31.4.0/22
80                         ALLOW       104.16.0.0/12
80                         ALLOW       108.162.192.0/18
80                         ALLOW       131.0.72.0/22
80                         ALLOW       141.101.64.0/18
80                         ALLOW       162.158.0.0/15
80                         ALLOW       172.64.0.0/13
80                         ALLOW       173.245.48.0/20
80                         ALLOW       188.114.96.0/20
80                         ALLOW       190.93.240.0/20
80                         ALLOW       197.234.240.0/22
80                         ALLOW       198.41.128.0/17
80                         ALLOW       199.27.128.0/21
443                        ALLOW       103.21.244.0/22
443                        ALLOW       103.22.200.0/22
443                        ALLOW       103.31.4.0/22
443                        ALLOW       104.16.0.0/12
443                        ALLOW       108.162.192.0/18
443                        ALLOW       131.0.72.0/22
443                        ALLOW       141.101.64.0/18
443                        ALLOW       162.158.0.0/15
443                        ALLOW       172.64.0.0/13
443                        ALLOW       173.245.48.0/20
443                        ALLOW       188.114.96.0/20
443                        ALLOW       190.93.240.0/20
443                        ALLOW       197.234.240.0/22
443                        ALLOW       198.41.128.0/17
443                        ALLOW       199.27.128.0/21
22 (v6)                    ALLOW       Anywhere (v6)
80                         ALLOW       2400:cb00::/32
80                         ALLOW       2405:8100::/32
80                         ALLOW       2405:b500::/32
80                         ALLOW       2606:4700::/32
80                         ALLOW       2803:f800::/32
443                        ALLOW       2400:cb00::/32
443                        ALLOW       2405:8100::/32
443                        ALLOW       2405:b500::/32
443                        ALLOW       2606:4700::/32
443                        ALLOW       2803:f800::/32

i.e. very long, and has ALLOW written next to every port you need.

The Celebratory Bit

Nice work! Now, nobody can access your website(s) without going through CloudFlare. Equally, nobody can access your server through ports which don’t have ALLOW written next to them.

Oh, quick pointer, make sure your site’s DNS looks like this, with the cloud thingamabob all orangey. If it isn’t all orangey, click on it to enable CloudFlare’s proxy. Probably should have said that first…

CloudFlare DNS Example with Orange Cloud

The Checking Bit

If you have no trust in me/yourself, you can check to make sure your setup by seeing if the port is open at ping.eu. First bash your hostname/domain name in, and port 80 or 443. It should say the port is open. If it doesn’t, check you’ve enabled CloudFlare’s proxy (the cloud’s all orangey) on your DNS doodah (scroll up ~200px).

Port check of domain example

And then run it again with your server’s IP instead of the domain. It should say the port is closed. If it doesn’t, you’ve messed up somewhere. Whoops! (Tweet to me at @AJSalkeld for help).

Port check of ip example

The Last Bit

Pat yourself on the back, you’re done.

Oh, and if you fancy a DigitalOcean server