Search code examples
phpipfirewallddosdenial-of-service

how can i improve this script firewall?


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);   
}
  • Basically the script checks if the current ip is found in a file 'ipBlocked' if it's found it dies.
  • If it's not found it adds the current ip to a file logger 'ipLogger'.
  • After this it counts the occurences of the ip in the file ipLogger if they are > $max it's blocks this ip by adding the ip to the file ipBlocked

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


Solution

  • 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.