Denying access to your web server by IP address

Posted by Steve on Sun 30 Oct 2005 at 21:44

Tags: none.

There are several times when you'll wish to deny particular clients access to your webserver. The most common and obvious solution is to simply firewall the visitors, however this doesn't let the visitors know what went wrong. They might just believe your webserver is down. A better approach is to use mod_rewrite to redirect them to an error page.

mod_rewrite is a very flexible Apache module which allows you to rewrite almost all aspects of incoming requests to your webserver.

We've previously given an introduction to using mod_rewrite which also covers installing it for both Apache 1.3.x and Apache 2.x.

Once installed you can take advantage of its rewriting rules by adding the following within the virtual host file you wish to protect. (You can add the rules globally instead if you prefer):

RewriteEngine on
Rewritemap ipmap txt:/path/to/blacklist.txt 

RewriteCond ${ipmap:%{REMOTE_ADDR}} ^b$            [NC]
RewriteCond %{request_uri} !^/sorry.html$          [NC]
RewriteCond %{request_uri} !^/stylesheet.css$      [NC]
RewriteRule .* /sorry.html                        [R,L]

The first line simply ensures that the mod_rewrite engine is engaged, and turned on.

The second line is causes Apache to define a lookup map - which we will use later. The map is stored in the file /path/to/blacklist.txt, and will have the form:  b  b  b

This file is a text file with IP addresses listed next to a " b". The "b" here is just a key, standing for "banned", which we'll test against.

After defining the mapfile we'll use it in the rule:

RewriteCond ${ipmap:%{REMOTE_ADDR}} ^b$            [NC]

This rule reads "If the lookup of the REMOTE_ADDR header field in the mapfile returns 'b' then we've got a match.", now we can continue with the later rules:

RewriteCond %{request_uri} !^/sorry.html$          [NC]
RewriteCond %{request_uri} !^/stylesheet.css$      [NC]
RewriteRule .* /sorry.html                        [R,L]

Here we say "If the request isn't "/sorry.html", or "/stylesheet.css" then forcibly redirect the visitor to the page "/sorry.html".

(The rule to allow the stylesheet merely allows the sorry.html file to look presentable - it might not make sense in your case.)

Altogether then the rules:

  • Define a lookup table of banned IP addresses.
  • Test each incoming connection against the IP ban
  • If there is a match:
    • And request wasn't for /sorry.html, or /stylesheet.css then:
    • Force visitor to view the /sorry.html page.

This is a nice simple technique for dealing with aggressive downloads, or people who persistently abuse your server.

The upside is they'll know they were banned, and hopefully will know to do better in the future. The downside is that there will be a lookup against the text file on each incoming request - but you'll most likely not notice this slowdown.



Posted by Anonymous (62.24.xx.xx) on Mon 31 Oct 2005 at 12:16
I guess this wouldnt work in a global context? If not how do we do this under a vhosts enviroment?

[ Parent | Reply to this comment ]

Posted by Anonymous (213.164.xx.xx) on Mon 31 Oct 2005 at 14:57
Not sure I understand your question, but..

> Rewritemap ipmap txt:/path/to/blacklist.txt
You could share this file.
You might even use /etc/hosts.deny

[ Parent | Reply to this comment ]

Posted by Steve (82.41.xx.xx) on Mon 31 Oct 2005 at 16:43
[ View Steve's Scratchpad | View Weblogs ]

/etc/hosts.deny isn't going to be read by Apache/Apache2.

Nor is it in the right format for using with a RewriteMap directive.


[ Parent | Reply to this comment ]

Posted by Anonymous (213.164.xx.xx) on Wed 2 Nov 2005 at 08:27

The official URL Rewriting guide gives it as an example:

[ Parent | Reply to this comment ]

Posted by Steve (82.41.xx.xx) on Mon 31 Oct 2005 at 16:42
[ View Steve's Scratchpad | View Weblogs ]

As I suggested in the article itself, yes it will.

Simple place the relevent lines inside your global configuration section if you don't want to put it inside a VirtualHost section.

For virtualhosts just include it in the relevent section (or config file if you're using Apache2 with a file for each host).


[ Parent | Reply to this comment ]

Posted by Anonymous (67.180.xx.xx) on Fri 17 Feb 2006 at 23:36
Is it possible to deny IP ranges using this method ?

[ Parent | Reply to this comment ]

Posted by Anonymous (193.184.xx.xx) on Mon 23 Oct 2006 at 05:44
Hi Steve,

You are my hero! Thanks for all great little tips and tricks!

(uhm... little too much coffee for the morning, but I thought that I would like to share my happiness:)


[ Parent | Reply to this comment ]

Posted by Anonymous (64.229.xx.xx) on Thu 26 Oct 2006 at 17:12
This is a great article. I am hoping you can tell me how to block by Ip range as well.

[ Parent | Reply to this comment ]

Posted by lxg (87.78.xx.xx) on Mon 26 May 2008 at 12:11
As each line in the IP list is interpreted as a regular expression, you can insert an appropriate RegEx to block/unblock a range (not tested, but should work).

[ Parent | Reply to this comment ]

Sign In







Current Poll

Will you stick to systemd as the default in Debian?

( 32 votes ~ 1 comments )