Configure HSTS (HTTP Strict Transport Security) for Apache and Nginx
HTTP Strict Transport Security (or HSTS) is a security capability to force web clients using HTTPS. The idea behind HSTS is that clients which always should communicate as safely as possible. At achieve this, the web server and web browser will prefer the HTTPS protocol instead of HTTP.
Benefits
The clear benefit of “forcing” a client to use HTTPS directly, is decreasing the risk of sharing any sensitive information via a protocol which can be snooped upon. Additionally it improves the performance by eliminating one redirect response (301/302). Another benefit is to force using a secure connection and deny a client if this can not be guaranteed (e.g. expired or self-signed certificate).
Configuration
Configure HSTS on Apache
Load the headers and mod_rewrite module (just to be sure)
# Load modules (or use the IfModule)
LoadModule headers_module modules/mod_headers.so
LoadModule rewrite_module modules/mod_rewrite.so
Rewrite HTTP connections and redirect them to HTTPS:
# Redirect HTTP connections to HTTPS
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteCond %{HTTPS} off
RewriteRule (.*) https://%{HTTP_HOST}%{REQUEST_URI} [R=301,L]
</IfModule>
Now configure the virtual host:
<VirtualHost 192.168.1.1:443>
Header always set Strict-Transport-Security "max-age=31536000; includeSubDomains"
</VirtualHost>
Configure HSTS on Nginx
To use HSTS on Nginx, use the add_header directive in the configuration. Then tell clients to use HSTS with a specific age.
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always;
- max-age: expire time
- includeSubDomains: also apply this protection on our subdomains
- preload (optional): preload list in some browsers, requires a max-age with a minimum value of 31536000
The always statement at the end of the add_header setting ensures that the header is always inserted in the response headers.
Adjust the related virtual hosts to perform a redirect (301) to the secured version of the website:
http {
server {
listen 80;
server_name example.com
return 301 https://$server_name$request_uri;
}
server {
listen 443;
server_name example.com
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always;
}
}
Important notes
The HSTS header should only be sent over a secured channel, therefore HTTP responses should not include them.
Within the headers, the max-age defines what period the site is willing to accept HTTPS-only (31536000 in the examples are 12 months). Usually, the amount of time is less important. This is because the trend is to keep using HTTPS for privacy and data protection anyways.
Additionally, make sure the domain itself is also properly configured for HSTS. This reduces attacks on the underlying subdomain names.
Technical details
RFC: RFC6797 (HTTP Strict Transport Security (HSTS))
More resources
See also the Wikipedia page on HTTP Strict Transport Security.