Mobile app version of vmapp.org
Login or Join
Connie744

: 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.

@Connie744

Posted in: #Hsts #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. 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.

10.02% popularity Vote Up Vote Down


Login to follow query

More posts by @Connie744

2 Comments

Sorted by latest first Latest Oldest Best

 

@Heady270

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.

10% popularity Vote Up Vote Down


 

@Jamie184

...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?

10% popularity Vote Up Vote Down


Back to top | Use Dark Theme