Keep Server Online
If you find the Apache Lounge, the downloads and overall help useful, please express your satisfaction with a donation.
or
A donation makes a contribution towards the costs, the time and effort that's going in this site and building.
Thank You! Steffen
Your donations will help to keep this site alive and well, and continuing building binaries. Apache Lounge is not sponsored.
| |
|
Topic: Rewrites and HSTS |
|
Author |
|
technima
Joined: 15 Jul 2016 Posts: 2
|
Posted: Fri 15 Jul '16 12:10 Post subject: Rewrites and HSTS |
|
|
I'm using this in .htaccess to redirect my visitors to the naked domain:
Code: | RewriteEngine on
RewriteCond %{HTTP_HOST} ^www\.(.+)$ [NC]
RewriteRule ^ https://%1%{REQUEST_URI} [L,R=301] |
The problem is that the 301 redirect is being sent without the HSTS header that I included at the top of the .htaccess file.
Code: | Header set Strict-Transport-Security "max-age=31415926; includeSubDomains; preload" env=HTTPS |
Is there any way to redirect conditionally with HSTS being sent in the header of this redirect?
My host runs Apache v2.2.22 and here is the entirety of my .htaccess file:
Code: | Header set Strict-Transport-Security "max-age=31415926; includeSubDomains; preload" env=HTTPS
RewriteEngine On
RewriteCond %{HTTPS} !=on
RewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]
RewriteEngine on
RewriteCond %{HTTP_HOST} ^www\.(.+)$ [NC]
RewriteRule ^ https://%1%{REQUEST_URI} [L,R=301] |
|
|
Back to top |
|
technima
Joined: 15 Jul 2016 Posts: 2
|
Posted: Sat 16 Jul '16 14:07 Post subject: Fixed! |
|
|
I managed to fix this. Here's how I did it.
First, I need to explain the env="HTTPS" at the end of the Header directive. The very last sentence of section 7.2 in RFC 6797 (HTTP Strict Transport Security [HSTS]) states: "An HSTS Host MUST NOT include the STS header field in HTTP responses conveyed over non-secure transport." Therefore, in order to be completely RFC 6797 compliant, you must include this argument in the Header directive for Apache HTTP Server (Dreamhost uses Apache HTTP Server for its shared hosting).
Second, I decided to stop looking at the documentation for the Apache HTTP Server's mod_rewrite module (here), which implements the RewriteRule directive, and look at the documentation for the mod_headers module (here), which implements the Header directive. That's where I stumbled upon the condition argument for the Header directive. The default for the condition argument is onsuccess, but that doesn't work for a 301 redirect which by its very being is not a successful (2xx) response. So the optional always condition needed to be set in Header set Strict-Transport-Security "max-age=31415926; includeSubDomains; preload" env=HTTPS for the HSTS Header directive to operate on the www-remove RewriteRule.
Code: | Header always set Strict-Transport-Security "max-age=31415926; includeSubDomains; preload" env=HTTPS |
Third, although the www-remove RewriteRule will only ever get to respond to HTTPS requests (by virtue of the preceeding forced-HTTPS RewriteRule), RewriteRules always reset the environment of the response header to HTTP (not HTTPS). Because of this and the fact that the HSTS Header directive is set to require an HTTPS environment, the HSTS Header directive fails to operate on the www-removal RewriteRule. So, the www-remove RewriteRule needs to be modified to set the post RewriteRule environment to HTTPS. I took a look at the documentation for the mod_rewrite module (here) and saw that RewriteRule allows for flags to be set, one of which (E) allows for environment variables such as HTTPS to be set. Once I added E=HTTPS to my flags for the www-remove RewriteRule, the HSTS Header directive could now operate on the www-remove RewriteRule directive. With that set, the secure www subdomain was now responding with a 301 redirect and HSTS in its header.
Code: |
RewriteEngine on
RewriteCond %{HTTP_HOST} ^www\.(.+)$ [NC]
RewriteRule ^ https://%1%{REQUEST_URI} [E=HTTPS,L,R=301] |
PS: I'd like to thank TruboFlash, whose personal blog entry on the visibility of environment variables between various Apache HTTP Server's modules' directives gave me the surprisingly never before documented insight needed to connect the dots for this problem. |
|
Back to top |
|
|
|
|
|
|