Two versions of .htaccess 301 redirect - .htaccess

I'm looking to move my site to https and I need to add a rule to the .htaccess file to set up the 301 redirect. I have read a lot of guides for this and there seem to be many different possibilities, but two of them keep coming up over and over again.
Why are these two options different? What do they do differently?
Option 1
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteCond %{HTTPS} off
RewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]
</IfModule>
Option 2
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteCond %{SERVER_PORT} 80
RewriteRule ^(.*)$ https://www.yoursite.com/$1 [R,L]
</IfModule>

Most of the time there are different ways to achieve one's goal, an answer to which method is the best can be opinion b(i)ased.
Option 1
will redirect all non-SSL traffic, independently of the listening ports you are requesting (you can listen to several ports at the same time, like 80, 81,..)
will redirect any FQDN to its https equivalent, keeping the request URI. You don't need to adapt it, unless you want several FQDNs to be redirected to the same https site.
the return code being 301, it will be cached easily by any proxy
Option 2
will redirect only traffic coming to the 80 port. If you are listening to another port, which is very likely on huge hosting platforms particularly behind load-balancers, you will need to change from 80 to another value
will redirect any FQDN to the very same https site (www.yoursite.com), keeping the request URI.
the return code being 302, it will probably be not cached if other headers are not set (Cache-Control)
Option 1 requires less work for the administrator and I believe it is the most used of the two. If there is any performance difference between the two, it's probably neglibible though I believe that Option 1 is better because %{REQUEST_URI} is a server variable and is not extracted from a regex.

Related

Trouble with redirects with multiple directories

I have a domain with two versions and I need to redirect 1 of the versions
test.example.ca
test.example.ca/en
test.example.ca/fr
I need the first domain test.example.com to redirect to test.example.ca/en anytime someone hits it. but i don't want test.example.ca/fr to redirect to test.example.com/en/fr
this is what I've been trying with no success.
RewriteCond %{HTTP_HOST} =test.example.ca
RewriteCond %{HTTP_HOST} !=test.example.ca/fr
RewriteRule ^(.*)$ https://%{HTTP_HOST}/en/$1 [R=301,L]
I understand the question such that you simply to not want requests to https://test.example.com/fr... to get redirected. So you want an exception.
I'd say this roughly is what you are looking for:
RewriteEngine on
RewriteCond %{HTTP_HOST} ^test\.example\.com$
RewriteCond %{REQUEST_URI} !^/fr
RewriteRule ^ https://test.example.ca/en%{REQUEST_URI} [R=301,L]
Chances are that your question was wrong in a few details, to me it reads as if you were not really precise with your host names. But above should be the correct answer to what you actually asked.
You should implement such rules in the http server's host configuration. If you do not have access to that you can also use a distributed configuration file (".htaccess"). That file should be located in the DOCUMENT_ROOT folder defined for your http host. And you need to make sure that the interpretation of such files is enabled at all (see the documentation for the AllowOverride directive for that).
It is a good idea to start out using a R=302 temporary redirection first. And to only change that to a R=301 permanent redirection once everything works as desired. That prevents nasty caching issues on the client side.

htaccess - Prevent Hotlinking/Webpage Scraping & Redirect Attacker's Webpage to Warning Page

Malicious website owners are using the contents of our website to say example.com on their websites say spam.com like:
<?php
$url='https://example.com/';
// using file() function to get content
$lines_array=file($url);
// turn array into one variable
$lines_string=implode('',$lines_array);
//output, you can also save it locally on the server
echo $lines_string;
?>
We want to prevent the contents of our website from displaying on their websites and redirect those requests to a warning page on our website (to a webpage and not an image).
After doing some R&D, we tried doing this:
<IfModule mod_rewrite.c>
RewriteEngine on
RewriteCond %{HTTP_REFERER} !^$
RewriteCond %{HTTP_REFERER} !^https://example\.com/.*$ [NC]
RewriteRule ^(.*) https://example.com/404 [R=301,L]
</ifModule>
But it doesn't work. What are we doing wrong?
Reference: htaccess prevent hotlink also prevents external links
"Hotlinking" and "webpage scraping" are two very different things. What you describe with the snippet of simplified PHP code is a form of "webpage scraping" or even "cloning". This does not (or is very unlikely to) generate a Referer header in the request, so cannot be blocked by simply checking the Referer (ie. HTTP_REFERER server variable) as you would do with "hotlinking".
(Your example mod_rewrite code blocks "hotlinking", not "scraping/cloning".)
The only way to block these types of requests is to block the IP address of the server making the request. For example, if the "malicious" requests are coming from 203.0.113.111 then you would do something like the following in the Apache 2.4 config (or .htaccess file) to block such requests:
<RequireAll>
Require all granted
Require not IP 203.0.113.111
</RequireAll>
However, the requests may not be coming from the same IP address that is hosting the "cloned" content. You'll need to determine this from your server's access logs. But to further complicate this the "attacker" may be using a series of IP addresses or have access to a botnet of ever-changing IPs. This can quickly become almost impossible to block without access to a more comprehensive firewall.
You can try other techniques such as issuing redirects to the canonical hostname from client-side code. However, more advanced "cloning" software (and/or reverse proxy servers) will "simply" modify the code/URLs to thwart your redirection attempts.
So, I'm try to google it, and finded this:
RewriteEngine On
RewriteCond %{HTTP_REFERER} !^$
RewriteCond %{HTTP_REFERER} !^http://(www\.)?example.com/.*$ [NC]
RewriteRule ^(.*)$ http://www.example.com/404 [R=404,L] # R=404 returns 404 page

Htaccess redirect for single page not working

My .htaccess file has redirect and rewrite code. It all works fine except for one page. I need to redirect https://example.com/shopping/ceylon-cinnamon-c-62.html and http://example.com/shopping/index.php?cPath=62 to https://example.com/ceylon-cinnamon-c-2_19.html I have tried the four lines under the NONE OF THESE WORK below (one at a time) but the redirect never works. The result url is https://example.com/c-62.html. Can anyone point out the problem or how to test it?
Options +FollowSymLinks -Indexes
RewriteEngine On
RewriteBase /
# NONE OF THESE WORK
Redirect 301 /shopping/ceylon-cinnamon-c-62.html https://example.com/index.php?cPath=2_19
Redirect 301 /shopping/index.php?cPath=62 https://example.com/index.php?cPath=2_19
RewriteRule ^(.*?)shopping/ceylon-cinnamon-c-62.html$ https://example.com/index.php?cPath=2_19 [R=301,L,NC]
RewriteRule ^(.*?)shopping/index.php?cPath=62$ https://example.com/index.php?cPath=2_19 [R=301,L,NC]
# THESE ALL WORK
RewriteRule ^shopping/(.*)$ /$1 [R=301,NC,L]
#redirect index.php to root
RewriteCond %{THE_REQUEST} ^[A-Z]{3,9}\ /index\.php\ HTTP/
RewriteRule ^index\.php$ https://example.com/ [R=301,L]
RewriteCond %{SERVER_PORT} 80
RewriteRule ^(.*)$ https://example.com/$1 [R,L]
RewriteRule ^(.*)-c-(.*).html$ index.php?cPath=$2&%{QUERY_STRING}
Your question is a bit vague... The example rules you give ("NONE OF THESE WORK") have little to do with what you ask in your question. And the claimed result of the rewriting attempts certainly is not what your attempts implement. So either your description is incorrect (written from memory maybe?) or you have some other factor in place which you do not tell us about (some application logic maybe that implements its own redirection?)...
Anyway, here are the simple rules to implement the exact redirection you ask about, independent of any other stuff:
RewriteEngine on
RewriteCond %{QUERY_STRING} (?:^|&)cPath=62(?:&|$)
RewriteRule ^/?shopping/index\.php$ /ceylon-cinnamon-c-2_19.html [R=301]
RewriteRule ^/?shopping/ceylon-cinnamon-c-62\.html$ /ceylon-cinnamon-c-2_19.html [R=301]
It is a good idea to start out with a 302 temporary redirection and only change that to a 301 permanent redirection later, once you are certain everything is correctly set up. That prevents caching issues while trying things out...
That said: when testing make tripple sure that you are not looking at cached results. Always use a fresh anonymouse browser window when testing, make deep reloads , not just reloads and watch your browser networking console for the actual response you receive...
This implementation will work likewise in the http servers host configuration or inside a dynamic configuration file (".htaccess" file). Obviously the rewriting module needs to be loaded inside the http server and enabled in the http host. In case you use a dynamic configuration file you need to take care that it's interpretation is enabled at all in the host configuration and that it is located in the host's DOCUMENT_ROOT folder.
And a general remark: you should always prefer to place such rules in the http servers host configuration instead of using dynamic configuration files (".htaccess"). Those dynamic configuration files add complexity, are often a cause of unexpected behavior, hard to debug and they really slow down the http server. They are only provided as a last option for situations where you do not have access to the real http servers host configuration (read: really cheap service providers) or for applications insisting on writing their own rules (which is an obvious security nightmare).

mod_rewrite http to https ends up in loop

I've got the problem that I want to redirect my HTTP requests to a HTTPS using a shared SSL certificate. For some stupid reason of my host I have to attach the SSL Port on the request url.
Basically I want to redirect this:
http://sub.domain.com
to
https://sub.domain.com:12345
my .htaccess looks like this:
RewriteEngine On
RewriteCond %{HTTPS} =off
RewriteRule ^(.*)$ https://%{HTTP_HOST}:12345%{REQUEST_URI} [L,R]
By this results in a redirect loop. I have no idea why though. Is this maybe because I use a shared SSL certificate which is not made for the domain and therefore the RewriteCond is always off?
thanks in advance!
EDIT:
I've checked the response header and saw that the location field still points to the non https url. But if I use another domain (or even a subdomain) it works. So why doesn't work the redirect to the same domain?
Try changing your condition to:
RewriteCond %{SERVER_PORT} 12345

.htaccess block all ip's, if they are blocked redirect to a page

So I am blocking all ip's except the ones on a list, so how can I redirect people to a new site if they're blocked?
My assumption is that you are blocking ip's using allow/deny. I do not believe that you are able to specify a redirect rule to work on the denied ip's as you have told the server to reject their connections outright.
Instead you are going to want to use the RewriteEngine to do a redirect. In case you are unfamiliar with the syntax I have provided the following example which will redirect all ip's except for "72.14.204.99" and "72.14.204.100" to "example.org":
RewriteEngine on
RewriteCond %{REMOTE_ADDR} !^72\.14\.204\.99$
RewriteCond %{REMOTE_ADDR} !^72\.14\.204\.100$
RewriteRule ^ http://www.example.org/ [R]

Resources