Вход Регистрация
Файл: archive/www/musimka.ru/antiddos.php
Строк: 180
<?php
/*
   =================================================================
              _DIMA_NOFLOOD.PHP, version 1.1, 2002-11-11
   =================================================================

   (c) Dmitry Borodin
   Homepage: http://php.spb.ru/
   Report bugs: dima@php.spb.ru

   Что это:

      Модуль защиты от флуда PHP-сайтов методом частых вызовов
      PHP-файлов, для создания большой нагрузки. Защищает так же
      от автоматического выкачивания сайта с одного IP.

   =================================================================

   Описание
   ~~~~~~~~
   Для подключения этого модуля напишите include $_SERVER['DOCUMENT_ROOT'].'/antiddos.php';
   в самом начале вашей программы. В случае флуда этот модуль завершит
   работу по команде exit. При нормальной работе - только увеличит
   счетчики загрузок и никак не отразится на вашем скрипте.

   Для настройки программы создайте сколько угодно правил на разное
   кол-во секунд. Например, первое правило "не более 11 загрузок за 10
   секунд" надо записать как "$nf_flood[10]=>11". Если хочется второе
   правило, допустим "не более 200 загрузок за час", то
   дополнительно в тот же массив надо дописать "$nf_flood[3600]=>200"
   (3600 - это 1 час). Правил может быть любое кол-во (но чем меньше,
   тем быстрее работает).

   Если по какому либо правилу возникает флуд, т.е. кол-во загрузок
   за последние Х секунд превысило N заданных раз, то происходит
   следующее:
   1. доступ для этого IP-адреса закрывается
   2. остальные правила как считали, так и продолжают считать/следить
      за допустимой нагрузкой
   3. сработавшее на флуд правило запоминает текущее время каждого
      обращения, из-за чего при регулярных продолжениях вызовов сайта
      этот счетчик не будет никогда сброшен
   Сработавшее флуд-правило очистит счетчик запросов, т.е. снимет игнор,
   только если в течении Х секунд к сайту не будет ни одного запроса.
   Если сработало правило флуда на 5 минут, то пользователь-флудер
   должен покинуть ваш сайт минимум на 5 минут. Если этот пользователь
   обратится через 4 минуты на сайт, то время окончания игнора повторно
   увеличится на 5 минут. Таким образом, это очень продвинута защита от
   скачиваний - стоит программе превысить любое из правил флуда,
   то повторные попытка что-то скачать только оттянут время снятия
   игнора. Дополнительно это приведет к срабатыванию более строгих
   правил, например на 60 минут (и придется уже минимум 60 минут
   не обращаться к сайту, чтобы игнор был сброшен).

   Раз в $nf_cron_run секунд запускается функция поиска старых файлов,
   которые устарели не менее, чем на $nf_old_file секунд. По-умолчанию,
   поиск производится раз в 20 минут, при котором стираются все файлы,
   которые устарели минимум на 2 часа. Внимание! Программа стирает ВСЕ
   файлы в своем каталоге ($nf_path), которые не начинаются с ".".
   Поэтому, чтобы закрыть каталог от доступа через браузер, положите
   туда файл ".htaccess" из 2х строк:
       Order Allow,Deny
       Deny from all

   Кроме проверки на флуд программа не позволит вызвать ни одного
   вашего PHP-скрипта параллельно. Т.е. если идет параллельный вызов,
   а старый вызов (и процесс с PHP-скриптом) еще не закончился,
   то более новый запрос будет отвергнут. Это достигается простым
   открытием файла. Файл после открытия не закрывается, из-за чего
   остается блокированным на весь период работы вашего скрипта.

   Сообщения/ошибки:
   - в случае параллельного вызова программа пишет
     "Parallel processing disable." и завершает работу
   - при достижении флуда программа пишет "Flood detect!" и завершается
   - если невозможно открыть файл на запись/чтение, то программа пишет
     короткое имя файла (без каталога) и причину, работа не прерывается,
     т.е. ваш скрипт получит управление (такие ошибки возможны только
     при первоначальной настройке программы)

   Когда вы меняете набор флуд правил в $nf_flood, то сразу после этого
   стирайте все файла в каталоге $nf_path!

   =================================================================
*/

   //
   // Путь к каталогу, где будут копится файлы
   // В этом каталоге будут стерты все файлы, кроме тех, что начинаются
   // с "." в имени.
   //
   // ОБЯЗАТЕЛЬНО ЗАДАЙТЕ КАТАЛОГ ДЛЯ ВРЕМЕННЫХ ФАЙЛОВ:
   //
   //$nf_path='/tmp/';

   //exit(getcwd());
   
$nf_path=$_SERVER['DOCUMENT_ROOT'].'/tmp/';

   
// имя файла для юзера - генерится из его IP-адреса
   
$nf_fip=$nf_path.$_SERVER['REMOTE_ADDR'];

   
// имя файла для встроенного крона (должно начинаться с точки)
   
$nf_fcron=$nf_path.'.time';

   
//
   // сек  => кол-во
   //
   //    не более скольки загрузок за сколько секунд можно сделать,
   //    чтобы не получить игнор
   //
   
$nf_flood=array(
      
10   => 10,      // не более 10 загрузок за 10 секунд
      
60   => 30,      // не более 30 загрузок за минуту
      
300  => 50,      // не более 50 загрузок за 5 минут       3600 => 200,     // не более 200 загрузок за час        10000000 => 200,     // не более 20000 загрузок за час
   
);

   
$nf_cron_run=1200// раз в сколько секунд проверять старые файлы

   
$nf_old_file=7200// через сколько секунд считать файл старым (и удалять)



/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */



function cron_update($fn,$update) {

   if (!
file_exists($fn)) {
      if (!@
touch($fn)) {
         echo 
'не могу создать <strong>'.basename($fn).'</strong>, проверьтЕ права на файлы (w+)<br/>';
         return -
1;
      }
   }
   else {
      if (
time()-filemtime($fn)<$update) {return 0;}
   }

   
$f=@fopen($fn,'r+');
   if (!
$f) {
      echo 
'не могу открыть <strong>'.basename($fn).'</strong>, проверьте права на файлы (r+)<br/>';
      return -
1;
   }
   if (!
flock($f,6)) {return;}
   
$text=fgets($f,100);
   if (
time()-intval($text)<$update) {return 0;}
   
fseek($f,0,SEEK_SET);
   
fwrite($f,time().'    ');
   
fclose($f);

   return 
1;

}


   
$nf_cron_code=cron_update($nf_fcron,$nf_cron_run);
   if (
$nf_cron_code==-1) return;
   if (
$nf_cron_code==1) {
      if (
$nf_dir=@opendir($nf_path)) {
         
$nf_time=time()-$nf_old_file;
         while ((
$nf_tmp=readdir($nf_dir))!==false) {
            if (
$nf_tmp[0]=='.') continue;
            if (
filemtime($nf_path.$nf_tmp)<$nf_time &&
               
preg_match("!^[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}$!",$nf_tmp))
            {
               if (!
unlink($nf_path.$nf_tmp)) {
                  echo 
'не могу удалить <trong>'.$nf_tmp.'</strong><br/>';
               }
            }
         }
         
closedir($nf_dir);
      }
   }
   unset(
$nf_cron_code);


   if (
file_exists($nf_fip)) {
      
$nf_f=@fopen($nf_fip,'r+');
      if (!
flock($nf_f,6)) exit('Parallel processing disable.');
      if (!
$nf_f) {
         echo 
'не могу открыть <strong>'.basename($nf_fip).'</strong> (r+)<br/>';
         return;
      }
      
$nf_buf=fgets($nf_f,1000);
      
$nf_buf=explode('|',$nf_buf);
   }
   else {
      for(
$nf_i=0$nf_i<count($nf_flood)*2$nf_i++) $nf_buf[]=0;
      
$nf_f=@fopen($nf_fip,'a+');
      if (!
$nf_f) {
         echo 
'не могу создать <strong>'.basename($nf_fip).'</strong> (a+)<br/>';
         return;
      }
      if (!
flock($nf_f,6)) exit('Parallel processing disable.');
   }


   
$nf_i=0;
   
$nf_stopflag=0;

   
//echo "<pre>";print_r($nf_buf);

   
foreach ($nf_flood as $nf_k=>$nf_v) {
      if (
$nf_buf[$nf_i+1]+$nf_k<time()) {
         
$nf_buf[$nf_i]=1;
         
$nf_buf[$nf_i+1]=time();
      }
      else {
         if (
$nf_buf[$nf_i]>$nf_v) {
            
$nf_stopflag=1;
            
$nf_buf[$nf_i+1]=time();
         }
         
$nf_buf[$nf_i]++;
      }
      
$nf_i+=2;
   }


   
ftruncate($nf_f,0);
   
fseek($nf_f,0);
   
fputs($nf_f,implode('|',$nf_buf));

   
//print_r($nf_buf);
//   if ($nf_stopflag) exit('<h1>Решил ДДОС пропихнуть? На сайте стоит  защита от ДДОС. Я слежу за тобой! Зайду буду  логи смотреть! by GOLD_SPACES</h1>');

   
unset($nf_f);
   unset(
$nf_i);
   unset(
$nf_k);
   unset(
$nf_v);
   unset(
$nf_stopflag);
   unset(
$nf_buf);
   unset(
$nf_fip);
   unset(
$nf_path);
   unset(
$nf_flood);
   unset(
$nf_cron_run);
   unset(
$nf_cron_idle);

?>
Онлайн: 1
Реклама