Apr 02

Banning someone by IP address

Category: Linux   — Published by tengo on April 2, 2008 at 12:43 pm

If you would like to ban a subnet, an IP address or a single country, most of these tasks can be done by using mod_rewrite and your .htaccess file.

Start by writing Rewrite conditions that match against the REMOTE ADDR variable. Depending on the length of your regexp you can ban a complete network, a subnet or a single IP:

RewriteCond %{REMOTE_ADDR} ^$ [OR]
RewriteCond %{REMOTE_ADDR} ^255.255.255. [OR]

As you can see the, the first regex matches a single IP, while the second matches a certain subnet. Next you need to define a RewriteRule that will be executet when someone is matched by your rules:

RewriteRule .* /not-allowed.html [R]

This redirects all accesses from the above IP-addresses to this html file. The problem is that the access to the "not-allowed" file itself will be banned and redirected to the file again - thus leading to an infinite redirect loop, so you have to modify the block as follows:

RewriteCond %{REQUEST_URI} !^/not-allowed.html$ [NC]
RewriteRule .* /not-allowed.html [R]

Which reads like "whenever you encounter an IP that is banned and the request is NOT for not-allowed, then redirect this request to not-allowed.html".

You can also modify this technique to use GeoIP functionality or to match agains a blacklist file, as described here.


A solution you can find on various places on the net is to simply not use the mod_rewrite rewrite engine's pattern matching technique and use apache's deny/allow hook:

order allow,deny
deny from
deny from 255.255.255
deny from .telefonica.es
allow from all

Would be a sample ruleset for such a task (note the banning of ip ranges on the first line)

A final WIP note:

So far I had good results with the described RewriteCond technique, although I tend to get false positives for IP addresses which do not appear in my regexp. Is this a problem with IPv4 vs IPv6? Or a lingering bug in my regexes? I have no idea. Any help welcome!

Further reading: