Enabling HSTS on Your Website

Content:

HTTP Strict Transport Security, or HSTS, is a security mechanism designed to protect websites from certain man-in-the-middle attacks. When enabled, HSTS allows a web server to force a client to connect through HTTPS.

Using HTTPS ensures that the data sent between the client and the server is encrypted, protecting sensitive information transmitted between the two.

HSTS prevents attacks, such as downgrade attacks, which rely on a server accepting connections using HTTP.

Before going any further, your server will need to accept both HTTP and HTTPS requests, and ideally have a valid security certificate.

How HSTS Works

When HSTS is configured, a site connecting over HTTPS will be sent a special header in the response. This header, Strict-Transport-Security, informs the browser receiving the response that requests should only be made through HTTPS in the future.

The browser will retain this information, for the length of time specified in the header response. If a user attempts to access the site through HTTP while the HSTS directive is valid, the browser will automatically change the request to use HTTPS.

This does require an initial connection to the server before it becomes active, as well as needing a further connection once the maximum age has passed.

Many websites automatically redirect HTTP traffic to HTTPS, through a server redirect. While this system generally works well, this requires two requests from the browser – the initial HTTP request, and a subsequent HTTPS request once the server redirect is returned. HSTS skips the initial HTTP request entirely – the redirect occurs in the browser instead. This can provide a small performance boost following the initial response.

Adding HSTS Headers

HSTS is enabled by adding the HTTP header Strict-Transport-Security to your server response. This header should include a max-age attribute, which specifies the length of time (in seconds) the HSTS instruction should apply for.

Strict-Transport-Security:max-age=31536000

31536000 seconds, equal to one non-leap year, is a common value.

You can add this header in your application, or more widely through your web server configuration.

For example, to add HSTS to nginx, add

add_header Strict-Transport-Security "max-age=31536000"

to the server block you want to apply it to.

The header should only be added to connections over HTTPS – it will be ignored for HTTP connections.

When a user visits the site, the max age value retained by their browser will update automatically. For example, with the one year max age set, a user revisiting the site after six months will reset the one year

With the previous header, HSTS will only apply to the request domain. By adding the includeSubDomains attribute to the header, the HSTS directive will apply to all subdomains under the request domain.

add_header Strict-Transport-Security "max-age=31536000; includeSubDomains"

This should only apply to subdomains below the request domain. For example:

  • example.com HSTS would cover blog.example.com
  • blog.example.com HSTS would cover test.blog.example.com
  • blog.example.com HSTS wound not cover example.com

That said, it’s advised to ensure all subdomains under the top-level domain (e.g. example.com) use HSTS connections. How HSTS is handled is at the discretion of the web browser, so it’s possible this is not always handled consistently.

Drawbacks

The one key drawback of HSTS is the requirement to constantly provide an HTTPS connection to your site. While this should arguably be standard on the modern web, the

For example, an issue with a web certificate will generally render your site unusable. I’m sure we’ve all visited a website before and seen a message similar to this one.

Connection not private message
An issue with the security certificate on the site. We’re still able to proceed.

Ever wondered why the option to proceed regardless is sometimes missing?

Connection not private message with no proceed option
An issue with the certificate on an HSTS-enabled site. It’s no longer possible to proceed.

You can blame HSTS for that. It does not allow an HTTP fallback, even if there is an issue visiting using HTTPS.

Should HTTPS ever be removed from the site, a similar issue will occur – at least, until the time period outlined in the max age directive has passed.

As the max age value directive is updated on every connection, it is possible to reduce or even remove HSTS entirely by setting a value of 0.

add_header Strict-Transport-Security "max-age=0"

This does still require the ability to connect through HTTPS in the first place. You should therefore consider carefully whether a long HSTS max age value is suitable for your site.

HSTS Preloading

From a security perspective, there’s still one weakness in HSTS. The initial connection to the server can still be made using HTTP, which will remain vulnerable.

To work around this, web browsers ship with an HSTS preload list. This list contains sites that are known to enforce HSTS, allowing the browser to apply the redirect without having to make an initial visit to the site.

You can submit your website to the preload list using the form at https://hstspreload.org.

Before you do this, though make sure you’re fully aware of the consequences. There’s also a slight change to the required header, explained below.

Adding the Preload Header

It’s possible for anyone to submit a domain to the preload list. To ensure the site owner intends for the site to be added, there’s an addition preload attribute to add to the header. The includeSubDomains attribute is also a requirement.

add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload"

Once submitted, the server response header is checked to ensure the required attributes are present.

You’ll then need to wait for browser developers to include the updated HSTS preload list with their browser. The time this takes will vary, depending on the browser release schedule.

You can check the status of your submission at any time, using the page linked previously.

HSTS status check result
HSTS status on this website.

As you can see, HSTS preload is currently enabled on this site.

Removals

Circumstances change, and it might be necessary to remove your site from the HSTS preload list. Be aware that, while this is possible, this is a difficult process and in the best-case, will take weeks to take effect.

There are a few prerequisites before you submit your request.

First, ensure your site still accepts connections through HTTPS. If you’re planning to remove HTTPS, you’ll need to keep it active for now. You’ll also need to retain a security certificate for your HSTS-enabled domain.

Next, remove the preload attribute from your response header.

You can now request removal using a second form over at the HSTS preload site.

Be aware that, like the addition, this will take time to filter through to web browsers as they update. Users with an older version of a web browser will retain their previous preload list, so your site is likely to be impacted well into the future, even after removal.

To speed up the process, you can change the max-age header to 0. This is considered a ‘knockout directive’, and actually overrides the preload list included in the browser. This should be kept in place for as long as is deemed necessary.

Should I Preload?

The decision to add your site to the preload list shouldn’t be taken lightly. The difficulty in removing your domain from the list, combined with the requirement to include subdomains, mean that this isn’t the right solution for everyone.

HSTS itself is useful, and we would recommend enabling it on your site. The preload list is a nice additional feature, but should be considered an optional extra feature if it’s suitable for your site.

If you like what we do, consider supporting us on Ko-fi