HTTP Strict Transport Security (HSTS) and Nginx Configuration
As a web server, Nginx shines in so many ways. The latest iteration of Apache may work as well, but it isn’t easier to configure, especially with HSTS. In fact, it’s so easy to do it that you may not think about the consequences. Once you take the HSTS (HTTP Strict Transport Security) path, you may not be able to take another path unless you skip a step or two in the process.
Nginx SSL Configuration with HSTS
Nothing is required at the HTTP context level. Each SERVER context level configuration (including subdomains) must contain this minimal information:
more_set_headers "Strict-Transport-Security: max-age=31536000;";
The “max-age” value is 365 days (31536000 divided by 86400, which are the seconds in a day). Some instructions will tell you to use half that much and some will say 18 weeks. Trust me, use a year.
Everything from here on pertains to the main domain name only. If you want your subdomains (if any) covered, you should tack on the “include subdomains” token, like so:
more_set_headers "Strict-Transport-Security: max-age=31536000; includeSubDomains;";
The “www” part of a domain name is a subdomain, but it isn’t treated as such. It’s treated as an alias to the domain name without it. Whether you use it or not, the HSTS routine will treat it the same way.
If you want to get on the Google Chrome preload list, which Firefox and Microsoft’s IE11 and Edge web browsers use as well, you need to tack on the “preload” token, like so:
more_set_headers "Strict-Transport-Security: max-age=31536000; includeSubDomains; preload";
The preload list is included in the web browser. If someone visits your website with “http://” in the address, the web browser will switch them to “https://” before it even attempts to connect.
First, you can’t get on the HSTS preload list unless the “includeSubDomains” and “preload” tokens exist, after which you have to give your main domain name to that website. If you have the proper redirects in place (port 80 www and non-www to port 443 www or non-www), these tokens and getting on the preload list are not really necessary (but that’s only my opinion).
Second, if you include the “includeSubDomains” token, all of your subdomains will have to use HTTPS. Until recently, that was an issue. It isn’t now because you can get a free SSL certificate (domain validation only) for each domain and subdomain.
Third and last, once you get on the preload list, it’s nearly impossible to get off of it. Your domain name may get removed in the latest web browser version, but some people never upgrade their web browsers. This is especially true of people using one version of Internet Explorer or another.
Why use HSTS at all?
Well, this excerpt from a Wikipedia article about HTTP Strict Transport Security says it all:
The most important security vulnerability that HSTS can fix is SSL-stripping man-in-the-middle attacks…
HSTS addresses this problem by informing the browser that connections to the site should always use TLS/SSL. The HSTS header can be stripped by the attacker if this is the user’s first visit. Google Chrome, Mozilla Firefox, Internet Explorer and Microsoft Edge attempt to limit this problem by including a “pre-loaded” list of HSTS sites.
It should go without saying that HSTS is worthless unless you’re using an SSL port and have your non-SSL ports redirecting properly to it. An attacker should never be able to do anything except connect to port 80 long enough to get redirected to port 443.
You may be able to get away with not using HSTS at all if you remove any listen directives to port 80, but this is something I haven’t tested. Would the downgrade attack work if there wasn’t anything to downgrade to?