Problem with redirecting everything to HTTPS


#1

After installing this wonderful solution (Let’s Encrypt), I got an info, that some changes have been made, because of some loop-errors that might occure later (after the step “Yes, everything should be redirected to HTTPS” or how it’s called). I thought “Nice, LE is great!” (I still do of course). I opened Firefox and et voilá the domain I’m running is HTTPS everywhere now (for www and without www). Well, on Firefox. But not on every Browser:

www.mydomain.tld (with content!)

  • Firefox: www.mydomain.tld and mydomain.tld are redirected correct to HTTPS

  • Chrome: www. is correct, but http://mydomain.tld isn’t - it’s still HTTP, saying Apache is working (without my current content!)

  • Internet Explorer: www. is correct, but http://mydomain.tld isnt - it’s still HTTP but after my first vist on mydomain.tld and www.mydomain.tld, mydomain.tld is magically HTTPS now.

  • Edge: Same as IE

Any ideas for troubleshooting?


Standard force http to https isn't working
#2

It doesn’t seem to be HTTPS everywhere but (just) HSTS, I guess. Once an HSTS capable browser detected that property it won’t load the site on http-only anymore but just with https.

While HSTS is a nice reminder for the browser to never accept http for your server again but replace it with https immediately for any manually entered or referred link, you should also setup your server to enforce any access to your site over port-80-http to port-443-https. Google for “redirect http to https” and add your favourite web server to the query to get easy help how to achieve that.

A proven setup, as done by big players like github, is to host all contents under https://mydomain.tld and let all other variants (non-https, www-prefixed, or both) redirect to that.

• serve content on https://mydomain.tld. Send HSTS header with long duration. Add subdomain and preload features at will.
• accesses to http://mydomain.tld are redirected to https://mydomain.tld
• accesses to http://www.mydomain.tld are redirected to https://mydomain.tld
• accesses to https://www.mydomain.tld are redirected to https://mydomain.tld (requires 2nd certificate – or ASN – for www.mydomain.tld). Send HSTS header, just in case.


#3

Well, I have a .htaccess in my domain-folder which looks like this:

RewriteEngine On

RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^\w+$ index.php?page=$0 [L]
RewriteCond %{THE_REQUEST} index\.php
RewriteCond %{QUERY_STRING} ^page=(\w+)$
RewriteRule ^index\.php$ /%1? [R=301,L]
RewriteRule ^news/(\d+)-([\w-]+)$ index.php?page=single_news&id=$1&headline=$2

At /etc/apache2/sites-enabled/mydomain.tld the mydomain.tld.conf looks like this:

<VirtualHost *:80>

ServerName mydomain.tld
ServerAlias www.mydomain.tld
ServerAdmin webadmin@mydomain.tld
DocumentRoot /var/www/mydomain.tld/public_html

<Directory /var/www/mydomain.tld/public_html>
Options FollowSymLinks
AllowOverride all
Require all granted
</Directory>

ErrorLog ${APACHE_LOG_DIR}/error.log
CustomLog ${APACHE_LOG_DIR}/access.log combined

RewriteEngine on
RewriteRule ^ https://%{SERVER_NAME}%{REQUEST_URI} [END,QSA,R=permanent]
</VirtualHost>

Should I delete the .htaccess and add the stuff into the .conf-file? And is there a collision or s.th. at the Rewrite-Rules? Maybe I have to modify the code of the .htaccess-stuff to be correct with LE?


#4

I’d suggest changing the rewrite rule at the end of the apache conf (http section ) to;

RewriteEngine On
RewriteCond %{HTTPS} off
RewriteRule (.*) https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]


#5

I’d advise to have the VirtualHost make a redirect just to either https://mydomain.tld or https://www.mydomain.tld (the former preferred). My RewriteRule for VirtualHost *:80 for ServerName mydomain.tld with ServerAlias www.mydomain.tld would look like:

RewriteRule ^ https://mydomain.tld%{REQUEST_URI} [END,QSA,R=permanent]

Also, for https a similar RewriteRule should be there for another VirtualHost *:443 with ServerName www.mydomain.tld. Avoid serving your content over both ServerNames. Delete the ServerAlias www.mydomain.tld from your VirtualHost *:443 with ServerName mydomain.tld and add a separate VirtualHost for www.mydomain.tld:

<VirtualHost *:443>

ServerName www.mydomain.tld
//your other SSL stuff just for www.mydomain.tld
//don’t forget a HSTS header

RewriteEngine on
RewriteRule ^ https://mydomain.tld%{REQUEST_URI} [END,QSA,R=permanent]
</VirtualHost>

Remove your .htaccess bloat.


#6

I updated my problems and all files. Maybe someone can help. Status quo:

My goal

Everything results in https://mydomain.tld (non-www and with TLS) and HSTS works correct. I am using the certificates from LE (Let’s Encrypt) and so I used their wizard to make my website HTTPS everywhere. But it doesn’t seem to work correct.

My current problems

  1. Visiting http://mydomain.tld (non-www, non-tls). The result is
    the Apache-status-page, but I already have a website running with
    content. Reloading the page results in https://mydomain.tld with
    website-content. But it should do that from the first vist on and
    not only after reloading the page.
  2. Visiting http://www.mydomain.tld results in
    https://www.mydomain.tld which is okay from TLS-view, but it
    doesn’t redirect to non-www, which is my goal.
  3. Visiting https://www.mydomain.tld resuslts in
    https://www.mydomain.tld. No redirection to non-www.
  4. No problem: Visiting https://mydomain.tld results in the same URL, which is what I want.

DNS-settings:

    A-RECORDS
    .mydomain.tld -> 111.222.333.444
    *.mydomain.tld -> 111.222.333.444
    www.mydomain.tld -> 111.222.333.444

mydomain.tld.conf

    <VirtualHost *:80>
    
    ServerName mydomain.tld
    ServerAlias www.mydomain.tld
    ServerAdmin contact@mydomain.tld
    DocumentRoot /var/www/mydomain.tld/public_html
    Redirect permanent / https://mydomain.tld/
    
    <Directory /var/www/mydomain.tld/public_html>
    Options FollowSymLinks
    AllowOverride all
    Require all granted
    </Directory>
    
    ErrorLog ${APACHE_LOG_DIR}/error.log
    CustomLog ${APACHE_LOG_DIR}/access.log combined
    
    RewriteEngine On
    RewriteCond %{HTTPS} off
    RewriteRule (.*) https://%{SERVER_NAME}/%$1 [R,L]
    </VirtualHost>

mydomain.tld-le-ssl.conf

    <IfModule mod_ssl.c>
    <VirtualHost *:443>
            ServerName www.mydomain.tld
            ServerAlias mydomain.tld
            ServerAdmin contact@mydomain.tld
            DocumentRoot /var/www/mydomain.tld/public_html
    
            <Directory /var/www/mydomain.tld/public_html>
            Options FollowSymLinks
            AllowOverride all
            Require all granted
            </Directory>
    
            ErrorLog ${APACHE_LOG_DIR}/error.log
            CustomLog ${APACHE_LOG_DIR}/access.log combined
    
    Header always set Strict-Transport-Security "max-age=63072000; includeSubdomains; preload"
    
    RewriteEngine on
    SSLCertificateFile /etc/letsencrypt/live/mydomain.tld/fullchain.pem
    SSLCertificateKeyFile /etc/letsencrypt/live/mydomain.tld/privkey.pem
    Include /etc/letsencrypt/options-ssl-apache.conf
    
    </VirtualHost>
    </IfModule>

As you can see above in the mydomain.tld-le-ssl.conf another file is included, which might doesn’t make problems, but just for the records:

options-ssl-apache.conf

    # Baseline setting to Include for SSL sites
    
    SSLEngine on
    
    # Intermediate configuration, tweak to your needs
    SSLProtocol             all -SSLv2 -SSLv3
    SSLCipherSuite          ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384:DHE-RSA$
    SSLHonorCipherOrder     on
    SSLCompression          off
    
    SSLOptions +StrictRequire
    
    # Add vhost name to log entries:
    LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-agent}i\"" vhost_combined
    LogFormat "%v %h %l %u %t \"%r\" %>s %b" vhost_common
    
    #CustomLog /var/log/apache2/access.log vhost_combined
    #LogLevel warn
    #ErrorLog /var/log/apache2/error.log
    
    # Always ensure Cookies have "Secure" set (JAH 2012/1)
    #Header edit Set-Cookie (?i)^(.*)(;\s*secure)??((\s*;)?(.*)) "$1; Secure$3$4"

Bonus-problem

I have a .htaccess-file in my domain-root which makes the links look better:

  • without: https://mydomain.tld/index.php?page=news
  • with: https://mydomain.tld/news

.htaccess

    RewriteEngine On
    
    RewriteCond %{REQUEST_FILENAME} !-f
    RewriteCond %{REQUEST_FILENAME} !-d
    RewriteRule ^\w+$ index.php?page=$0 [L]
    RewriteCond %{THE_REQUEST} index\.php
    RewriteCond %{QUERY_STRING} ^page=(\w+)$
    RewriteRule ^index\.php$ /%1? [R=301,L]

I would like to live without the .htaccess-file and add the stuff to the .conf-file(s) if possible, but everything I did, didn’t work yet.


#7

I don’t see any redirect in mydomain.tld-le-ssl.conf - so if someone hits https://www.mydomain.tld they won’t get redirected to https://mydomain.tld - you need to add a redirect there if you want that to happen, for example using mod_rewrite:

RewriteCond %{HTTP_HOST} ^www\.(.+)$ [NC]
RewriteRule ^ https://%1%{REQUEST_URI} [L,R=301]

The reason http://www.mydomain.tld isn’t redirecting as expected may be because your HSTS rule is kicking in first, so the browser directly requests https://www.mydomain.tld instead and you then run into the same problem as above. (I’d suggest getting all the redirects working correctly before enabling HSTS, it’ll only complicate things otherwise).

As to why http://mydomain.tld doesn’t redirect the first time, I dunno. Sounds like a cache problem.


#8

It works now. Thank you very much!

This stuff for Port 80 is correct?

RewriteEngine On
RewriteCond %{HTTPS} off
RewriteRule (.*) https://%{SERVER_NAME}/%$1 [R,L]

If anyone has an idea, how I have to add the stuff from my .htaccess into a .conf-file, I’d love to hear that.

EDIT:

I got it.

I added the .htaccess-stuff into the mydomain.tld-le-ssl.conf between the <directory>-tags:

...
<Directory /var/www/mydomain.tld/public_html>
Options FollowSymLinks
AllowOverride all
Require all granted

RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^\w+$ index.php?page=$0 [L]
RewriteCond %{THE_REQUEST} index\.php
RewriteCond %{QUERY_STRING} ^page=(\w+)$
RewriteRule ^index\.php$ /%1? [R=301,L]
</Directory>
...

#10

It’s weird. Yesterday I created new certs and it still worked. Today:

Chrome (mobile): http://mydomain.tld redirects correct to https://mydomain.tld
Firefox (desktop): http://mydomain.tld doesn’t redirect and results in Apache-page

Firefox (mobile) which never was on my website: Same as Firefox (desktop)
Safari (mobile) which never was on my website: Same as Firefox (desktop)

So, it seems there is still a problem.

In mydomain.tld.conf (for Port 80) there are two lines that might do the same?

...
Redirect permanent / https://mydomain.tld/
...
RewriteCond %{HTTPS} off
RewriteRule (.*) https://%{SERVER_NAME}/%$1 [R,L]
...

Edit: I did a2dissite 000-default.conf and now it redirects again nearly correct. Now the redirect results in https://mydomain.tld/%25/. A new problem…

EDIT 2:

Solution for this problem:

  • $ sudo a2dissite 000-default.conf

  • Remove the stuff below in mydomain.tld.conf:

RewriteEngine On RewriteCond %{HTTPS} off RewriteRule (.*) https://%{SERVER_NAME}/%$1 [R,L] RewriteRule ^ https://%{SERVER_NAME}%{REQUEST_URI} [END,QSA,R=permanent]

Just use: Redirect permanent / https://mydomain.tld

  • $sudo /etc/init.d/apache2 restart

Final files

mydomain.tld.conf

    <VirtualHost *:80>
    
    ServerName mydomain.tld
    ServerAlias www.mydomain.tld
    ServerAdmin contact@mydomain.tld
    DocumentRoot /var/www/mydomain.tld/public_html
    Redirect permanent / https://mydomain.tld
    
    <Directory /var/www/mydomain.tld/public_html>
    Options FollowSymLinks
    AllowOverride all
    Require all granted
    </Directory>
    
    ErrorLog ${APACHE_LOG_DIR}/error.log
    CustomLog ${APACHE_LOG_DIR}/access.log combined
    </VirtualHost>

mydomain.tld-le-ssl.conf

    LoadModule headers_module modules/mod_headers.so
    
    <IfModule mod_ssl.c>
    <VirtualHost *:443>
    Header always set Strict-Transport-Security "max-age=63072000; includeSubdomain$
    
    ServerName mydomain.tld
    ServerAlias www.mydomain.tld
    ServerAdmin contact@nmydomain.tld
    DocumentRoot /var/www/mydomain.tld/public_html
    
    <Directory /var/www/mydomain.tld/public_html>
    Options FollowSymLinks
    AllowOverride all
    Require all granted
    
    RewriteEngine On
    RewriteCond %{REQUEST_FILENAME} !-f
    RewriteCond %{REQUEST_FILENAME} !-d
    RewriteRule ^\w+$ index.php?page=$0 [L]
    RewriteCond %{THE_REQUEST} index\.php
    RewriteCond %{QUERY_STRING} ^page=(\w+)$
    RewriteRule ^index\.php$ /%1? [R=301,L]
    
    </Directory>
    
    ErrorLog ${APACHE_LOG_DIR}/error.log
    CustomLog ${APACHE_LOG_DIR}/access.log combined
    
    RewriteEngine on
    SSLCertificateFile /etc/letsencrypt/live/mydomain.tld/fullchain.pem
    SSLCertificateKeyFile /etc/letsencrypt/live/mydomain.tld/privkey.pem
    Include /etc/letsencrypt/options-ssl-apache.conf
    
    RewriteCond %{HTTP_HOST} ^www\.(.+)$ [NC]
    RewriteRule ^ https://%1%{REQUEST_URI} [L,R=301]
    </VirtualHost>
    </IfModule>