IP flood detection, DDoS detector for PHP
Posted by: tez
Posted on: 2006-06-14 18:57:00
Now, I didn't come up with the original script for this, someone else did (on webmaster world?) the "read and write to file" parts. It will take the IP address and create an MD5 hash of it and use that to track the visiting times per ip, it is possible that two visitors on the same IP or proxy will trip the flood filter - but I say, though titties.
You will get an email each time a user is banned (mainly for testing and fun), the defaults will ban someone for 60 seconds if they do more than 9 hits in 10 seconds.
There are two parts to this. A php script, which you can either insert into your index.php, or a common functions file, or as an include_once('filename.php');
And a 777 writeable directory to store the tracked IPs with a iplog.dat file in there. This script will eventually create 255, 2 digit, 0kb files in the folder to track each ip.
The php. I created a floodstopper.php file and in any script like index.php for my forum or site I put include_once('floodstopper'); near the start and it will execute this script every time someone hits the index.php file. If you want to be really nasty you could make a .htaccess file which redirects all 404 file not found errors to this script as well - just in case. or maybe redirect all image leechers to this etc.
<?php
$cookie = $_COOKIE['yourcookie']; /* if you have a known cookie on your site,
you can use this, otherwise just ignore this, it will set a different limit
for people with this cookie */
/* I use yourothercookie as the cookie ID for the forum, my forum uses ID
greater than 0 for all members and -1 for guests and members who have logged out,
so making it match greater than zero means members will get better access and
guests with or without cookies won't */
$othercookie = $_COOKIE['yourothercookie'];
if($cookie && $othercookie > 0) $itime = 20; // Minimum number of seconds between visits
else $itime = 10; // Minimum number of seconds between visits
$ipenalty = 60; // Seconds before visitor is allowed back
if($cookie && $othercookie > 0)$imaxvisit = 30; // Maximum visits per $iteme segment
else $imaxvisit = 9; // Maximum visits per $iteme segment
$iplogdir = "./iplog/";
$iplogfile = "iplog.dat";
$ipfile = substr(md5($_SERVER["REMOTE_ADDR"]), -2);
$oldtime = 0;
if (file_exists($iplogdir.$ipfile)) $oldtime = filemtime($iplogdir.$ipfile);
$time = time();
if ($oldtime < $time) $oldtime = $time;
$newtime = $oldtime $itime;
if ($newtime >= $time $itime*$imaxvisit)
{
touch($iplogdir.$ipfile, $time $itime*($imaxvisit-1) $ipenalty);
$oldref = $_SERVER['HTTP_REFERER'];
header("HTTP/1.0 503 Service Temporarily Unavailable");
header("Connection: close");
header("Content-Type: text/html");
echo "<html><body bgcolor=#000000 text=#00FF00 link=#ffff00>
<font face='Verdana, Arial'><p><b>
Too many page views (more than ".$imaxvisit." visits within ".$itime." seconds)
by your IP address. Unregistered visitor hackers get less privileges.
</b>
";
echo "Please wait ".$ipenalty." seconds and try again.</p>
Or go to google.com <a href='http://google.com'></font></body></html>";
$fp = fopen($iplogdir.$iplogfile, "a");
if ($fp)
{
$useragent = "<unknown user agent>";
if (isset($_SERVER["HTTP_USER_AGENT"])) $useragent = $_SERVER["HTTP_USER_AGENT"];
fputs($fp, $_SERVER["REMOTE_ADDR"]." ".date("d/m/Y H:i:s")." ".$useragent."n");
fclose($fp);
$yourdomain = $_SERVER['HTTP_HOST'];
//the @ symbol before @mail means 'supress errors' so you wont see errors on the page if email fails.
if($_SESSION['reportedflood'] < 1 && ($newtime < $time $itime $itime*$imaxvisit))
@mail('webmaster@'.$yourdomain, $yourdomain.'site flood by '.$cookie.' '
.$_SERVER['REMOTE_ADDR'],'flood occured and ban for '.$_SERVER['REMOTE_ADDR'].' at '
.$_SERVER['REQUEST_URI'].' from '.$oldref.' agent '.$_SERVER['HTTP_USER_AGENT'].' '
.$cookie.' '.$othercookie);
$_SESSION['reportedflood'] = 1;
}
exit();
}
else $_SESSION['reportedflood'] = 0;
touch($iplogdir.$ipfile, $newtime);
?>
and create a directory called /iplog/ and make it writeable CHOWN 777 (log into webFTP from control panel to do this) (or 755 if that works on your server, but I doubt it!).
create a file in /iplog/ called iplog.dat and CHOWN it 666 (log into webFTP from control panel to do this).
Hope it works, if not I can help as I have about 3 copies all running in different places. I will post another php / htaccess combination here which you could use in unison with this script to automatically permanently ban visitors to are too frequent for your tastes.
Edited by tez on 06/14/06 07:27 PM (server time).