recently one of my server is getting targetting by a number of dos attack (thousands requests/min) by some chinese IP (these ip aren't always the same).
So at the start of my framework I made a little function to block after an ip if it has made too much requests.
function firewall() {
$whitelist = array('someips');
$ip = $_SERVER['REMOTE_ADDR'];
if (in_array($ip,$whitelist))
return null;
if (search($ip,$pathToFileIpBanned))
die('Your ip did too many requests')
appendToFile($ip,$pathTofileIpLogger); //< When the file reaches 13000 bytes truncate it
if (search($ip,$pathTofileIpLogger) > $maxRequestsAllowed)
appendToFile($ip,$pathToFileIpBanned);
}
ATM is working.. it has banned some chinese/tw ips
The bottleneck of this script is the search function that must counts the occurences in a file of a string (the ip). For this reasons I am keeping low the file (the iplogger file is truncated as soon as it reaches 600-700 ips logged)
Of course to add ips to the file without having to worry about race condition i do it like this:
file_put_contents($file,$ip."\n",FILE_APPEND | LOCK_EX);
The only problem i am experiencing with is is the poeple behind NAT. they all have the same IP but their requests shouldn't be blocked
Some very basic file/serialize code, you could use as an example:
<?php
$ip = $_SERVER['REMOTE_ADDR'];
$ips = @unserialize(file_get_contents('%path/to/your/ipLoggerFile%'));
if (!is_array($ips)) {
$ips = array();
}
if (!isset($ips[$ip])) {
$ips[$ip] = 0;
}
$ips[$ip] += 1;
file_put_contents('%path/to/your/ipLoggerFile%', serialize($ips));
if ($ips[$ip] > $maxRequestsAllowed) {
// return false or something
}
Of course, you'll have to integrate this in some way into your firewall
function.