: HSTS Preload section on .htaccess Recently having moved a site to SSL, I looked into enforcing HSTS for eventual preload. The syntax is approved and the Chrome List allows it to be OK.
Recently having moved a site to SSL, I looked into enforcing HSTS for eventual preload. The syntax is approved and the Chrome List allows it to be OK. However, not being a coder at all, a slight problem arises.
I have:
php_value upload_tmp_dir "/tmp"
# Force SSL
RewriteEngine On
RewriteCond %{HTTPS} off
RewriteRule ^ %{HTTP_HOST}%{REQUEST_URI} [L,R=301]
# Redirect to www
RewriteCond %{HTTP_HOST} ^example.com.com [NC]
RewriteRule (.*) www.example.com/ [E=HTTPS,R=301,L]
# Security header
Header set Strict-Transport-Security "max-age=63072000; preload; includeSubdomains" env=HTTPS
# End Force SSL'
This seems OK, but some sites on the web --- I won't clutter this with cites --- advise RewriteCond %{HTTPS} off and others have RewriteCond %{HTTPS} on
Logically ON seems right, but I need to know what is correct. Neither give errors.
More posts by @Connie744
2 Comments
Sorted by latest first Latest Oldest Best
RewriteCond %{HTTPS} !=on
RewriteRule (.*) %{HTTP_HOST}%{REQUEST_URI} [R=301,L]
Check whether HTTPS ISN'T on
RewriteCond %{HTTPS} off
RewriteRule (.*) %{HTTP_HOST}%{REQUEST_URI} [R=301,L]
Check whether HTTPS IS off
RewriteCond %{SERVER_PORT} !^443$
RewriteRule (.*) %{HTTP_HOST}%{REQUEST_URI}
Check whether connection runs NOT on secure https port 443
But all of them do the same: check if no https and redirect to https.
<IfModule mod_headers.c>
Header set Strict-Transport-Security "max-age=10886400; includeSubDomains; preload"
</IfModule>
You know already what it does.
...advise RewriteCond %{HTTPS} off and others have RewriteCond %{HTTPS} on
That wouldn't make sense in the context given as these are obviously opposites (I would be interested to see the full examples you are quoting this from).
However, maybe you mean off vs !on? These are equivalent in this context. The ! prefix negates the regex, so that effectively means not "on" (ie. it must be "off").
So, in the context of your directives above, where you are testing whether HTTPS is not active, then the following are equivalent:
# Does the HTTPS server variable contain "off"?
RewriteCond %{HTTPS} off
# Does the HTTPS server variable not contain "on"?
RewriteCond %{HTTPS} !on
The HTTPS server variable is either set to "on" or "off". (Or, it's not set at all - but that is dependent on your server/SSL setup and you will have already discovered that by now.)
Which you use is really just a matter of preference.
# Redirect to www
RewriteCond %{HTTP_HOST} ^example.com.com [NC]
RewriteRule (.*) www.example.com/ [E=HTTPS,R=301,L]
# Security header
Header set Strict-Transport-Security "max-age=63072000; preload; includeSubdomains" env=HTTPS
(I assume the extra .com in ^example.com.com is just a typo? That should be just ^example.com.)
E=HTTPS - The setting of the environment variable HTTPS on the RewriteRule redirect would seem to be required in order to set the Strict-Transport-Security HTTP response header on the canonical (HTTPS only) non-www to www redirect[*1] (ie. example.com to www.example.com), which is set conditionally based on the env=HTTPS check on the Header directive. However, for this header to be set on the redirect, you'll also need to use the always keyword on the Header directive, like so:
Header always set Strict-Transport-Security "max-age=63072000; preload; includeSubdomains" env=HTTPS
As noted in the Apache docs, regarding the use of always with the Header directive when setting headers on redirects:
You're adding a header to a locally generated non-success (non-2xx) response, such as a redirect, in which case only the table corresponding to always is used in the ultimate response.
[*1] This header must be set on the redirect in order to satisfy point 4.1 of the HSTS preload submission requirements:
If you are serving an additional redirect from your HTTPS site, that redirect must still have the HSTS header (rather than the page it redirects to).
Just an additional comment on the linked article in the comments below, that states:
The env=HTTPS environment variable wasn't working as expected. So I used the E=HTTPS flag on the www redirect to **set the env=HTTPS environment variable on the next request**.
The last bit about setting "the env=HTTPS environment variable on the next request" isn't quite correct. It's setting the HTTPS environment variable on the current (redirect) response. By the time the "next request" comes about (ie. the browser has responded to the redirect), this environment variable (that was set above) is long forgotten. but this does require the always keyword to be used on the Header directive (as mentioned above).
Header always set Strict-Transport-Security "max-age=63072000; preload; includeSubdomains" env=HTTPS
Just a minor point, and maybe this doesn't actually matter, but... I would include the preload directive at the end of the list of directives. For example:
Header always set Strict-Transport-Security "max-age=63072000; includeSubdomains; preload" env=HTTPS
The preload directive is not actually part of the HTTP Strict Transport Security (HSTS) specification. It is only required by the preload list. Other user-agents/browsers do not use this and may not even understand this, so it would be more logical to put this at the end of the list. Some parses might stop as soon as they reach an "invalid" directive?
Terms of Use Create Support ticket Your support tickets Stock Market News! © vmapp.org2024 All Rights reserved.