How to Block 100,000+ Individual Ip Addresses

How do you block ip addresses inside of apache dynamically?

See: Ban IPs from text file using htaccess

Essentially, you can leverage a RewriteMap to either read from a text file, run a script (which could access a database) or even perform an SQL Query using dbd. Remember that you can't define the map in an htaccess file, but you can use the map in one.

And you'd be checking the %{HTTP:X-FORWARDED-FOR} condition instead of the %{REMOTE_ADDR}:

RewriteEngine On 
RewriteCond ${access:%{HTTP:X-FORWARDED-FOR}} deny [NC]
RewriteRule ^ - [L,F]

Hashing IP Address Ranges

Remembering that every IP address (for IPv4) is a group of 4 8-bit numbers, you can simply keep the first two numbers (leftmost 16 bits). As a simple solution.

123.123.xx.yyy -> 123.123 -> the binary representation of these two numbers. That's the first number times 256 plus the second number.

// IP address is n1.n2.n3.n4
myHash = n1*256+n2; // integer value between 0 and 65535

Hashing IP Address Ranges

Remembering that every IP address (for IPv4) is a group of 4 8-bit numbers, you can simply keep the first two numbers (leftmost 16 bits). As a simple solution.

123.123.xx.yyy -> 123.123 -> the binary representation of these two numbers. That's the first number times 256 plus the second number.

// IP address is n1.n2.n3.n4
myHash = n1*256+n2; // integer value between 0 and 65535

Query to return rows that match a block of ip addresses?

The answer to your question is to use like:

SELECT *
FROM blocked
WHERE $_SERVER['REMOTE_ADDR'] like replace(ip, '*', '%')

The wildcard in like is '%' rather than '*', so this replaces the asterisk with the percent sign. I am guessing that you would actually store the string like '199.199.%.%', but the above is for clarity.

Although this technically solves your problem, it has other issues because MySQL may not use an index for these comparisons (see here). The impact depends on how large the blocked table is. If it has 100 rows, this may not be an issue. If it has 100,000 then it probably is.

An alternative to using wildcards for the blocked table is to have FromIP and ToIP as columns. Then something like "199.199.." would simply be stored as "199.199.000.000" and "199.199.999.999". The query would be:

where $_SERVER['REMOTE_ADDR'] between FromIP and ToIP

And you would have an index on blocked(FromIP, ToIP).



Related Topics



Leave a reply



Submit