Configuring the ufw firewall to allow Cloudflare IP addresses

How to allow only Cloudflare to access your web sites through your firewall

I have a Linode running Ubuntu 16.04, and I use the ufw firewall.

I have a web site running on that server, originally accessible via HTTPS on port 443 from anywhere on the internet.

The domain for that web site is managed via Cloudflare. I want the site to be available only through the domain, and not via the Linode's IP address.

Cloudflare publishes the IP addresses it uses to access your web site: https://www.cloudflare.com/ips/

Here is a page describing the overall idea of using ufw to allow access to your web site only from those Cloudflare IP addresses: https://www.ajsalkeld.com/blog/tutorial/2016/08/01/how-to-use-ufw-to-whitelist-cloudflare-ips-ubuntu-debian-digitalocean/

In this repo https://github.com/Paul-Reed/cloudflare-ufw there is a script that does this: https://github.com/Paul-Reed/cloudflare-ufw/blob/master/cloudflare-ufw.sh

I modified it a bit so that:

  • it uses the /tmp directory
  • it uses a unique filename (containing the current process ID) when retrieving the Cloudflare IP addresses
  • it specifically allows connections only on port 443 (you may want to allow connections on port 80 as well or instead)
  • it just outputs to the screen the commands that it would issue using ufw; If the commands look sane/good to you, copy and paste them into your terminal to run them

Here is my script:

#!/bin/sh
cd /tmp
wget https://www.cloudflare.com/ips-v4 -O ips-v4-$$.tmp
wget https://www.cloudflare.com/ips-v6 -O ips-v6-$$.tmp

for cfip in `cat ips-v4-$$.tmp`; do echo "ufw allow from $cfip to any port 443 proto tcp"; done
for cfip in `cat ips-v6-$$.tmp`; do echo "ufw allow from $cfip to any port 443 proto tcp"; done

Once I ran the script and copied and pasted its output into a terminal, ufw was configured as follows:

# ufw status numbered
Status: active

     To                         Action      From
     --                         ------      ----
[ 1] 22                         ALLOW IN    Anywhere
[ 2] 443/tcp                    ALLOW IN    103.21.244.0/22
[ 3] 443/tcp                    ALLOW IN    103.22.200.0/22
[ 4] 443/tcp                    ALLOW IN    103.31.4.0/22
[ 5] 443/tcp                    ALLOW IN    104.16.0.0/12
[ 6] 443/tcp                    ALLOW IN    108.162.192.0/18
[ 7] 443/tcp                    ALLOW IN    131.0.72.0/22
[ 8] 443/tcp                    ALLOW IN    141.101.64.0/18
[ 9] 443/tcp                    ALLOW IN    162.158.0.0/15
[10] 443/tcp                    ALLOW IN    172.64.0.0/13
[11] 443/tcp                    ALLOW IN    173.245.48.0/20
[12] 443/tcp                    ALLOW IN    188.114.96.0/20
[13] 443/tcp                    ALLOW IN    190.93.240.0/20
[14] 443/tcp                    ALLOW IN    197.234.240.0/22
[15] 443/tcp                    ALLOW IN    198.41.128.0/17
[16] 22 (v6)                    ALLOW IN    Anywhere (v6)
[17] 443/tcp                    ALLOW IN    2400:cb00::/32
[18] 443/tcp                    ALLOW IN    2405:8100::/32
[19] 443/tcp                    ALLOW IN    2405:b500::/32
[20] 443/tcp                    ALLOW IN    2606:4700::/32
[21] 443/tcp                    ALLOW IN    2803:f800::/32
[22] 443/tcp                    ALLOW IN    2c0f:f248::/32
[23] 443/tcp                    ALLOW IN    2a06:98c0::/29

I tested by browsing to my web site's domain (e.g. https://mysite.com) and it worked. Then I tried to browse to my server's IP address (e.g. https://123.45.67.89) and it did not work, as expected and as intended.


Update: January 3, 2018: Thank you to Florian Schulze who suggested the use of Cloudflare's authenticated origin pulls, described at https://support.cloudflare.com/hc/en-us/articles/204494148-Setting-up-NGINX-to-use-TLS-Authenticated-Origin-Pulls. With this method, you don't have to worry that Cloudflare may have changed its IP addresses (the reason why you would need to update your ufw rules periodically).

There is also TLS client side authentication, a feature described at https://support.cloudflare.com/hc/en-us/articles/115000088491-Cloudflare-TLS-Client-Auth. It is, however, available only to Enterprise Cloudflare customers.