I would like to implement HSTS to my application.
I have an ELB terminating SSL and forwarding the traffic to my application, which is an apache server used as reverse p
Maybe? - Did resolve a similar scenario I had in the past.
Please note that since this is not supported for Apache < 2.4, it's best to encapsulate it in <IfVersion >= 2.4>
, like so:
<IfVersion >= 2.4>
<IfModule mod_headers.c>
<If "%{REQUEST_SCHEME} == 'https' || %{HTTP:X-Forwarded-Proto} == 'https'">
Header set Strict-Transport-Security "max-age=31536000; includeSubDomains; preload"
</If>
</IfModule>
</IfVersion>
I asked the AWS Support and the answer was that at the moment ELB cannot add HSTS headers on the requests from the clients. So, I decided to find a workaround using my Apache server. Here is the solution I found:
The HSTS RFC states that
An HSTS Host MUST NOT include the STS header field in HTTP responses conveyed over non-secure transport.
What I did then was to set the header AFTER the http=>https redirection in Apache. Since this redirection has the flag [L], that means that the 301 redirection will not include the header, but any https request will. My apache config looks like this:
<VirtualHost *:80>
...
#http=>https
RewriteCond %{HTTP:X-Forwarded-Proto} =http
RewriteRule . https://%{HTTP:Host}%{REQUEST_URI} [L,R=permanent]
#hsts
Header set Strict-Transport-Security "max-age=31536000"
If you're working with Apache 2.4+, you may be familiar with expressions and the directives <If>
, <ElseIf>
, and <Else>
.
I have a complex configuration between dev, staging, and production environments, so relying on the [L]
flag with the RewriteRule
just wouldn't cut it for me.
This brought me to the following solution, which I placed in my .htaccess:
<IfModule mod_headers.c>
<If "%{REQUEST_SCHEME} == 'https' || %{HTTP:X-Forwarded-Proto} == 'https'">
Header set Strict-Transport-Security "max-age=31536000"
</If>
</IfModule>
It works better in my environment and I feel that it is more reliable for meeting the RFC.
You could drop the "%{REQUEST_SCHEME} == 'https'
part if you never hit your instances directly, but that's part of my debug process in my dev environments.
Much thanks to Pedreiro for pointing me in the right direction for the actual specifications on the HSTS RFC.