Connection is not private while redirecting HTTPS to HTTP [duplicate] - apache

I'm trying to redirect https://www.example.com to http://www.example.com. I tried the following code in the .htaccess file
RewriteEngine On
RewriteCond %{HTTP_HOST} ^example\.com$ [NC]
RewriteRule ^(.*)$ http://www.example.com/$1 [R=301,L]
This code successfully redirects https://example.com to http://www.example.com. However when I type in https://www.example.com then it gives me a "web page not available" error in the browser.
I have also tried the following 2 codes without success
Attempt 1
RewriteEngine On
RewriteCond %{HTTPS} !=on
RewriteRule ^/(.*):NOSSL$ http://www.example.com/$1 [R=301,L]
Attempt 2
RewriteEngine On
RewriteCond %{HTTPS} on
RewriteRule (.*) http://%{HTTP_HOST}%{REQUEST_URI}
Both above attempts failed. Any suggestions?

Attempt 2 was close to perfect. Just modify it slightly:
RewriteEngine On
RewriteCond %{HTTPS} on
RewriteRule (.*) http://%{HTTP_HOST}%{REQUEST_URI} [R=301,L]
UPDATE:
Above solution works from a technical point of view. BUT:
Since a few years now the user will receive a huge warning indicating that the connection is not private. That is to be expected: none of today's browsers will silently switch from an encrypted to a not encrypted connection, for obvious reasons ... You cannot get around that behavior of standard browsers. That however has nothing to do with the redirection itself. It is how the web works today, how users are protected from criminal intents.

However, if your website does not have a security certificate, it's on a shared hosting environment, and you don't want to get the "warning" when your website is being requested through https, you can't redirect it using htaccess. The reason is that the warning message gets triggered before the request even goes through to the htaccess file, so you have to fix it on the server. Go to /etc/httpd/conf.d/ssl.conf and comment out the part about the virtual server 443. But the odds are that your hosting provider won't give you that much control. So you would have to either move to a different host or buy the SSL just so the warning does not trigger before your htaccess has a chance to redirect.

You can use the following rule to redirect from https to http :
RewriteEngine On
RewriteCond %{HTTPS} ^on$
RewriteRule ^(.*)$ http://example.com/$1 [NC,L,R]
Explanation :
RewriteCond %{HTTPS} ^on$
Checks if the HTTPS is on (Request is made using https)
Then
RewriteRule ^(.*)$ http://example.com/$1 [NC,L,R]
Redirect any request (https://example.com/foo)
to http://example.com/foo .
$1 is part of the regex in RewriteRule pattern, it contains whatever value was captured in (.+) , in this case ,it captures the full request_uri everything after the domain name.
[NC,L,R] are the flags, NC makes the uri case senstive, you can use both uppercase or lowercase letters in the request.
L flag tells the server to stop proccessing other rules if the currunt rule has matched, it is important to use the L flag to avoid rule confliction when you have more then on rules in a block.
R flag is used to make an external redirection.

RewriteEngine On
RewriteCond %{SERVER_PORT} 443
RewriteRule (.*) http://%{HTTP_HOST}%{REQUEST_URI} [R=301,L]

The difference between http and https is that https requests are sent over an ssl-encrypted connection. The ssl-encrypted connection must be established between the browser and the server before the browser sends the http request.
Https requests are in fact http requests that are sent over an ssl encrypted connection. If the server rejects to establish an ssl encrypted connection then the browser will have no connection to send the request over. The browser and the server will have no way of talking to each other. The browser will not be able to send the url that it wants to access and the server will not be able to respond with a redirect to another url.
So this is not possible. If you want to respond to https links, then you need an ssl certificate.

RewriteCond %{HTTP:X-Forwarded-Proto} =https

Your code is correct. Just put them inside the <VirtualHost *:443>
Example:
<VirtualHost *:443>
SSLEnable
RewriteEngine On
RewriteCond %{HTTPS} on
RewriteRule (.*) http://%{HTTP_HOST}%{REQUEST_URI}
</VirtualHost>

Related

Why is the htaccess in my subdomain folder overriding aspects of the htaccess in my main domain?

Let me explain my setup here, I have two domains, for the sake of naming them lets call them domain1.com and domain2.com. I have shared hosting that runs cPanel.
Domain1.com is my main domain, and is what I have my hosting account setup using. I have a website hosted at that domain. Domain2.com is set as an add-on domain, and directs to a folder inside of the main domains root. That has it's own website (a Ghost blog).
That all works fine. However the websites hosted at the two domains are quite different and I did not want the subdomain to work, but as far as I can tell add-on domains in cPanel have to have a subdomain in order to be added to the account. The redirect options for the subdomains in cPanel aren't good enough for me, as I wanted anyone accessing say domain1.com/domain2 to get a 404 error as if it didn't exist. So I set up the .htaccess file for domain1.com to look like this:
RewriteEngine On
#301 (permenant) redirects all HTTP requests to HTTPS (SSL)
RewriteCond %{HTTPS} !on
RewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]
#404 redirects all domain.com/subdomain requests
RewriteCond %{HTTP_HOST} ^(www.)?domain1.com$ [NC]
RewriteCond %{REQUEST_URI} ^/domain2/(.*)$
RewriteRule ^(.*)$ - [L,R=404]
#404 redirects all subdomain.domain.com & www.subdomain.domain.com requests
RewriteCond %{HTTP_HOST} ^domain2.domain1.co.uk$ [OR]
RewriteCond %{HTTP_HOST} ^www.domain2.domain1.co.uk$ [OR]
RewriteCond %{REQUEST_URI} ^/$
RewriteRule ^(.*)$ - [L,R=404]
This worked perfectly, anyone tryting to access domain2 via domain1 would get a 404 error. But that was before I installed Ghost on domain2 After getting Ghost installed I created an .htaccess file in the domain2 folder inside of domain1's root.I had to put this in it in order for Ghost for to run, as it uses NodeJS:
RewriteEngine on
RewriteRule ^(.*)$ http://127.0.0.1:55555555/$1 [P,L]
This also works perfectly except for one aspect. Now all requests to the domain using domain1.com have started working again. For example if I type domain2.domain1.com it will now show me the Ghost blog where as before it was correctly displaying a 404 Not Found error. Why is this and how do I go about rectifying this issue?
As a side note, I also started trying to have all http requests redirect to https. I added the following to the domain1.com htaccess file as I wanted all requests on both domains to redirect to https and I assumed this was necessary:
RewriteCond %{HTTPS} !on
RewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]
Now this kind of works. All requests, whatever they are (with or without www for instance), redirect to https, and when I visit it in my browser I get a green the icon indicating it's secured with SSL. Again even with this the previous issue of the domain redirect still doesn't work. But I have another odd issue here.
If I type in my browser simply "domain1.com" (ie without https:// or www. or a combination of the two), it will show just "domain1.com" in the address bar but with the green icon and say it is secured. If however I type in "domain2.com" (again with no https:// or www etc.) it does the same thing except it states it is not secure, suggesting it requested http.
And yet if I type in www.domain2.com or http://domain2.com, that works and I get the secured icon. It is highly puzzling. It seems that the https redirect works on every request except for just "domain2.com" while any other variation (www.domain2.com, http://domain2.com etc) works fine. Any clues? I mean clearly I've done something wrong with the htaccess files but I don't know what, I got most of what I'd put in them from searching sites like Stackexchange, but personally I don't really know anything about them or how they work.
I think I have fixed my own problem here.
I corrected the main htaccess so the https redirect acts like this;
RewriteCond %{HTTP:X-Forwarded-Proto} !https
RewriteCond %{HTTPS} off
RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]
From what I can tell it's better to do it this way than the way I had it previously. This in itself didn't fix the problems. What fixed it for me is editing the domain2.com htaccess to look like this:
RewriteEngine on
#Force WWW if it isn't in the request
RewriteCond %{HTTP_HOST} !^www\. [NC,OR]
#Or include WWW even if it is in the request
RewriteCond %{HTTP_HOST} ^www\. [NC]
#Then Force it to use https
RewriteRule .* https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]
#Defines this domain so main htaccess rules for subdomains work
RewriteCond %{HTTP_HOST} ^(.*)?domain2.com$ [NC]
#Proxy for Ghost
RewriteRule ^(.*)$ http://127.0.0.1:55555555/$1 [P,L]
Now everything works. All requests are redirected to https. All requests to the subdomain from the main domain fail with a 404. domain2.com now redirects to https://www.domain2.com or https://domain2.com so it is now always secured by SSL. I'm a novice at htaccess as is probably evident and I've no doubt some or all of this could have unnecessary elements removed or simplified so if anyone wants to correct my syntax so it's less messy I'd appreciate it.

.htaccess redirecting URL but not content for subdomain

I'm trying to set up a test site but having real trouble getting .htaccess to redirect properly.
I want the contents of www.example.com/test to show when a user types in test.example.com. My rewrite rules allow me to use test.example.com in the address bar, but it's actually showing me the content of the root (www.example.com), not the test subfolder.
I'm not an .htaccess guru by any stretch, but I've been using Stack Overflow for 5 years and this is the first time I've been stumped enough to ask a question! Your collective wisdom is appreciated.
Here's the relevant part of my .htaccess code:
RewriteEngine On
# Rewrite for http cases
RewriteCond %{HTTPS} off
RewriteRule (.*) https://%{HTTP_HOST}%{REQUEST_URI} [L]
# Rewrite for no www cases
RewriteCond %{HTTP_HOST} !www\.example\.com [NC]
#redirect for test subdomain
RewriteCond %{HTTP_HOST} !^test\.example\.com$ [NC]
RewriteRule ^(.*)$ https://www.example.com/$1 [R=301,L]
# redirect to correct for old subfolder usage
RewriteRule ^oldsubfolder/$ https://www.example.com/ [L,R=301]
I want the contents of www.example.com/test to show when a user types in test.site.com.
I assume you just have one domain and test.site.com should really be test.example.com (which would seem to be consistent with the rest of your question)?
In the code you've posted, there's nothing that really attempts to do this redirect? In the code you've posted, a request for test.example.com would not be redirected - so if it is then you may be seeing a cached response. Clear your browser cache.
You would need something like:
RewriteCond %{HTTP_HOST} ^(?:www\.)?(test)\.example\.com [NC]
RewriteRule (.*) http://www.example.com/%1/$1 [R,L]
The (?:www\.)? part simply catches an optional www subdomain of the subdomain! Depending on how this subdomain was created, both test.example.com and www.test.example.com might be accessible. (Although I suspect your SSL cert probably doesn't allow this anyway?)
%1 is a backreference to the captured group in the CondPattern (ie. test) and $1 is a backreference to the captured RewriteRule pattern. Capturing the subdomain (eg. "test") just avoids repetition, but also allows for more than one subdomain to be handled by the same rule.
This is also a temporary (302) redirect. Change this to a 301 only when you are sure it's working (if that is the intention). 301s are cached by default, so can make testing problematic.
Clear your browser cache before testing.
# Rewrite for no www cases
RewriteCond %{HTTP_HOST} !www\.example\.com [NC]
#redirect for test subdomain
RewriteCond %{HTTP_HOST} !^test\.example\.com$ [NC]
RewriteRule ^(.*)$ https://www.example.com/$1 [R=301,L]
The comment in the middle of this block would seem to be misleading (it doesn't "redirect for test subdomain"). The whole block just redirects to www, excluding the test subdomain. The other code then redirects the subdomain.
UPDATE:
I was hoping it would continue to show test.example.com in the address bar
Yes, this is possible. Providing test.example.com and www.example.com point to the same filesystem then you can simply rewrite the request without actually changing the host. For this example, I'll assume test.example.com and www.example.com point to the same document root.
Change the above redirect to the following rewrite:
RewriteCond %{ENV:REDIRECT_STATUS} ^$
RewriteCond %{HTTP_HOST} ^(?:www\.)?(test)\.example\.com [NC]
RewriteRule (.*) /%1/$1 [L]
The request now stays on test.example.com and will serve content from test.example.com/test (although this is hidden from the user) since test.example.com and www.example.com are really the same thing.
The check against REDIRECT_STATUS ensures we are only processing the intial request and not the rewritten request, thus avoiding a rewrite loop. REDIRECT_STATUS is empty on the initial request and set to 200 after the first successful rewrite.
However, if test.example.com points somewhere entirely different then you'll need to implement a reverse proxy and "proxy" the request to www.example.com in order to "hide" this from the user.

Difference between 2 apache mod_rewrites

I've found 2 different code snippets to force https on my website:
RewriteRule (.*) https://%{SERVER_NAME}/$1 [R,L]
and
RewriteRule (.*) https://%{HTTP_HOST}%{REQUEST_URI}
I'm sure that they both work (one's from Httpd Wiki and the other's from SSL shopper). Would someone be able to explain the differences in how they perform the redirect?
They just use different Apache variables to make up the URL for redirect.
RewriteRule (.*) https://%{SERVER_NAME}/$1 [R,L]
This first rule takes the filename if one is entered such as myfile.php and appends the redirect with it replacing $1 in the redirect so that you get https://somesite.com/myfile.php
RewriteRule (.*) https://%{HTTP_HOST}%{REQUEST_URI}
The 2nd one using %{HTTP_HOST} will grab the information from the http headers instead to make up the URL used to redirect so entering the same url http://somesite.com/myfile.php will be redirected to https://somesite.com/myfile.php
It's just a matter of telling apache what to use for redirection. Either use the server internal name or use the one sent by the browser.
%{SERVER_NAME}
That is a server internal variable in apache and is defined in the server config.
%{HTTP_HOST}
This is the what is sent by the browser in the HTTP request headers. This is client side while the SERVER_NAME if from the server config.
%{REQUEST_URI}
REQUEST_URI is the path component of the requested URI, such as "/index.html". This is a special Apache variable.
There a many ways that have been done to redirect to https and both should work. Your choice.

Redirect Loop while redirecting all http requests to https using .htaccess

I have the following rules on my .htaccess file
# to redirect http to https
RewriteCond %{HTTPS} off
RewriteRule (.*) https://www.example.com/$1 [R=301,L]
# to redirect urls with index.php to /
RewriteCond %{THE_REQUEST} ^.*/index.php
RewriteRule ^(.*)index.php$ /$1 [R=301,L]
# to redirect non www requests to www url
RewriteCond %{HTTP_HOST} !^www\.example\.com
RewriteRule ^(.*)$ http://www.example.com/$1 [R=301,L]
When I am trying to access the website, it turns into a Redirect Loop. How to fix this issue and redirect properly?
Just in case somebody have redirect loop when using Apache http->https rewrite behind load balancer, here's solution that worked for me.
I had the same problem when used RewriteCond %{HTTPS} off for Apache behind load balancer, when load balancer does SSL stuff.
If https version of the site is not configured via Apache ModSSL it doesn't set %{HTTPS} variable to "on" and keeps redirecting infinitely.
The simplest solution to fix it is to target all https traffic to another Apache VirtualHost (when SSL is handled by load balancer) that is the copy of main one, but has different port (lets say 81). And in .htaccess do mod_rewrite for everything that is not on port 81:
ReWriteCond %{SERVER_PORT} !^81$
RewriteRule ^/(.*) https://%{HTTP_HOST}/$1 [NC,R,L]
The second way to do this is to send X-Forwarded-Proto header from load balancer to Apache and use it in rewrite condition:
RewriteCond %{HTTP:X-Forwarded-Proto} !https
RewriteRule .* https://%{HTTP_HOST}%{REQUEST_URI} [R,L]
I've seen a lot of people suffering redirect loops when trying to use .htaccess files to move from http to https. And there are a LOT of different answers to how to solve this issue. Some people say:
ReWriteCond %{SERVER_PORT} 80
OR
RewriteCond %{HTTPS} off
OR
RewriteCond %{HTTPS} !on
OR (as above)
RewriteCond %{HTTP:X-Forwarded-Proto} !https
OR EVEN
RewriteCond %{HTTP:X-Forwarded-SSL} =off
but none of these worked for me. I eventually discovered the underlying truth, that the different servers out there are configured in different ways, and they're all providing different server variables.
If none of the above work for you, then the trick is to use PHP to find out what env variables your particular server is sending you when you access an http page, and what env variables it sends you when you access an https page, and then you can use that variable to do the redirect. Just make a PHP file (such as showphpvars.php) on your server with this code:
<?php phpinfo() ?>
and then view it with a browser. Find the section of variables with _SERVER["HTTP_HOST" (etc)] in it, and have a scout around for one that changes for http versus https. Mine turned out to be a variable called SSL that was set to 1 when using https, and not set at all when using http.
I used that variable to redirect to https with PHP, which is so much nicer than using htaccess, but I think that any of the _SERVER variables can also be accessed using htaccess, if you're keen to continue to use that. Just use the name inside the quotes, without the _SERVER[""] bit that PHP adds.
For your information, it really depends on your hosting provider. It may be using a Load Balancer, as stated by Konstantin in another answer.
In my case (Infomaniak), nothing above actually worked and I got infinite redirect loop.
The right way to do this is actually explained in their support site:
RewriteEngine on
RewriteCond %{HTTP:X-Forwarded-Proto} !https
RewriteRule (.*) https://your-domain.com/$1 [R=301,L]
So, always check with your hosting provider. Hopefully they have an article explaining how to do this. Otherwise, just ask the support.
If you get a redirect loop no matter what you do in htaccess, do the redirect in PHP instead.
I used phpinfo(), like #z-m suggests, to find the variable that changes when I'm on SSL. In my case it was $_SERVER['HTTP_X_PROTO'] == "https". When not on SSL, this variable is not set.
This is the code I use to redirect from HTTP to HTTPS:
if ($_SERVER['HTTP_X_PROTO'] != "https") {
header("HTTP/1.1 301 Moved Permanently");
$location = "https://" . $_SERVER[HTTP_HOST] . $_SERVER[REQUEST_URI];
header("Location: $location");
exit;
}
RewriteEngine on
RewriteCond %{HTTPS} off
RewriteRule (.*) https://%{HTTP_HOST}%{
In my case it was:
if ($_SERVER['HTTPS'] != "on")

Problem with forcing SSL using .htaccess

I have the following .htaccess file:
Order deny,allow
Deny from all
Allow from XX.XXX.XXX.XXX
RewriteEngine on
RewriteBase /
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.php
RewriteCond %{HTTPS} !=on
RewriteRule ^.*$ https://%{SERVER_NAME}%{REQUEST_URI} [R,L]
Which is supposed to:
Only allow access from my IP (numbers changed to Xs to protect the innocent)
Send any request which is not a specific file through to /index.php
Force https for the entire domain
As far as I can see, it's identical to a previous project, which was admittedly on a different hosting provider, but that worked like a charm. This time it's resulting in a message saying "Firefox has detected that the server is redirecting the request for this address in a way that will never complete.".
Anybody know what's going on & what I need to change please?
Perhaps your new hosting provider is using some sort of setup (like a reverse proxy) that's preventing the HTTPS variable from being set. You may be able to use something else (like SERVER_PORT, or perhaps a header set by the remote proxy, assuming there is one) to determine if the request is HTTPS or HTTP.