So I recently issued a Let’s Encrypt cert for my main websites (both built using Drupal 7.x via sub-directories) and I’ve tried to force them to use it.
To give context…
My “live” site installation path: /home/myhostspace/public_html/mylivesite/ (Drupal 7 installation one.)
My “test” site installation path: /home/myhostspace/public_html/mytestsite/ (Drupal 7 installation two.)
I have an .HTACCESS file at the following locations:
/home/myhostspace/public_html/.HTACCESS - Handles initial requests from domain aliases.)
I’ve configured the first HTACCESS to handle routing of requests made with my aliases so that each domain name is correctly routed to the respective sub-directory installation (because without it, requests would be reaching “/home/myhostspace/public_html/” for requests like “www.mylivesite.com” or “www.mytestsite.com”.
But in the Drupal HTACCESS files, I have added the following code after the initial “RewriteEngine on” lines:
.
.
.
# I added the following 3 lines below, which made it looks like SSL was working:
RewriteCond %{HTTPS} off
RewriteCond %{HTTP:X-Forwarded-Proto} !https
RewriteRule ^(.*)$ https://%{HTTP_HOST} [L,R=301]
.
.
.
Everything else was left alone…
Now the problems:
For the most part, this seems to be working without major issues except that…
When I look at Firebug in Firefox, I see the initial requests indicating an HTTP status of 301 (“Moved Permanently”) but that’s only before any redirections occur. After that, everything looks fine.
Automated CRON appears to be having issues… The command I’ve scheduled with CRON is as follows: lynx -source https://www.mylivesite.com/cron.php?cron_key=dhfkjdhjfhdjfhdjhhdfh, but when it runs, it terminates with the following error:
I can execute CRON manually without a single problem from inside Drupal admin. When I try to run the command directly via an SSH prompt on the server, it results in the same problem. Interestingly enough, when I try lynx https://www.mylivesite.com/cron.php?cron_key=dhfkjdhjfhdjfhdjhhdfh, (without -source) I get a subsequent prompt in the SSH window indicating the following:
…which makes me suspect that something on my host’s server might be misconfigured. I originally wanted to blame my HTACCESS enforcement of SSL as being the culprit in all this but I suspect the issues here could also be related to my recent PHP upgrade as well due to going from a 5.x version up to a 7.x version. I just don’t know.
I could use some insights here. My experience with HTACCESS is sparse and I’m not within earshot of being an SSL guru… Where should I start in fixing all this?
I’ve always used Lynx–I can’t remember why I went with it instead of something else. I guess because it was something I came across from the bazillions of tutorials and articles I remember scouring through to find something that just worked. Ha. Why would a cert run into problems from how the website is accessed based on the use of Lynx??? Why would that cause problems, I mean? Seems like Lynx is just a text browser and since all I used it for was just triggering CRON, I can’t seem to understand why it would run into problems now for no other reason than the use of my cert. (Just thinking out loud here and trying to understand the situation better.)
Needless to say, I’ll give your idea a try and see what happens with it. I just tried it manually in an SSH prompt and it seemed to work. Hopefully scheduling it through CRON results in the same outcome.
Any thoughts about the 301 issue? Maybe I should make a separate post about that?
SSL is based on trust. All browsers and other utilities that connect to websites have a list of root certificates they trust, and every SSL certificate you get has to be signed by one of those root certificates in order for the tool to accept it.
Let’s Encrypt uses a relatively new root certificate and apperantly lynx doesn’t have it yet, so it complains. This is not a problem with your server but with lynx.
With regards to the 301 I don’t really understand what the problem is there. Could you elaborate?
Sure. When I make an initial request for www.mylivesite.com, I can see in Firebug’s Network tab that the first hit results in a 301: Moved Permanently status code. Every hit after that thought looks like a clean 200s and the page loads up without a single issue.
What I suspect is going on here is that it has something to do with the HTACCESS file I have in /home/myhostspace/public_html/, which I try to use to handle how requests get routed to their appropriate sub-directory Drupal installations.
So here’s the layout on my web server:
/home/myhostspace/public_html/.HTACCESS ← Handles initial request routing, namely for www.mylivesite.com.
/home/myhostspace/public_html/mylivesite/
/home/myhostspace/public_html/mytestsite/
If I enter into my browser the URL of “www.mylivesite.com”, the /home/myhostspace/public_html/.HTACCESS file is supposed to direct that request to the appropriate Drupal installation in the above “live” sub-directories but also ensure that SSL is being used.
Here’s what the HTACCESS file looks like:
RewriteEngine on
# For all www.mylivesite.com requests, route the visitor to /home/myhostspace/public_html/mylivesite/...
RewriteCond %{HTTP_HOST} ^www\.mylivesite\.com$ [NC]
RewriteRule ^$ mylivesite/index.php [L]
RewriteCond %{HTTP_HOST} ^www\.mylivesite\.com$ [NC]
RewriteCond %{DOCUMENT_ROOT}/mylivesite%{REQUEST_URI} -f
RewriteRule .* mylivesite/$0 [L]
RewriteCond %{HTTP_HOST} ^www\.mylivesite\.com$ [NC]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule .* mylivesite/index.php?q=$0 [QSA]
# Meant to force use of SSL...
RewriteCond %{HTTP_HOST} ^mylivesite\.com$
RewriteRule ^(.*)$ https://www.mylivesite.com/$1 [R=301]
I’m sure better ways exist to do everything I’m trying to do with this but at the end of the day, I’m just trying to make sure that anyone that requests mylivesite.com or www.mylivesite.com gets routed to the appropriate site that exists in the sub-directories they’re installed in. I’m able to bypass doing all this for the “test” site because I assigned it a C-PANEL sub-domain (which allowed me to use C-PANEL to designate which sub-directory the sub-domain should route requests to without needing to do much for it via HTACCESS besides the SSL stuff).
My live site, however, doesn’t use a sub-domain, forcing me to use HTACCESS to designate which sub-directory to route everything to (and to ensure the use of SSL).
Hopefully that makes sense…? But with all this in play, I see the 301 for the first hit in Firebug’s Network tab when the site loads up in the browser, but after that, everything is normal.
There is an HTTP header specifically for what you want, called HTTP Strict Transport Security, or HSTS. You must send this along with any HTTPS response and it will tell the browser it must only ever connect to your site over HTTPS from that moment on, even if the user types HTTP. The browser will then internally redirect to HTTPS without hitting your server.
That does mean though that the very first request will still be over HTTP, nothing to be done about that. But it’s just one request, so the chance of a MITM there is quite slim.
Sounds like I could probably use what I currently have in my HTACCESS but also add the HSTS on top of that. Would that be a good idea to do? If so, I just have to figure out how to send the HSTS thing.
It’s impossible to enforce HTTPS at the very 1st request, right? The only way I see that ever happening is if browser vendors somehow build their browsers to do that…
There is https://hstspreload.org where you can submit your site to be preloaded with HSTS in browsers so the browsers know to redirect to HTTPS even if the visitor has never been to your site yet, but I have never actually tried that so I’m not sure how it works.
And yes you can add it to the .htaccess, although you must take care to send it over HTTPS only, never over HTTP.