CloudFlare and Origin Servers for the Rightfully Paranoid

Mark Wubben
4 min readFeb 23, 2016

--

These days HTTPS is a necessity. It increases the privacy of your users, allows you to use new browser features, and lets you retain access to existing features. Browsers will start marking HTTP as non-secure.

CloudFlare makes it easy to provide HTTPS to your users’ browsers. They’ll host your DNS and route all web traffic through their servers. SSL certificates are provided for free and their servers are configured for best security and performance. Traffic is routed through cache servers around the world, meaning content reaches your users faster and load on your servers is decreased. All for gratis!

Security is never that easy though.

Yes, using CloudFlare protects your users from attacks that happen between CloudFlare and their browser. That’s pretty great but does not protect against (Hu)man-in-the-Midle attacks on the traffic between CloudFlare and your origin server. Or a much more mundane case of your server’s public IP address changing, meaning CloudFlare is now serving content from a different server. One that’s probably not yours.

CloudFlare provides a strict mode for securing the requests it sends to your servers:

In strict mode, CloudFlare validates the certificate chain on the back-end using its own list of trusted certificate authorities. (…) CloudFlare’s list is more exclusive than the ones used by the popular browsers. By trusting a smaller and more exclusive list of certificate authorities, we protect our customers against MitM attacks using certificates signed by rogue or compromised certificate authorities.

Strict mode requires your server to be configured to serve its traffic over HTTPS, using a valid SSL certificate. (You won’t need to optimize it to the same extent as CloudFlare’s servers are though).

A year ago CloudFlare announced a beta program that would enable you to obtain an SSL certificate for your origin server, for free. This option does not yet seem available on CloudFlare’s dashboard however. For now you’ll have to settle for the next best thing: Let’s Encrypt.

Let’s Encrypt issues certificates that are valid for 90 days. You can run a Let’s Encrypt client on your server to obtain a certificate. The client will take care of proving to Let’s Encrypt that you control the domain names you want the certificate for. There are four ways of verifying ownership:

  1. Validation via HTTP
  2. Validation via TLS with Server Name Indication
  3. Holding an existing SSL certificate
  4. Changing DNS records

The official Let’s Encrypt client only supports the first two types. Unfortunately these don’t work when you’ve set up your site to be served via CloudFlare. Neither does the third. You’ll need to use the last method instead, which uses DNS.

Alternative clients that implement the DNS challenge are available. Some have plugins that integrate with CloudFlare. I wrote my own client specifically for this purpose. Here’s a tutorial for using it with CloudFlare.

You’ll probably want a certificate that covers your domain name and the www subdomain. Use one of the alternative clients to get that certificate and use it to set up your server.

Before you change your CloudFlare settings make sure the certificate can be accepted. You can use the openssl s_client CLI command to do this. Make sure to pass it the IP address of your origin server, not your CloudFlare-hosted domain name, like so:

openssl s_client -connect 104.x.x.x:443

For my server this resulted in:

CONNECTED(00000003)
depth=2 /C=US/O=IdenTrust/CN=IdenTrust Commercial Root CA 1
verify error:num=20:unable to get local issuer certificate
verify return:0

You may get a result like this though:

CONNECTED(00000003)
depth=0 /CN=novemberborn.net
verify error:num=20:unable to get local issuer certificate
verify return:1
depth=0 /CN=novemberborn.net
verify error:num=27:certificate not trusted
verify return:1
depth=0 /CN=novemberborn.net
verify error:num=21:unable to verify the first certificate
verify return:1

This is because Let’s Encrypt is still quite new and CloudFlare doesn’t yet trust its certificate root. You’ll have to configure your server to also send Let’s Encrypt’s intermediate certificates.

Once that’s done you can log in to your CloudFlare dashboard, go to the Crypto section, and enable Full SSL (Strict) for your site. Load a URL that CloudFlare hasn’t (yet) cached to see if it works. (You’ll see Error 526 if CloudFlare can’t verify your server’s SSL certificate).

CloudFlare’s strict mode ensures it only communicates with your servers. You may want to do the same from your server’s perspective, since you probably don’t want to serve traffic to people side-stepping CloudFlare’s cache. To this end CloudFlare can be configured to present a client certificate when it sends requests to your server. You can then validate this and reject connections that did not come from CloudFlare. Exact configuration will vary by server. If you’re using Node.js I wrote a handy module you could use.

In conclusion, by enabling strict mode you can be sure only CloudFlare can see the traffic between your server and your users. Authenticated Origin Pulls let you drop any connections that did not come via CloudFlare. Now your site is more secure. Win!

--

--

Mark Wubben

Humanist ∪ Technologist. ❤ working with the web. Occasional Dutch speaker.