Apache dynamic whitelist - apache

I am looking for a solution for dynamic whitelist, so I do not need to restart apache2 service. I've tried to do something like this:
order Deny,Allow
include conf/IPList.conf
Allow from all
But this solution didnt work for me correctly. I've tried also this, but im not sure if my whitelist.txt is correct. How should it looks like?
## WHITELIST IPS ##
RewriteMap ipslist txt:/path/to/whitelist.txt
RewriteCond %{REMOTE_ADDR} ^(.*)$
RewriteCond ${ipslist:%1|black} ^black$ [NC]
RewriteRule (.*) - [F]
Or maybe there is another, better way to make dynamic whitelist for Apache2 ?

Using a rewrite map is fine. There's a reverse way to do this that I've posted about here.
You can simplify the rules a little though:
RewriteMap ipslist txt:/path/to/whitelist.txt
RewriteCond ${ipslist:%{REMOTE_ADDR}|black} ^black$ [NC]
RewriteRule ^ - [F]
The whitelist.txt file needs to look like:
1.2.3.4 ok
2.3.4.5 ok
etc.
The "ok" can be anything, but you need something that the whitelisted IP address maps to, other than "black". The whitelist.txt file will be cached by apache and when you change it, apache will automatically reload and reparse the file. This way, you don't need to restart apache.

Related

Apache Rewrite for Entire Subdomain

How would I go about rewriting :
proxmox.example.com
to
example.com/forward/?url=proxmox.example.com
I am trying to do this on Ubuntu with Apache
Please let me know what Apache plugins are used.
Will this rewrite go into my VirtualHosts file? (/etc/apache2/sites-available)
Thanks for the help!
You won't need a vhost for that. It can be put in the main Apache config.
Put this in your config:
RewriteEngine On
RewriteCond %{HTTP_HOST} ^(proxmox.(example.com))$
RewriteRule .* http://%2/forward/?url=%1 [R,L]
Use [P,L] instead of 'R' if you want to mask/hide the rewrite from the user. Otherwise stay with 'P'.
Also I used two nested brackets to retrieve example.com (value is stored in %2) and use that instead of a static 'example.com' in the second line. But if you prefer a 'clearer' (=easier to read) rule, use this:
RewriteEngine On
RewriteCond %{HTTP_HOST} ^(proxmox.example.com)$
RewriteRule .* http://example.com/forward/?url=%1 [R,L]
Hope it helped. Let us know if it did, and even more so, if it didn't so we can help furthermore :)

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]

.htaccess redirect according to PHP parameters

I'm trying to build some redirections with my .htaccess file to deal with some old forum url. I want the redirections to be made according to the PHP parameters (the topic ID).
For instance, something like
RewriteEngine On
RedirectPermanent /forum/viewtopic.php?t=123 /page1.html
RedirectPermanent /forum/viewtopic.php?t=345 /page7.html
RedirectPermanent /forum/viewtopic.php?t=89 /page3.html
The old and new URL are not related to each other (no PHP parameter has to be kept or something). I want to decide manually in my .htaccess file what to do for each topic ID.
But I can't manage to do that so easily. I tried many things, but nothing works.
Is this possible ? Any idea ?
Thanks a lot !
Edit : additional question : I want to add a global redirection of all the folder /forum to the root of the site ("/"). I guess I can place it after the others, so if no other rule is trigered, this one will be trigered.
I'm trying some things like
RewriteRule ^forum /? [L,R=301]
But everything I have tried so far redirects me to the "page1.html" (my first rule). Any idea why ? Thanks a lot !
You can't match against the query string using mod_alias's Redirect, RedirectMatch, etc. You need to use mod_rewrite and match against the %{QUERY_STRING} variable:
RewriteEngine On
RewriteCond %{QUERY_STRING} ^t=123$
RewriteRule ^forum/viewtopic\.php$ /page1.html? [L,R=301]
RewriteCond %{QUERY_STRING} ^t=345$
RewriteRule ^forum/viewtopic\.php$ /page7.html? [L,R=301]
RewriteCond %{QUERY_STRING} ^t=89$
RewriteRule ^forum/viewtopic\.php$ /page3.html? [L,R=301]
NOte that RewriteEngine is a mod_rewrite directive, not mod_alias. So it has no affect at all on the RedirectPermanent directives.

Apache Rewrite: image directory based on HTTP host

My software supports multiple domain names all pointed at the same directory on the server (a different database for each of course). So these domains...
www.example1.com
www.example2.com
www.example3.com
...all point to...
/public_html/
In the image directory...
/public_html/images/
I have directories that exactly match the host names for each website:
/public_html/images/www.example1.com/
/public_html/images/www.example2.com/
/public_html/images/www.example3.com/
I'm trying to get Apache to rewrite requests so that if you view the image directly and look at the address bar you only see the host name once.
So a request for...
http://www.example1.com/images/book.png
...is fetched by Apache at...
/public_html/images/www.example1.com/book.png
One of the things I've tried and have had success with in different circumstances is the following though it doesn't work in this situation:
RewriteRule ^[^/]*/images(.+) images/%{HTTP_HOST}/$1
Try adding the following to the .htaccess file in the root directory of your site (public_html)
RewriteEngine on
RewriteBase /
#prevent looping from internal redirects
RewriteCond %{ENV:REDIRECT_STATUS} !200
#only rewrite gif, jpg or png
RewriteRule ^(images)(/.+\.(gif|jpg|png))$ $1/%{HTTP_HOST}$2 [L,NC]
Your rule
RewriteRule ^[^/]*/images(.+) images/%{HTTP_HOST}/$1
did not work because you have a leading / before images. In .htaccess the leading / is removed, so the rule would never match.
Here's one of the things I've made for my high performance framework (see my bio).
I give you an advanced RewriteRule, I'm pretty sure you'll have enough material to finish:
Create static domains:
static.example1.com
static.example2.com
static.example3.com
Where all your images will be.
From now on, no more:
www.example1.com/images/www.example1.com/picture.jpg
www.example2.com/images/www.example2.com/picture.jpg
www.example3.com/images/www.example3.com/picture.jpg
but
static.example1.com/picture.jpg
static.example2.com/picture.jpg
static.example3.com/picture.jpg
Nice URLs uh?
Now create a vhost with all your static files:
<VirtualHost *>
ServerName static.example1.com
ServerAlias static.example2.com static.example3.com
</VirtualHost>
Set your document root to the base without the vhost name, so in your case:
DocumentRoot "/public_html/images"
And add this RewriteRule
RewriteCond %{HTTP_HOST} ^static\.([a-zA-Z0-9\-]+)\.com$
# Change the path, and add the request:
RewriteRule (.*) %{DOCUMENT_ROOT}/static.%1.com$1 [QSA,L]
So all in all:
<VirtualHost *>
ServerName static.example1.com
ServerAlias static.example2.com static.example3.com
RewriteCond %{HTTP_HOST} ^static\.([a-zA-Z0-9\-]+)\.com$
# Change the path, and add the request:
RewriteRule (.*) %{DOCUMENT_ROOT}/static.%1.com$1 [QSA,L]
</VirtualHost>
Ok that doesn't aswer exactly to your question so here's the short answer, but I don't like it because it doesn't help you to do a very (very) good job:
RewriteCond %{HTTP_HOST} ^www\.(example1|example2|example3)\.com$
# Change the path:
RewriteRule (.*)(\.(css|js|txt|htc|pdf|jpg|jpeg|gif|png|ico))$ %{DOCUMENT_ROOT}/www.%1.com$1$2 [QSA,L]
And if that's not enough:
Two hints:
If you're not in a hosted environment (= if it's your own server and you can modify the virtual hosts, not only the .htaccess files), try to use the RewriteLog directive: it helps you to track down such problems:
# Trace:
# (!) file gets big quickly, remove in prod environments:
RewriteLog "/web/logs/mywebsite.rewrite.log"
RewriteLogLevel 9
RewriteEngine On
My favorite tool to check for regexp:
http://www.quanetic.com/Regex (don't forget to choose ereg(POSIX) instead of preg(PCRE)!)
John,
I've just posted a separate Q on some of the challenges that you face. I would welcome your comments, but back to your challenge: one trick that you can use an environment variable to store your (preferably validated) host, for example:
RewriteCond %{HTTP_HOST} ^www\.(host1|host2|host3\.com
RewriteRule ^ - [E=HOST:%1]
You might also want to add [S] flags to implement if/then/else logic in your rules. And you can also use the HOST variable in following rule or condition strings (not regexp patterns) as %{ENV:HOST}.
You also need to take a clear look at a full phpinfo() report to understand whether you hosting service is using an mod_php or a mod_suPHP, ... interface and host it supports DNS multihoming. E.g my supplier sets up %{ENV:DOCUMENT_ROOT_REAL} which I need to use instead of %{DOCUMENT_ROOT} when examining file-space.
All of your URI "arrivals" at DOCROOT/ are of the form http://www.exampleX.com/images/book.png so if your .htaccess location is your DOCROOT then your base is /. So assuming the above ENV setting, these should work
RewriteBase /
RewriteCond %{HTTP_HOST} ^www\.(host1|host2|host3)\.com
RewriteRule ^ - [E=HOST:%1]
RewriteCond %{ENV:HOST}==%{REQUEST_URI} !^(.*?)==/image/\1
RewriteRule ^image/(.*) image/%{ENV:HOST}/$1 [L,NS]
The cond is a botch to stop the rewrite rule looping.
Generalised version
The above solution is an already generalised solution as you as for. Just replace the RewriteCond regexp with whatever pattern matches your own naming convention, and I agree that if it is (.*) then you may as well drop the first rule and replace %{ENV:HOST} by %{HTTP_HOST}. You need the RewriteCond guard to prevent the loop which results in a 500.

.htaccess require SSL for a particular URL

I want to force Apache to use HTTPS for a particular URL in the following form:
https://www.example.com/signup/*
so
if someone goes to any of the following example URLs directly, Apache will forward the URL over to the HTTPS equivalent site.
e.g.
http://www.example.com/signup --> https://www.example.com/signup
http://www.example.com/signup/basic+plan --> https://www.example.com/signup/basic+plan
http://www.example.com/signup/premium --> https://www.example.com/signup/premium
Anyone know how?
Thanks in advance
Thank Murat,
Yours almost worked but figured out how to get it to exactly work.
The following is what works:
RewriteCond %{SERVER_PORT} 80
RewriteCond %{REQUEST_URI} ^/somefolder/?
RewriteRule ^(.*)$ https://www.domain.com/$1 [R,L]
Notice that I didn't include somefolder in the www.domain.com rewriterule
I think this was what i used:
RewriteEngine On
RewriteCond %{SERVER_PORT} 80
RewriteCond %{REQUEST_URI} ^/somefolder/?
RewriteRule ^(.*)$ https://www.domain.com/somefolder/$1 [R,L]
(from here)
You can use the Redirect directive:
Redirect 301 /signup https://www.example.com/signup
This will automatically preserve anything following /signup in the URL. Be sure to configure this directive only on your non-SSL site, or it might get into a recursive loop!
You should take a look at mod_rewrite documentation
I used the following to require the checkout section of a website to require SSL:
<Directory "/var/www/html">
RewriteEngine on
Options +FollowSymLinks
Order allow,deny
Allow from all
RewriteCond %{SERVER_PORT} !^443$
RewriteRule \.(gif|jpg|jpeg|jpe|png|css|js)$ - [S=1]
RewriteRule ^checkout(.*)$ https://%{SERVER_NAME}%{REQUEST_URI} [L,R]
</Directory>
So for example, hitting http://www.example.com/checkout redirects to https://www.example.com/checkout
The rule will skip file extensions that are typically included within a page so that you don't get mixed content warnings. You should add to this list as necessary.
If you want multiple pages change the RewriteRule to something like:
RewriteRule ^(checkout|login)(.*)$ https://%{SERVER_NAME}%{REQUEST_URI} [L,R]
Of course, the directory should match the actual path on your server. This page may also help with some more information for your specific needs: http://www.whoopis.com/howtos/apache-rewrite.html
I'm using this on a website that runs Plesk 8.6 but that shouldn't matter. This is in my vhost.conf file which is like putting it in your httpd.conf file. I'm not sure if you'd need to adjust anything to use it in a .htaccess file but I doubt it. If adding to a conf file don't forget to restart apache to reload the configuration.
If you are like me and want to use SSL only on particular pages then you also want a rewrite rule that sends you back to regular http for the rest. You can use the following for the reverse effect:
RewriteCond %{SERVER_PORT} ^443$
RewriteRule \.(gif|jpg|jpeg|jpe|png|css|js)$ - [S=1]
RewriteRule !^(checkout|login)(.*)$ http://%{SERVER_NAME}%{REQUEST_URI} [L,R]
If you are using Plesk like I am keep in mind that all non-SSL traffic uses the vhost.conf file but all SSL traffic uses the vhost_ssl.conf file. That means your first rewrite rule to require SSL would go in the vhost.conf file but the second rule to force back to non-SSL will have to go in the vhost_ssl file. If you are using httpd.conf or .htaccess I think you can put them both in the same place.
I've also posted this tutorial on my blog: Apache rewrite rules to force secure/non-secure pages.
You can do this with mod_rewrite -
RewriteCond %{SERVER_PORT} !^443$
RewriteRule ^/signup https://example.com/signup
RewriteRule ^/signup/(.*)$ https://example.com/signup/$1
Should work, though I haven't tested it.
-- edit --
Correction, I just tried this on one of my servers, and it works fine for me. You may want to doublecheck your mod_rewrite configuration. Also, if you're using .htaccess, you'll want to make sure overrides are allowed for that directory.
As a side note, this assumes your SSL traffic is coming over port 443. If it isn't, you'll need to adjust the rewrite condition accordingly.
.htaccess files are normally placed in a scope with Options -FollowSymLinks, which blocks Rewrite rules. This is often a security rule.
So a more trivial thing is often needed like this one:
<If "%{HTTPS} != 'on'">
Redirect 301 /your/path https://www.example.com/your/path
</If>
This is a small enhancement to the answer of Greg Hewgill.