Цитата мудреца

Голосование

Вегетарианство
 
Система Orphus. Если вы заметили ошибку на сайте, нажмите сюда.
Загружается, подождите...
Начало сайта Материалы сайта Программы PHP-скрипты
Версия для слабовидящих
Версия для печати

Ограничение на скорость выдачи страниц одному пользователю

Здесь представлены некоторые мои разработки на PHP. Это в, основном, служебные скрипты, которые работают в составе других скриптов и не могут быть протестированы здесь непосредственно.

Модуль с этим кодом нужно вставлять в самом начале каждой страницы.


Скажите пожалуйста, а где прописывать этот скрипт в форуме phpBB ?
Ответить


Marinera писал(а):Скажите пожалуйста, а где прописывать этот скрипт в форуме phpBB ?

Вызов модуля с этим скриптом нужно делать в самом начале каждого вызываемого пользователем файла php, который Вы хотите ограничить. Т.е. index.php, viewtopic.php и т.п. Не обязательно вставлять этот модуль туда, где по определению нет большого наплыва, например, в админский интерфейс.
Ответить


Yakushev писал(а):
Marinera писал(а):Скажите пожалуйста, а где прописывать этот скрипт в форуме phpBB ?

Вызов модуля с этим скриптом нужно делать в самом начале каждого вызываемого пользователем файла php, который Вы хотите ограничить. Т.е. index.php, viewtopic.php и т.п. Не обязательно вставлять этот модуль туда, где по определению нет большого наплыва, например, в админский интерфейс.


спасибо большое!
Я в них (index.php, viewtopic.php) как раз вчера и поставила :-)
Ответить


В связи с ошибкой, появляющейся в работе скрипта, ограничивающего выдачу страниц, несколько изменился его принцип действия - вышла вторая версия.
Ответить


Здравствуйте, Андрей.

Спасибо за Ваш скрип. Скажите, пожалуйста,

/* Время задержки в секундах */
$ad_delay=3;


можно ли выставить задержку в 1 секунду, т.е. установить $ad_delay=1? Если не секрет, почему Вы выбрали именно 3 секунды?
Ответить


Kio писал(а):можно ли выставить задержку в 1 секунду, т.е. установить $ad_delay=1? Если не секрет, почему Вы выбрали именно 3 секунды?

Конечно можно.
3 секунды - это среднее время, за которое выведется страница и посетитель найдёт глазами новую ссылку, чтобы нажать. Уменьшение времени задержки - увеличивает возможности для скачивающих программ.
Ответить


Yakushev

Понял, спасибо. Попробую пока поставить 1 секунду, если письма от PeterHost'а (компания предоставляющая мне хостинг) о высокой нагрузке будут приходить снова (и это будет связано с выкачиванием сайта), придется увеличивать время задержки :roll:.
Ответить


здравствуйте.
знакомое лицо по-моему :)
не подскажите почему скрипт может не работать на иностранных хостингах без русского apache и т.д. (хостинг большой и удобный). Может ли быть дело в кодировке? Требует ли скрипт включения всех фунцкий safe mode=off?
Спасибо!


кстати, нашел еще такой скрипт (ручная проверка на человек/робот)

К примеру, создадим каталог anti_ddos и кидаем все скрипты туда:

anti_ddos.php (модуль обнаружения DDOS атаки):
PHP код:
Код: Выделить всё
<?php 

$ad_ddos_query=10; // количество запросов в секунду для обнаружения DDOS атаки 
$ad_check_file='check.txt'; // файл для записи текущего состояния во время мониторинга 
$ad_temp_file='all_ip.txt'; // временный файл 
$ad_black_file='black_ip.txt'; // будут заносится ip машин зомби 
$ad_white_file='white_ip.txt'; // заносятся ip посетителей 
$ad_dir='anti_ddos'; // каталог со скриптами 
$ad_num_query=0; // текущее количество запросов в секунду из файла $check_file 
$ad_sec_query=0; // секунда из файла $check_file 
$ad_end_defense=0; // время окончание защиты из файла $check_file 
$ad_sec=date("s"); // текущая секунда 
$ad_date=date("mdHis"); // текущее время 
$ad_defense_time=10000; // при обнаружении ddos атаки время в секундах на которое прекращается мониторинг 



if(!file_exists("{$ad_dir}/{$ad_check_file}") or !file_exists("{$ad_dir}/{$ad_temp_file}") or !file_exists("{$ad_dir}/{$ad_black_file}") or !file_exists("{$ad_dir}/{$ad_white_file}") or !file_exists("{$ad_dir}/anti_ddos.php")){ 
die("Не хватает файлов."); 


require("{$ad_dir}/{$ad_check_file}"); 

if ($ad_end_defense and $ad_end_defense>$ad_date){ 
require("{$ad_dir}/anti_ddos.php"); 
} else { 
if($ad_sec==$ad_sec_query){ 
$ad_num_query++; 
} else { 
$ad_num_query='1'; 


if ($ad_num_query>=$ad_ddos_query){ 
$ad_file=fopen("{$ad_dir}/{$ad_check_file}","w"); 
$ad_end_defense=$ad_date+$ad_defense_time; 
$ad_string='<?php $ad_end_defense='.$ad_end_defense.'; ?>'; 
fputs($ad_file,$ad_string); 
fclose($ad_fp); 
} else { 
$ad_file=fopen("{$ad_dir}/{$ad_check_file}","w"); 
$ad_string='<?php $ad_num_query='.$ad_num_query.'; $ad_sec_query='.$ad_sec.'; ?>'; 
fputs($ad_file,$ad_string); 
fclose($ad_fp); 


?>




anti_ddos.php (модуль погашения DDOS атаки):
PHP код:
Код: Выделить всё
<?php 
function getIP() { 
if(getenv("HTTP_CLIENT_IP") and preg_match("/^[0-9\.]*?[0-9\.]+$/is",getenv("HTTP_CLIENT_IP")) and getenv("HTTP_CLIENT_IP")!='127.0.0.1') { 
$ip = getenv("HTTP_CLIENT_IP"); 
} elseif(getenv("HTTP_X_FORWARDED_FOR") and preg_match("/^[0-9\.]*?[0-9\.]+$/is",getenv("HTTP_X_FORWARDED_FOR")) and getenv("HTTP_X_FORWARDED_FOR")!='127.0.0.1') { 
$ip = getenv("HTTP_X_FORWARDED_FOR"); 
} else { 
$ip = getenv("REMOTE_ADDR"); 

return $ip; 

$ad_ip=getIP(); 

$ad_source=file("{$ad_dir}/{$ad_black_file}"); 
$ad_source=explode(' ',$ad_source[0]); 
if (in_array($ad_ip,$ad_source)){die();} 

$ad_source=file("{$ad_dir}/{$ad_white_file}"); 
$ad_source=explode(' ',$ad_source[0]); 
if (!in_array($ad_ip,$ad_source)){ 

$ad_source=file("{$ad_dir}/{$ad_temp_file}"); 
$ad_source=explode(' ',$ad_source[0]); 
if (!in_array($ad_ip,$ad_source)){ 
$ad_file=fopen("{$ad_dir}/{$ad_temp_file}","a+"); 
$ad_string=$ad_ip.' '; 
fputs($ad_file,"$ad_string"); 
fclose($ad_fp); 
?>

Сайт в данный момент подвергается DDOS атаке, если Вы не машина-зомби атакующая сайт нажмите на кнопку, иначе Ваш IP (<?=$ad_ip?>) будет заблокирован!!! 
<form method="post"> 
<input type="submit" name="ad_white_ip" value="Кнопка"> 
</form> 

<?php 
die(); 

elseif ($_POST['ad_white_ip']){ 
$ad_file=fopen("{$ad_dir}/{$ad_white_file}","a+"); 
$ad_string=$ad_ip.' '; 
fputs($ad_file,"$ad_string"); 
fclose($ad_fp); 

else { 
$ad_file=fopen("{$ad_dir}/{$ad_black_file}","a+"); 
$ad_string=$ad_ip.' '; 
fputs($ad_file,"$ad_string"); 
fclose($ad_fp); 
die(); 


?>

Также для работы скрипта понадобятся 4 файла check.txt, white_ip.txt, black_ip.txt и all_ip.txt создаем их в этом же каталоге и на все ставим права 666 (чтение и запись).

Желательно также во время атаки списки IP адресов атакующих машин формирующихся в файле black_ip.txt переносить постепенно в файл .htaccess и блокировать их оттуда, тогда нагрузка еще значительно снизится.

Пример файла .htaccess
Код:
Deny from 11.11.11.11 22.22.22.22 и т.д. через пробел



Да чуть не забыл, для подключения скрипта, в начале каждого файла, который может быть подвергнут атаке добавляем строчку:
Код:
Код: Выделить всё
<? require("anti_ddos/index.php"); ?>
Ответить


filip писал(а):здравствуйте.
знакомое лицо по-моему :)

Здравствуйте. Не знаю, не знаю...

filip писал(а):не подскажите почему скрипт может не работать на иностранных хостингах без русского apache и т.д. (хостинг большой и удобный). Может ли быть дело в кодировке? Требует ли скрипт включения всех фунцкий safe mode=off?
Спасибо!

Надо смотреть, почему не работает. Есть ли какие-нибудь системные сообщения?


filip писал(а):кстати, нашел еще такой скрипт (ручная проверка на человек/робот)

Спасибо за скрипт.
Только тяжеловат он. Я написал вторую версию скрипта, где отказался от чтения файла и перешёл на чтение каталога. Эта операция работает быстрее. Просто когда идёт большая нагрузка, сам скрипт начинает тормозить и увеличивать нагрузку на сервер.
Кстати, проверьте, какую версию Вы пробуете.
Ответить


вот еще известный скрипт

Код: Выделить всё
<?
/*


   Что это:

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

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

   Описание
   ~~~~~~~~
   Для подключения этого модуля напишите include("noflood.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=getenv("DOCUMENT_ROOT")."/tmp-ip/";

   //exit(getcwd());
   $nf_path="/absolut/parh/to/your/account/tmp-ip/";

   // имя файла для юзера - генерится из его IP-адреса
   $nf_fip=$nf_path.getenv("REMOTE_ADDR");

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

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

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

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



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


function cron_update($fn,$update) {

   if (!file_exists($fn)) {
      if (!@touch($fn)) {
         echo "не могу создать <b>".basename($fn)."</b>, проверьте права на файлы (w+)<br>";
         return -1;
      }
   }
   else {
      if (time()-filemtime($fn)<$update) {return 0;}
   }
   
   $f=@fopen($fn,"r+");
   if (!$f) {
      echo "не могу открыть <b>".basename($fn)."</b>, проверьте права на файлы (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 "не могу удалить <b>$nf_tmp</b><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 "не могу открыть <b>".basename($nf_fip)."</b> (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 "не могу создать <b>".basename($nf_fip)."</b> (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("Flood detect!");
   
   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);

?>


тк ваш скрипт почему то не на всех хостингах работает пользуюсь этим. права на папку для временных файлов 777 на .time тоже. нет разделения для поисковиков поэтому нужно выставлять интервалы тщательней...
Ответить


След.

Вернуться в PHP-скрипты



Кто сейчас на сайте

Зарегистрированные пользователи: Yahoo [Bot], Yandex [bot]