HSTS preloading

For a while now, my website has been using HSTS.  HSTS stands for HTTP Strict Transport Security, and essentially it’s a response header that your server sends back with your website to tell that browser that in future, this page should always be requested securely (via HTTPS).  I talked about it briefly last year in my post about making WCG Online secure and again in my post about going HTTPS with Cloudflare.

At the time, I was experimenting with HSTS, and not ready to fully commit, so I did not choose to “preload”.  However, now that I’m more comfortable, this does add an extra layer of security.

For the astute, you may have noticed the hole already – the first time someone accesses your site, if they do so insecurely (which is still the default for browsers if you don’t specify HTTPS) then they will receive the page insecurely, which will then return the header and in my case, because I have it configured within Cloudflare, a redirect to the secure site.  But this initial response is insecure, and could be tampered with.  If someone stripped out this header, you may never get the benefits of HSTS!

The solution to this is to “preload”.  If you’re using Cloudflare, this is as simple as going into the Crypto tab and clicking on the “Change HSTS settings” button, confirm you understand the dangers of getting this wrong, and then enabling the preload option.  You’ll also need to make sure you have a suitably long max age (at least a year) and enable the include subdomains option.  These are all pre-requisites for preloading.

Cloudflare options
Cloudflare options for HSTS

The next step is to go to the HSTS Preload website, so that you can submit your URL.  This site will test your URL to make sure that it matches all of the required pre-requisites, and return any errors.

For me, I had errors about redirections, where “rik.onl” was redirecting to http://www.rik.onl, the insecure protocol, which is a no-no for HSTS.  I checked my .htaccess file and there were no redirects in there.  Then it occurred to me that I now run my site using WordPress, in which you configure the site URL, and it was WordPress that was performing this redirect to “www” – it’s specified as HTTP here because my origin server doesn’t have a certificate, and making it HTTPS causes Cloudflare to go into a redirect loop.

To fix this, I added my redirect rules back into my .htaccess file, like this…

  RewriteEngine On
  RewriteCond %{HTTP_HOST} ^rik\.onl$ [NC]
  RewriteRule ^(.*)$ https://www.rik.onl/$1 [R=301,L]

This tells the webserver to rewrite any URL that starts “rik.onl” to be https://www.rik.onl and this kicks in before WordPress, so WordPress no longer tries to redirect itself.  You can see this at work in the DevTools “Network” tab…

Redirects for rik.onl
  1. Requesting http://rik.onl (using HTTP protocol) triggers a 307 redirect to https://rik.onl, because of my HSTS header.
  2. Requesting https://rik.onl (using HTTP2, and therefore HTTPS protocol) triggers a 301 redirect to https://www.rik.onl, because of my .htaccess rewrite rule.
  3. Requesting https://www.rik.onl (using HTTP2, and therefore HTTPS protocol) works successfully (200) and the website loads.

Ideally this wouldn’t double hop, but it’s not possible to use HSTS to redirect from non-www to www – at least the 307 is internal though, so there’s only one external redirect.

Now going back to the HSTS Preload website and checking “rik.onl” again, I get lots of lovely comforting green, a couple of confirmation boxes (yes, I do own this domain, and no, I don’t have subdomains that need to be insecure) and I can submit my website.

It’ll take a while for this to really happen, because my website needs to be baked into the next version of each of the major browsers, but over time, my website will be on the preload list, and this 307 redirect will happen the very first time someone goes to my website.