mod_rewrite based on ip - apache

I'd like to implement mod_rewrite to put my site into maintenance. Basically all IP addresses except a handful we specify would be forwarded to a static html page.
Please can someone help with this rule. Also is there a way to turn this on and off easily without editing the htaccess file?

You can use the REMOTE_ADDR variable in a RewriteCond
RewriteCond %{REMOTE_ADDR} !^10\.0\.1\.1$
RewriteRule ^ /maintenance.html
Just change the condition to match the IPs you want, for more than one you can use ^(ip1|ip2|...|ipn)$.
About how to disable the maintenance mode without changing the .htaccess file I think that's not possible short of writing a program that would delete it or otherwise modify it, an easy one would be to rename it.

I'd like to slightly correct Vinko Vrsalovic's answer.
RewriteCond %{REMOTE_ADDR} !^10\.0\.1\.1$
RewriteRule ^ /maintenance.html
This rule result will be infinite loop and HTTP server error, because it will be executed on redirection page too. To make it work you should exclude redirection page from the rule. It can be done this way:
RewriteCond %{REMOTE_ADDR} !^10\.0\.1\.1$
RewriteCond %{REQUEST_URI} !/maintenance.html$ [NC]
RewriteRule .* /maintenance.html [R=302,L]

Small improvement to Alexander's answer, it's not necessary to use regular expression for the IP address.
RewriteCond %{REMOTE_ADDR} !=10.0.0.1
RewriteCond %{REQUEST_URI} !/maintenance.html$ [NC]
RewriteRule .* /maintenance.html [R=302,L]

you could enable this state and disable it via some admin interface that is able to write to .htaccess (e.g. permissions set to 755 or 777). it would just always find the .htaccess, insert those two lines at the beginning and on disabling maintenance it would delete those two lines, leaving the rest of the file untouched

Optional redirect only specific addresses
Late to the party, and just an add-on if somebody needs it the other way around.
With this approach, you redirect only specific addresses into maintenance then play with the aliases.
ServerName 10.0.1.1
ServerAlias 10.0.2.1
ServerAlias 10.0.3.1
RewriteEngine On
RewriteRule ^(.*)$ http://www.domainname.com/maintenance.html$1 [L,R=301]

Related

I changed domains and post slug structure at the same time for my WP site. Can I use 1 redirect to do so with htaccess?

I am planning a domain change from example1.com to example2.com. To add a twist to it, I also want to change my permalinks at the same time. My current permalinks for posts have the date and I want to remove it.
I'm a bit hesitant to test and lose SEO so I was hoping someone could confirm this would work before.
Here is what I was thinking:
after changing domains I use this code in my htaccess
RewriteEngine on
RewriteCond %{HTTP_HOST} ^example1.com [NC,OR]
RewriteCond %{HTTP_HOST} ^www.example1.com [NC]
RewriteRule ^\d{4}/\d{2}/(.*) https://example2.com/$1 [R=301,L]
then I found this rule to change dates:
RewriteRule ^[0-9]{4}/[0-9]{2}/(.*)$ https://example2.com/$1
I saw this one as well:
RewriteRule ^/(\d*)/(\d*)/([A-Za-z0-9-]*)$ https://example2.com/$4
I'm not sure what these rules specifically mean but I THINK I should be able to combine them like this?
RewriteEngine on
RewriteCond %{HTTP_HOST} ^example1.com [NC,OR]
RewriteCond %{HTTP_HOST} ^www.example1.com [NC]
RewriteRule ^[0-9]{4}/[0-9]{2}/(.*)$ http://example2.com/$1 [L,R=301,NC]
It doesn't seem quite right.
Or would simply changing the permalink structure in WordPress affect the change so that
https://www.example1.com/2019/01/how-to-write-about-cars/
redirects to
https://www.example2.com/how-to-write-about-cars/
UPDATE
Using MrWhite's answer below. I added this code:
RewriteEngine on
RewriteCond %{HTTP_HOST} ^example1.com [NC,OR]
RewriteCond %{HTTP_HOST} ^www.example1.com [NC]
RewriteRule ^/(\d*)/(\d*)/([A-Za-z0-9-]*)$ https://example2.com/$4
This is working now in the case of
https://www.example1.com/2019/01/how-to-write-about-cars/
which redirects to
https://www.example2.com/how-to-write-about-cars/
However
https://www.example2.com/2019/01/how-to-write-about-cars/
does NOT redirect to
https://www.example2.com/how-to-write-about-cars/
It just returns a 404. This likely isn’t an issue as nothing should be bookmarked but just in case, is there a way to fix that?
Or would simply changing the permalink structure in WordPress affect the change
I don't believe this would implement the redirect from the old to new URL structure, if that is what you are thinking. (At least not by default.)
RewriteCond %{HTTP_HOST} ^example1.com [NC,OR]
RewriteCond %{HTTP_HOST} ^www.example1.com [NC]
RewriteRule ^[0-9]{4}/[0-9]{2}/(.*)$ http://example2.com/$1 [L,R=301,NC]
This looks OK. Although if the new URLs at example2.com don't contain the date (ie. /YYYY/MM/ prefix) then there wouldn't seem to be any need to check the requested hostname.
This rule must also go at the top of the .htaccess file, before any of the existing WordPress directives (ie. before the # BEGIN WordPress comment marker).
You should first test with a 302 (temporary) redirect to avoid potential caching issues.
Final Solution
This can, however, be tidied a bit. The following one-liner should be sufficient:
RewriteRule ^\d{4}/\d{2}/(.*) https://example2.com/$1 [R=301,L]
You do not need any of the RewriteCond directives. (Just the RewriteEngine On directive, if it doesn't already appear elsewhere in the .htaccess file.)
Note the https on the target URL. \d (shorthand character class) is the same as [0-9]. The trailing $ on the regex is not required since regex is greedy by default. The NC flag is not required either, since there is nothing case specific in this regex.
Aside: (Don't use this!)
I saw this one as well:
RewriteRule ^/(\d*)/(\d*)/([A-Za-z0-9-]*)$ https://example2.com/$4
This rule, however, is very wrong! Due to the slash prefix on the RewriteRule pattern this will never match in .htaccess and the rule will do nothing. But there are only 3 capturing groups in the regex, so the $4 backreference would always be empty (everything would be redirected to the homepage, which would likely be treated as a soft-404 by search engines).

Apache mod_rewrite for specific folders and paths

I have found dozens of articles online on how to setup mod_rewrites but for the love of God I can't figure out how to PROPERLY force HTTPS on ALL pages and after that force HTTP on certain directories or (already rewritten) pages.
Now this one gets really tricky as I need HTTPS on this directory, except for two cases, such as "/surf" which actually is rewritten from "surf.php", and "promote-([0-9a-zA-Z-]+)$" which is rewritten from "promote.php?user=$1" :
<Directory /home/rotate/public_html/ptp/>
AllowOverride None
Order Deny,Allow
Allow from all
Options +SymLinksIfOwnerMatch
ErrorDocument 404 "<h1>Oops! Couldn't find that page.</h1>"
RewriteEngine On
RewriteRule ^promote-([0-9]+)$ promote.php?user=$1 [QSA,NC,L]
RewriteRule ^([^.?]+)$ %{REQUEST_URI}.php [L]
</Directory>
I have tried some stuff but which only resulted in some weird redirection loops...
RewriteCond %{HTTPS} on
RewriteRule !^(surf|promote-([0-9]+)$) https://%{HTTP_HOST}%{REQUEST_URI} [R=301,L]
So basically I need to force HTTPS everywhere in /ptp/ except /ptp/surf (which is rewritten from surf.php AND /ptp/promote-123 which is rewritten from promote.php?user=123
Currently I'm using PHP to redirect to HTTP or HTTPS as per my needs but I know that it would be much faster if I could manage to do it via rewrites.
Any pointers, tips, suggestions? Thanks.
UPDATE2: This worked:
RewriteCond %{HTTPS} off
RewriteRule !^(surf|promote(-[0-9]+)?) https://%{HTTP_HOST}%{REQUEST_URI} [R=301]
RewriteRule ^promote-([0-9]+)$ promote.php?user=$1 [NC,L]
RewriteRule ^([^.?]+)$ %{REQUEST_URI}.php
However, the resources such as javascript, fonts etc, were being blocked by the browser, unless I specified absolute HTTPS paths. Note that this never happened when redirecting through PHP...
I changed a little bit and it works perfectly
Changes
Remove the Change the RewriteRule to match file to .php to bottom.
Remove the $ sign that is End of the pattern
As Said in the update promote-1111 will redirect to promote.php?user=$1 change the promote-[0-9]+ to promote(-[0-9]+)? otherwise it will override in the second redirection as you redirecting it to promote.php?user=$1
The Code
RewriteCond %{HTTPS} off
RewriteRule !^(surf|promote(-[0-9]+)?) https://%{HTTP_HOST}%{REQUEST_URI} [R=301,L]
RewriteRule ^([^.?]+)$ %{REQUEST_URI}.php [L]
The page surf
The Page Index
Never mind the error message shown in this image. Since I tried it from my localhost, it won't have a certificate.
Will work with servers
Your rules aren't in the "update" working because of side effects of using <Directory> context. Each substitution starts processing again.
When you request /promote-123 and rewrite it to put the numbers in the query string, you can't then match the numbers as if they're still in the path. You'll need to match the rewriten path and the numbers with RewriteCond %{QUERY_STRING} (if you care about the numbers)

Conditionally whitelist IP's in Apache using presence or absence of files

I found a pretty good solution to this problem but it is missing one component that I need. This is close:
# WHITELIST IPS #
RewriteMap ipslist txt:/path/to/whitelist.txt
RewriteCond %{REMOTE_ADDR} ^(.*)$
RewriteCond ${ipslist:%1|black} ^black$ [NC]
RewriteRule (.*) - [F]
MOST of the time I want to limit access to the site, but there will be times when I want many (beta testers) to have access. At that point, it will be easiest just to let anyone access the site during the test. So what I would really like to do is to make the whitelist apply conditionally. IF the whitelist.txt file is present, limit the access. But if there is no file, then let anyone access the site. Or, find some other approach.
I have searched for something similar but what I have above is as close as I can get. Can I use *.*.*.* in the whitelist.txt to allow ALL IP's when I need to? Or is there some better way to "turn on and turn off" the IP restriction logic?
Have you considered using a flag file as a condition instead of the file of ip addresses?
Something like:
# WHITELIST IPS #
RewriteMap ipslist txt:/path/to/whitelist.txt
RewriteCond /path/to/flag_enabled_feature_file -f
RewriteCond %{REMOTE_ADDR} ^(.*)$
RewriteCond ${ipslist:%1|black} ^black$ [NC]
RewriteRule (.*) - [F]

apache RewriteRule not working

I have this url http://www.example.com/Courses/get/38789/my-course, i added this rule to the .htaccess file
RewriteEngine On
RewriteCond %{HTTP_HOST} !^www\.
RewriteRule ^(.*)$ http://www.%{HTTP_HOST}/$1 [R=301,L]
RewriteEngine On
RewriteCond %{REQUEST_URI} ^/Courses/get
RewriteRule ^Courses/get/(.*)/(.*)$ course-$1-$2 [R=301,L]
but when i go to http://www.example.com/Courses/get/38789/my-course nothing happens, i stay on the same page, there is no redirect.
p.s the link is just an example not the actual link
A more efficient method would be to use the following:
RewriteRule ^Courses/get/(\d+)/([^/]+)/?$ /course-$1-$2 [R=301,L]
Now, keep in mind that this rule should come before any rules that may rewrite the request to, say, an index.php file. This would be naturally true if the code you posted in your question was all of your code. If not, please post your entire .htaccess file so we can be sure it is being placed in the right location.
Be sure the mod_rewrite is turned on, and the you have set AllowOverride All in your virtual host/Apache site configuration. If you're running on a shared production server, this would not apply to you.
Side note: Whilst it does work, you need not use RewriteEngine on twice - only once at the beginning of your file will suffice. You also do not need RewriteCond %{REQUEST_URI} ^/Courses/get - it is essentially redundant as you are already using an expression to test against the request.

Mod Rewrite, Unexpected Results

We are trying to redirect everything from one domain to another with the following
RewriteEngine on
RewriteCond %{HTTP_HOST} !^www\.example\.com$ [NC]
RewriteRule .? http://www.example2.com%{REQUEST_URI} [R=301,L]
When we visit http://www.example.com/v2sc
We are being redirected to http://www.example2.comv2sc
We would like to be redirected to http://www.example2.com/v2sc considering www.example2.comv2sc is not a valid hostname
Any ideas on how we can accomplish this?
Thank you!
It seems like you're using a .htaccess file for this. In that context the leading slash is not present in %{REQUEST_URI} so it's up to you to put it back in.
RewriteEngine On
RewriteCond %{HTTP_HOST} !=www.example.com
RewriteRule ^ http://www.example2.com/%{REQUEST_URI} [R=301]
Please also note that solutions like this should be used only if you cannot edit the main server configuration file. Doing so would allow you to use a cleaner combination of vhosts and Redirect directives that would run much more quickly.