How To Use UFW to whitelist CloudFlare
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…
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).
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).
The Last Bit
Pat yourself on the back, you’re done.
Oh, and if you fancy a DigitalOcean server…