HSTS - a no-nonsense guide
Posted on by Steve Workman About 5 min reading time
I've been playing with HTTP Strict Transport Security (HSTS, I'm late to the party as usual) and there's some misconceptions that I had going in that I didn't know about that threw me a bit. So, here's a no nonsense guide to HSTS.
The HSTS Header is pretty simple to implement
I actually thought that this would be the hard bit, but actually putting the header in is very simple. As it's domain specific you just need to set it at the web server or load balancer level. In Apache, it's pretty simple:
Header always set Strict-Transport-Security "max-age=10886400;"
You can also upgrade all subdomains using this header
A small addition to the header auto-upgrades all subdomains to HTTPS, making it really simple to upgrade long-outdated content deep within databases or on static content domains without doing large-scale migrations.
Header always set Strict-Transport-Security "max-age=
Having a short max-age is good when you're starting out with subdomains
@steveworkman unless your env is so simple you can be *absolutely* sure there aren't HTTP only subdomains you forgot about.
— Eric Lawrence (@ericlaw) July 6, 2016
Having a short max-age is bad in the long-run
If you have a max-age length shorter than 18 weeks then you are ineligible for the preload list.
Wait, what?
There's a preload list - browsers know about HSTS-supported sites
It turns out that all of the browsers include a "preload" list of websites that support HSTS, and will therefore always point the user to the HTTPS version of the website no matter what link they have come from to get there.
So, how does it work?
Well, you go to https://hstspreload.appspot.com and submit your website to the list. Chrome, Firefox, Opera, IE 11 (assuming you got a patch after June 2015), Edge and Safari pick it up and will add you to a list to always use HTTPS, which will take away a redirect for you. There are four other requirements to meet - have a valid cert (check), include subdomains, have a max-age of 18 weeks, add a preload directive and some redirection rules.
Header always set
Here are the standard redirection scenarios for a non-HSTS site that uses a www subdomain (like most sites):
- User enters https://www.example.com - no HSTS. There are 0 redirects in this scenario as the user has gone straight to the secure www domain.
- User enters https://example.com - no HSTS. There is 1 redirect as the web server adds the www subdomain
- User enters example.com - no HSTS. There is 1 redirect here as the web server redirects you to https://www.example.com in 1 hop, adding both HTTPS and the www subdomain
How to Redirect HTTP to HTTPS as described by Ilya Grigorik at Google I/O in 2014
This is the best-practice for standard HTTPS migrations as set out in HTTPS Everywhere as Ilya Grigorik shows us that scenario 3 should only have 1 redirect, otherwise you get a performance penalty.
HSTS goes against this redirection policy... for good reason
To be included on the preload list you must first redirect to HTTPS, then to the www subdomain:
This felt incredibly alien to me, so I started asking some questions on Twitter, and Ilya pointed me in Lucas Garron's direction
— Lucas Garron (@lgarron) July 4, 2016Following that link I get a full explanation:
This order makes sure that the client receives a dynamic HSTS header from
example.com
, not justwww.example.com
http -> https -> https://www is is good enough to protect sites for the common use case (visiting links to the parent domain or typing them into the URL bar), and it is easy to understand and implement consistently. It's also simple for us and other folks to verify when scanning a site for HSTS.
This does impact the first page load, but will not affect subsequent visits. And once a site is actually preloaded, there will still be exactly one redirect for users.
If I understand correctly, using HTTP/2 you can also reuse the
https://example.com
connection forhttps://www.example.com
(if both domains are on the same cert, which is usually the case).Given the growth of the preload list, I think it's reasonable to expect sites to use strong HSTS practices if they want to take up space in the Chrome binary. This requirement is the safe choice for most sites.
Let me try to visualise that in the scenarios:
- First visit, user types example.com into their browser. They get a 301 redirect to https://example.com and receive the HSTS header. They are then 301 redirected to https://www.example.com. 2 redirects
- Second visit, the browser knows you're on HSTS and automatically upgrades you to HTTPS before the first redirect, so typing yell.com into the browser performs 1 redirect from https://example.com to https://www.example.com
- If you're in the preload list, the second visit scenario happens on the first visit. 1 redirect
So, that makes sense to me. In order to set the HSTS upgrade header for all subdomains, it needs to hit the naked domain, not the www subdomain. This appears to be a new requirement to be added to the preload list, as the Github issue was raised on May 19th this year, and Lucas has said that this new rule will not be applied to websites that are already on the list (like Google, Twitter etc).@davidben__ @igrigorik @steveworkman @lgarron You need to go to the bare domain on HTTPS 1st so it can set HSTS with includeSubdomains.
— Eric Lawrence (@ericlaw) July 4, 2016
For me, this takes away much of the usefulness of HSTS, which is meant to save redirects to HTTPS by auto-upgrading connections. If I have to add another redirect in to get the header set on all subdomains, I'm not sure if it's really worth it.
So, I asked another question:
And this is the response I got from Lucas@lgarron but we have 20 years worth of back links around the internet. Are there other benefits of the HSTS header + preload list?
— Steve Workman (@steveworkman) July 4, 2016
So it helps when people type in the URL, sending them to HTTPS first. This takes out the potential for any insecure traffic being sent. Thinking of the rest of the links on the internet, the vast majority of yell.com links will include the www subdomain, so HSTS and the preload list will take out that redirect, leaving zero redirects. That's a really good win, that Lucas confirmed.@steveworkman The banner use case is for people typing domains into the URL bar.
— Lucas Garron (@lgarron) July 4, 2016
@lgarron yes, and our sitemaps are correct with that link. What will happen to http versions of those (most common use case)?
— Steve Workman (@steveworkman) July 4, 2016
@steveworkman They will be redirected to HTTPS on the same host (if they've either visited https://t.co/L6pqB2Hw4E or have preload).
— Lucas Garron (@lgarron) July 4, 2016
@steveworkman Yeah, 1 redirect the first time if not preloaded, and "0" (HTTP->HTTPS on the client side) after that if the browser has HSTS.
— Lucas Garron (@lgarron) July 4, 2016
Summary - HSTS will likely change how you perform redirects
So, whilst this all feels very strange to me, and goes against the HTTPS Everywhere principles, it will eventually make things better in the long run. Getting subdomains for free is a great boost, though the preload list feels like a very exclusive club that you have to know about in order to make the best of HSTS. It's also quite difficult to get off the list, should you ever decided that HTTPS is not for you as you'll have the HSTS header for 18 weeks, and there is no guarantee that the preload list will be modified regularly. It's an experiment, but one that changes how you need to implement HSTS.
So, that's my guide. Comments, queries, things I've gotten wrong, leave a comment below or on Twitter: @steveworkman