How to ensure that Apache always serves a single page via HTTPS? - apache

I would like to redirect all connections from htt_p://www.example.com/abc.html to HTTP_S://www.example.com/abc.html . What mod_alias or mod_rewrite commands would work for this? I've tried:
RewriteEngine on
RewriteCond %{HTTPS} =off
RewriteRule $abc\.html^ https://www.example.com/abc.html [R]
in both .htaccess and httpd.conf but that doesn't work. It works if the first string in the RewriteRule is anything else (like abz.html) but not if it is abc.html. abc.html is a real file on the server (not another redirect). Options FollowSymlinks is present in the appropriate Directory directive.
Many thanks.

Something along the lines of the following will allow you to redirect non-SSL pages to SSL versions (assuming that you are running SSL on port 443):
RewriteEngine on
# Limited redirects
RewriteCond %{SERVER_PORT} !^443$
RewriteCond %{REQUEST_URI} ^/abc\.html$ [OR,NC]
RewriteCond %{REQUEST_URI} ^/def\.html$ [OR,NC]
RewriteCond %{REQUEST_URI} ^/ghi\.html$ [NC]
RewriteRule ^/(.*)$ https://%{HTTP_HOST}/$1 [R=301,L]
The [OR] flag after the RewriteCond is literally that, "or", which is why the last condition doesn't have it

Related

How can I direct all folders on my website to use HTTPS in .htaccess?

Please be kind, this is my first question on here :)
My Setup
Apache served on my Raspberry Pi 4
My .htaccess file
# Force HTTPS on all pages
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteCond %{HTTPS} !on
RewriteRule (.*) https://%{HTTP_HOST}%{REQUEST_URI} [R=301,L]
</IfModule>
The Problem
Typing in "tyler.cloud" successfully redirects to https://www.tyler.cloud, but typing in "tyler.cloud/react" stays at http://tyler.cloud/react (not HTTPS).
What I've tried in addition to above with the same results
RewriteEngine on
RewriteCond %{SERVER_PORT} 80
RewriteRule ^(.*)$ https://%{SERVER_NAME}%{REQUEST_URI} [R=301,L]
and
RewriteEngine On
RewriteCond %{HTTPS} !on
RewriteRule (.*) https://%{HTTP_HOST}%{REQUEST_URI}
and a few other variations.
It turns out "AllowOverride" in /var/www has to be "All" in /etc/apache2/apache2.conf.
It was set to "None", and that means it ignored all of my .htaccess files.
I used this:
RewriteEngine On
RewriteCond %{HTTPS} !on
RewriteRule (.*) https://%{HTTP_HOST}%{REQUEST_URI}
and it seems to work!
Consider using apache2.conf instead of .htaccess. Because using .htaccess in a server where you have root access is a bad idea. It can slow your website down unnecessarily.
Try using this instead of .htaccess:
<Directory "/path/to/web/directory">
RewriteEngine On
RewriteCond %{HTTPS} !on
RewriteRule (.*) https://%{HTTP_HOST}%{REQUEST_URI}
</Directory>
And if you are using VirtualHosts, add:
RewriteEngine On
RewriteOptions Inherit
inside the virtualhost.
And also, if someone points their domain to your IP address, then they will be able to show your website through their IP address (unless you are using Name based virtual hosting i.e. https://httpd.apache.org/docs/2.4/vhosts/name-based.html, but still they will be able to access your main Apache host with the IP address of course). Although because you are using HTTPS, their domain probably will fail HTTPS. But, because you do not have HSTS (https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Strict-Transport-Security) set up, users can still access the website.
So, I would also suggest you to redirect to your domain if the domain doesn't match https://www.tyler.cloud, using the following: (add the following to inside <Directory> directive)
(If you are planning to add HSTS preload see the next solution please)
#Do not use RewriteEngine On more than once. see the next solution if you are planning to use HSTS preload
RewriteCond %{HTTP_HOST} !^www\.tyler\.cloud [OR]
RewriteCond %{HTTPS} !=on
RewriteRule ^ https://www\.tyler\.cloud%{REQUEST_URI} [R=301,L]
Use the next solution if planning to use HSTS preload:
RewriteCond %{HTTP_HOST} ^tyler\.cloud
RewriteCond %{HTTPS} !=on
RewriteRule ^ https://tyler\.c%{REQUEST_URI} [R=301,L]
RewriteCond %{HTTP_HOST} !^www\.tyler\.cloud [OR]
RewriteCond %{HTTPS} !=on
RewriteRule ^ https://www\.tyler\.cloud%{REQUEST_URI} [R=301,L]
And you are good to go!

Suppressing www hostname and forcing HTTPS in .htaccess

I‘m trying to force my website to load via https:// and supressing the www. hostname in my .htaccess file located in the topmost public directory.
mod_rewrite is on. I know that this is easily possible in PHP but I’m trying to do this in my .htaccess file.
Here is my approach:
<IfModule mod_rewrite.c>
RewriteEngine on
RewriteCond %{SERVER_PORT} ^443$
RewriteCond %{HTTP_HOST} ^(www\.)(.+)$ [NC,OR]
RewriteCond %{SERVER_PORT} !^443$
RewriteCond %{HTTP_HOST} ^(www\.)?(.+)$ [NC]
RewriteRule ^ https://%2%{REQUEST_URI} [R=301,L]
</IfModule>
This works in Google Chrome (37.0.2062.124) what kinda surprises me since I thought the whole process is handled on the server side and should behave the same way on the client side.
I have also tried to use %{HTTPS} =off and %{HTTPS} !=on instead of checking the port.

htaccess redirect to https://www

I have the following htaccess code:
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteCond !{HTTPS} off
RewriteRule ^(.*)$ https://www.%{HTTP_HOST}%{REQUEST_URI} [L,R=301]
RewriteCond %{HTTP_HOST} !^www\.
RewriteRule ^(.*)$ https://www.%{HTTP_HOST}%{REQUEST_URI} [L,R=301]
</IfModule>
I want my site to be redirected to https://www. with HTTPS, and enforcing the www. subdomain,
but when I access http://www. (without HTTPS), it does not redirect me to https://www with HTTPS.
To first force HTTPS, you must check the correct environment variable %{HTTPS} off, but your rule above then prepends the www. Since you have a second rule to enforce www., don't use it in the first rule.
RewriteEngine On
RewriteCond %{HTTPS} off
# First rewrite to HTTPS:
# Don't put www. here. If it is already there it will be included, if not
# the subsequent rule will catch it.
RewriteRule .* https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]
# Now, rewrite any request to the wrong domain to use www.
# [NC] is a case-insensitive match
RewriteCond %{HTTP_HOST} !^www\. [NC]
RewriteRule .* https://www.%{HTTP_HOST}%{REQUEST_URI} [L,R=301]
About proxying
When behind some forms of proxying, whereby the client is connecting via HTTPS to a proxy, load balancer, Passenger application, etc., the %{HTTPS} variable may never be on and cause a rewrite loop. This is because your application is actually receiving plain HTTP traffic even though the client and the proxy/load balancer are using HTTPS. In these cases, check the X-Forwarded-Proto header instead of the %{HTTPS} variable. This answer shows the appropriate process
Michals answer worked for me, albeit with one small modification:
Problem:
when you have a single site security certificate, a browser that tries to access your page without https:// www. (or whichever domain your certificate covers) will display an ugly red warning screen before it even gets to receive the redirect to the safe and correct https page.
Solution
First use the redirect to the www (or whichever domain is covered by your certificate) and only then do the https redirect. This will ensure that your users are not confronted with any error because your browser sees a certificate that doesn't cover the current url.
#First rewrite any request to the wrong domain to use the correct one (here www.)
RewriteCond %{HTTP_HOST} !^www\.
RewriteRule ^(.*)$ https://www.%{HTTP_HOST}%{REQUEST_URI} [L,R=301]
#Now, rewrite to HTTPS:
RewriteCond %{HTTPS} off
RewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]
If you are using CloudFlare or a similar CDN you will get an infinite loop error with the %{HTTPS} solutions provided here. If you're a CloudFlare user you'll need to use this:
RewriteEngine On
RewriteCond %{HTTP:X-Forwarded-Proto} =http
RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]
BAD SOLUTION AND WHY!
Don't ever use the solution below because when you are using their code that is something like:
RewriteCond %{HTTPS} off
RewriteRule .* https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]
RewriteCond %{HTTP_HOST} !^www\. [NC]
RewriteRule .* https://www.example.com%{REQUEST_URI} [L,R=301]
The browser goes to:
http://example.com
Then redirects to:
https://example.com
Then redirects to:
https://www.example.com
This is too much request to the server.
Most of the answers even accepted one has this problem.
BEST SOLUTION AND THE ANSWER
This code has an [OR] condition to prevent dual changes at url!
RewriteEngine on
RewriteCond %{HTTPS} off [OR]
RewriteCond %{HTTP_HOST} !^www\. [NC]
RewriteRule (.*) https://www.example.com%{REQUEST_URI} [R=301,L]
This is the best way I found for Proxy and not proxy users
RewriteEngine On
### START WWW & HTTPS
# ensure www.
RewriteCond %{HTTP_HOST} !^www\. [NC]
RewriteRule ^ https://www.%{HTTP_HOST}%{REQUEST_URI} [L,R=301]
# ensure https
RewriteCond %{HTTP:X-Forwarded-Proto} !https
RewriteCond %{HTTPS} off
RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]
### END WWW & HTTPS
There are a lot of solutions out there. Here is a link to the apache wiki which deals with this issue directly.
http://wiki.apache.org/httpd/RewriteHTTPToHTTPS
RewriteEngine On
# This will enable the Rewrite capabilities
RewriteCond %{HTTPS} !=on
# This checks to make sure the connection is not already HTTPS
RewriteRule ^/?(.*) https://%{SERVER_NAME}/$1 [R,L]
# This rule will redirect users from their original location, to the same location but using HTTPS.
# i.e. http://www.example.com/foo/ to https://www.example.com/foo/
# The leading slash is made optional so that this will work either in httpd.conf
# or .htaccess context
To redirect http:// or https:// to https://www you can use the following rule on all versions of apache :
RewriteEngine on
RewriteCond %{HTTPS} off [OR]
RewriteCond %{HTTP_HOST} !^www\.
RewriteRule ^ https://www.example.com%{REQUEST_URI} [NE,L,R]
Apache 2.4
RewriteEngine on
RewriteCond %{REQUEST_SCHEME} http [OR]
RewriteCond %{HTTP_HOST} !^www\.
RewriteRule ^ https://www.example.com%{REQUEST_URI} [NE,L,R]
Note that The %{REQUEST_SCHEME} variable is available for use since apache 2.4 .
If you are on CloudFlare, make sure you use something like this.
# BEGIN SSL Redirect
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteCond %{HTTP:X-Forwarded-Proto} =http
RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]
</IfModule>
# END SSL Redirect
This will save you from the redirect loop and will redirect your site to SSL safely.
P.S. It is a good idea to if check the mod_rewrite.c!
RewriteEngine On
RewriteCond %{SERVER_PORT} 80
RewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI} [L,R]
RewriteEngine On
RewriteCond %{HTTP_HOST} !^www.
RewriteRule ^(.*)$ https://www.%{HTTP_HOST}/$1 [R=301,L]
Notes: Make sure you have done the following steps
sudo a2enmod rewrite
sudo service apache2 restart
Add Following in your vhost file, located at /etc/apache2/sites-available/000-default.conf
<Directory /var/www/html>
Options Indexes FollowSymLinks MultiViews
AllowOverride All
Order allow,deny
allow from all
Require all granted
</Directory>
Now your .htaccess will
work and your site will redirect to http:// to https://www
Similar to Amir Forsati's solution htaccess redirect to https://www but for variable domain name, I suggest:
RewriteEngine on
RewriteCond %{HTTPS} off [OR]
RewriteCond %{HTTP_HOST} !^www\. [NC]
RewriteCond %{HTTP_HOST} ^(www\.)?(.+)$ [NC]
RewriteRule ^ https://www.%2%{REQUEST_URI} [R=301,L]
Set in your .htaccess file
RewriteEngine On
RewriteCond %{HTTP_HOST} !^www.
RewriteRule ^(.*)$ https://www.%{HTTP_HOST}/$1 [R=301,L]
RewriteCond %{HTTPS} !=on
RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]
I used the below code from this website, it works great https://www.freecodecamp.org/news/how-to-redirect-http-to-https-using-htaccess/
RewriteEngine On
RewriteCond %{SERVER_PORT} 80
RewriteRule ^(.*)$ https://www.yourdomain.com/$1 [R,L]
Hope it helps
I try first answer and it doesnt work...
This work:
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /
RewriteCond %{ENV:HTTPS} !=on
RewriteRule ^.*$ https://%{SERVER_NAME}%{REQUEST_URI} [R,L]
# BEGIN WordPress
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /
RewriteRule ^index\.php$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.php [L]
</IfModule>
# END WordPress

Endless loop when rewriting to https

I recently bought a wildcard ssl certificate to move my site to https.
Since Apache can't handle multiple Virtual hosts, under the same IP, in separate s, I was forced to use VirtualDocumentRoot from mod_vhost_alias. This at first solved my problems with Apache and the wildcard certificate, but it was not for long.
For a matter of necessity, I decided to move the homepage of my site to the root of the domain (ie, http://domain.com, instead of http://www.domain.com). Once I moved, the rules I established to move to https cause an endless loop on the server, resulting in an error 500. Note that the same rules when applied to any sub-domain still works, rewriting any http to https.
The error:
Request exceeded the limit of 10 internal redirects due to probable configuration error. Use 'LimitInternalRecursion' to increase the limit if necessary.
My VirtualHost config:
<VirtualHost IP:443>
...
VirtualDocumentRoot /.../public_html/%1/
...
VirtualScriptAlias /.../public_html/%1/cgi-bin/
...
</VirtualHost>
My .htaccess config:
SetEnv APPLICATION_ENV development
Options +FollowSymlinks -Indexes
RewriteEngine On
RewriteCond %{HTTP_HOST} ^www.domain.com [NC,OR]
RewriteCond %{HTTP_HOST} ^domain.com [NC]
RewriteCond %{SERVER_PORT} !443
RewriteRule ^(.*)$ https://domain.com/$1 [L,R=301]
RewriteCond %{REQUEST_FILENAME} -s [OR]
RewriteCond %{REQUEST_FILENAME} -l [OR]
RewriteCond %{REQUEST_FILENAME} -d
RewriteRule ^(.*)$ - [NC,L]
RewriteRule ^(.*)$ index.php [NC,L]
<FilesMatch "\\.(js|css)$">
SetOutputFilter DEFLATE
</FilesMatch>
My application was build using the Zend Framework.
The main mystery here is why does it work with any sub-domain, but does not when I'm using the root sub-domain. Any hint in what can be causing the problem? Is there any way I can see all the rewrites de .htacess does?
Try this:
RewriteEngine On
RewriteCond %{HTTP_HOST} ^(www\.)?domain\.com$ [NC]
RewriteCond %{HTTPS} !on
RewriteRule (.*) https://%{HTTP_HOST}/$1 [L,R=301]
RewriteCond %{REQUEST_FILENAME} !-s
RewriteCond %{REQUEST_FILENAME} !-l
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule (.*) index.php [L]
Changes:
www.domain.com and domain.com could be matched in one line, so did it
check for HTTPS instead of SERVER_PORT
redirect to HTTPT on same domain name as requested (change if you want all to point to one name).
instead of making a rule that would "kill" rewriting, with 3 RewriteCond's in OR, negated the cond's to apply to the real rule in question
there is no point of setting NC flag when matching .*
The rest of the .htaccess should stay the same (did not include those parts).

generic non-www to www, and non-http to https

I have the following code for my .htaccess file that I've picked up from here and tried adapting it as I understand from .htaccess, yet I can't seem to get it to work (or maybe the browser has cached it but I can't seem to clear it).
Options -Indexes
Options +FollowSymlinks
<IfModule mod_rewrite.c>
########## FORCE SSL ##########
RewriteEngine On
RewriteBase /
# Non-secure requests to www.domain.com should redirect to https://www.domain.com
RewriteCond %{HTTPS} off
RewriteCond %{HTTP_HOST} ^www\.%{HTTP_HOST} [NC]
RewriteRule ^(.*)$ https://www\.%{HTTP_HOST}%{REQUEST_URI} [L,R=301]
# All secure (HTTPS) traffic should redirect to https://www.domain.com
RewriteCond %{HTTPS} on
RewriteCond %{HTTP_HOST} !^www\.%{HTTP_HOST} [NC]
RewriteRule ^(.*)$ https://www\.%{HTTP_HOST}/$1 [L,R=301]
</IfModule>
I want to make it as generic a possible so I can simply copy and paste it to any site I make so no need to edit it each time - I guess I could also do this in PHP but I think it would be good if .htaccess is also there.
Another point is, can .htaccess be read if i were to go to www.domain.com/.htaccess or do I need to cover that in a 'deny all' kind of thing?
The second argument to the RewriteCond must be a regex, so it cannot contain a variable.
Try adding the following to your .htaccess file in place of the rules you had
#capture top level domain (.com or .co.uk)
RewriteCond %{HTTP_HOST} ([-_a-zA-Z0-9]+\.([a-zA-Z]{2,5}|co\.uk))$ [NC]
RewriteCond %{HTTP_HOST} (www\.)?(.+)$ [NC]
RewriteRule ^ - [E=MY_TLD:%2]
# Non-secure requests to www.domain.com should redirect to https://www.domain.com
RewriteCond %{HTTPS} off
RewriteRule ^ https://www\.%{ENV:MY_TLD}%{REQUEST_URI} [L,R=301]
# All secure (HTTPS) traffic should redirect to https://www.domain.com
RewriteCond %{HTTPS} on
#if host does not start with www
RewriteCond %{HTTP_HOST} !^www\.[-_a-zA-Z0-9]+\.([a-zA-Z]{2,5}|co\.uk)$ [NC]
RewriteRule ^ https://www\.%{ENV:MY_TLD}%{REQUEST_URI} [L,R=301]
Shortest version would be:
RewriteEngine On
RewriteBase /
RewriteCond %{HTTPS} off [OR]
RewriteCond %{HTTP_HOST} !^www\.
RewriteCond %{HTTP_HOST} (www\.)?(.+)$ [NC]
RewriteRule ^ https://www\.%2%{REQUEST_URI} [L,R=301]
Only (somewhat) downside would be that subdomain.example.com gets redirected to www.subdomain.example.com