Cloudflare - Free Tier

Cloudflare - Free Tier

While researching ways to improve the speed of this website, I recently found out that Cloudflare offers a free tier of service to personal websites and blogs. Everything I read made this seem like a pretty easy move and the benefits of increased security, speed, and DOS protection seemed like this was a good decision.

The decision was a good one and the benefits have materialized. That being said, I have had to learn a lot and full implementation has been a little complicated in trying to make my server as secure as possible. I did not know all of this was possible at the outset but here is what I have been able to do with Cloudflare.

Cloudflare Settings

Initially setting up Cloudflare is really easy. Simply sign up for an account, point your current domain records to the IPs provided by Cloudflare, and then allow Cloudflare to manage your DNS. This takes about 24 hours but does not require any down time on your website.

At this point hitting your domain directly will route all requests through the Cloudflare CDN with whatever options you have configured in their admin panel. In my case, the only major consideration I had to make was with respect to Crypto/SSL. Since I was running Let's Encrypt Certs on my page I had to configure Full (Strict) mode (I have since changed this, more on that later).


I also enabled most of the speed improving capabilities of Cloudflare. The only issue I noticed at this point was that PrismJS (a code syntax highlighting JS module) kept kicking back 404 errors in my web logs. If I put Cloudflare in Development (bypass) mode, I did not get the errors. After weeks of troubleshooting locally, I finally discovered that the RocketLoader feature is in Beta and apparently has some issues with PrismJS. Disabling RocketLoader solved that problem.

Client Cert

While perusing the Cloudflare settings (and wanting to enable all the security related ones), I found a setting for Authenticated Origin Pulls. This setting passes a certificate in all requests directly to your server so that you can validate that the requests come from CLoudflare and nowhere else. This requires local configuration changes to your web server config.

The complication here is that I do some management of my website through an SSH tunnel so as not to expose my management interface. As such, Authenticated Origin Pulls will fail when accessing my page from local host with the recommended config changes.

The update to make this work with Cloudflare is to set up different server blocks (in NGINX as least) for the primary website and for the admin portion much like this ServerFault article.

The block that you do NOT want to do client certificate checking on needs to come first in your config but requires no other changes (this took a few hours of troubleshooting). For all other server blocks, you will need to add these lines:

ssl_client_certificate /etc/ssl/certs/cloudflare.crt;
ssl_verify_client on;

Then you will need to save the Cloudflare Public Key cert to the location listed above (or a location of your choosing). Restart your NGINX service and you should be good to enable this setting in your Cloudflare panel.

SSL Configuration

Also while perusing the security and crypto settings for Cloudflare I realized that they present certificates for SSL/TLS and that users never actually see my server certificate. In Full (strict) mode, Cloudflare still validates my cert but there is no real benefit here. I also tend to have major issues renewing my Let's Encrypt certs (I think due to my web server config).

Because of this, I decided to ditch Let's Encrypt just use self-signed certs on my server end and rely on Cloudflare to present that valid certs to users. I just followed this Digital Ocean guide to configure my server with self-signed certs.

openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout /etc/ssl/private/nginx-selfsigned.key -out /etc/ssl/certs/nginx-selfsigned.crt

And update these lines in the my NGINX config:

ssl_certificate /etc/ssl/certs/nginx-selfsigned.crt;
ssl_certificate_key /etc/ssl/private/nginx-selfsigned.key;

Finally, set your Cloudflare SSL setting to Full (ignore certificate errors).


At this point, everything was pretty secure and squared away through Cloudflare but my website was still accessible directly via IP. I already had a good set of rules for iptables from here but they did not take into account this Cloudflare configuration. To update I needed to add these lines to my iptables rules:

# Accept HTTP and HTTPS from CLoudflare IPs only
-4 -A INPUT -m set --match-set cf4 src -p tcp -m multiport --dports http,https -j ACCEPT
-6 -A INPUT -m set --match-set cf6 src -p tcp -m multiport --dports http,https -j ACCEPT
# Continue to allow localhost access
-4 -A INPUT -i lo -p tcp -m multiport --dports http,https -j ACCEPT

Then to create and keep the IP sets up to date I followed the steps here I rolled those steps into a script that I will run as a cron job on a weekly basis to ensure I get any updates.

echo "Destorying old IP Sets"
ipset destroy cf4
ipset destroy cf6

echo "Creating new IP Sets"
ipset create cf4 hash:net
ipset create cf6 hash:net family inet6

echo "Getting latest lists from CLoudflare"
for x in $(curl; do ipset add cf4 $x; done
for x in $(curl; do ipset add cf6 $x; done

echo "Reload IP tables"


All of this configuration should force all traffic to my server through Cloudflare except for traffic that I am tunneling over SSH to the server directly. I am taking advantage of as much of the security and speed improvements as I can from Cloudflare. I have also learned a TON more about server configs and using a CDN.

Cloudflare Client Certificate