Антиддос скрипты на PHP

Тема в разделе "Защита от Ddos-атак", создана пользователем Devider, 17 авг 2013.

  1. На уровне PHP защищаться от ддоса не эффективно, такие скрипты применяют на хостинг-тарифах, где нет возможности конфигурации сервера. Впрочем, хостеры обычно отключают сайт, если на него идет ДДос, поэтому никакие скрипты вы использовать не успеете.

    Выкладываю некоторые здесь. Если кому помогут - отписывайтесь, вместе посмеемся над этим ддосером.

    Но прежде чем использовать подобные скрипты, надо оценить обстановку.
    Если ваш хостер предоставляет SSH-доступ, попробуйте с помощью команды
    Код:
    netstat -ntu |wc -l
    определить силу ддоса. Команда выведет количество соединений. Если сервер совсем повис, попробуйте перезагрузить его (через службу поддержки или самостоятельно если такая возможность есть) и отрубите апач
    Код:
    service httpd stop
    если у вас nginx
    Код:
    service nginx stop
    либо, если ддос несильный, закоментируйте срочку _index.php в корне вашего сайта. После чего можно поизучать логи и оценить силу и таргетинг ддоса.

    Если ддос действительно слабенький, можно попробовать использовать PHP скрипты, но предупреждаю, они будут загружать сервер и годятся только как временное решение проблемы.


    Скрипт AntiOverload *FIX*
    Код:
    <?php
    /*
    *--------------------------------------------------------
    * Модуль antioverload
    *--------------------------------------------------------
    * Модуль предназначен для ограничения доступа к сайту или 
    * к страницам, где он включён.
    * Принцип работы в том, что запоминается ip-адрес и время
    * обращения с этого адреса. И если в течение заданного
    * времени происходит обращение с того же адреса, то ему
    * выдаётся ошибка 503.
    * Модуль необходимо подключать к скрипту самым первым.
    * Этим обеспечивается быстрота его работы.
    *--------------------------------------------------------
    */
     
    /* Время задержки в секундах */
    $ad_delay=2;
    /* Путь к папке с временными файлами. Должен существовать */
    $ad_DirName=$_SERVER['DOCUMENT_ROOT'].'/tmp';
     
    /*
    *---------------------------------------------------------
    * Список поисковых роботов.
    * Очень не хорошо, если поисковый робот будет натыкаться
    * на ошибки на сайте. Ему это может сильно не понравиться.
    * Поэтому пишем список юзер-агентов роботов; добавляем или
    * удаляем, что нужно.
    *---------------------------------------------------------
    */
    $ad_Robots_UserAgent=array(
      'aipbot',
      'Aport',
      'eStyleSearch',
      'Gigabot',
      'Gokubot',
      'Google',
      'MJ12bot',
      'msnbot',
      'PlantyNet_WebRobot',
      'StackRambler',
      'TurtleScanner',
      'Yahoo',
      'Yandex',
      'YaDirectBot',
    );
    /*
    *---------------------------------------------------------
    * Список доверенных IP.
    *---------------------------------------------------------
    */
    $ad_good_ip = array(
        '217.107.36.73',
    );
     
    /*
    *----------------------------------------------------------
    * Функция создаёт в указанной директории файл, начинающийся
    * с буквы a (для отличия от других возможных файлов) и
    * содержащий в имени ip-адрес клиента.
    *----------------------------------------------------------
    */
    function ad_WiteIP($dir){
      $f=fopen($dir.'/a'.$_SERVER['REMOTE_ADDR'], 'w');
      fclose($f);
    }
    /*
    *----------------------------------------------------------
    * Проверка на наличие в поле HTTP_USER_AGENT чего-нибудь из
    * вышенаписанного списка.
    *----------------------------------------------------------
    */
    $ad_IsRobot=false;
    foreach ($ad_Robots_UserAgent as $match){
      if (strstr($_SERVER['HTTP_USER_AGENT'], $match)){
          $ad_IsRobot=true;
          break;
      }
    }
    if( in_array($_SERVER['REMOTE_ADDR'], $ad_good_ip) ) {
        $good_ip = true;
    } else {
        $good_ip = false;
    }
    /*
    *---------------------------------------------------------
    * Поисковые роботы не любят, когда к адресу страницы
    * добавляется переменная сессии. Поэтому, если на сайте
    * используются сессии, то их лучше включать, если агент -
    * не робот.
    * Если сессии не используются, то этот кусок можно убрать.
    *---------------------------------------------------------
    */
    if (!$ad_IsRobot AND !$good_ip){
      session_start();
    }
     
    if (!$ad_IsRobot AND !$good_ip){
      /*** Чтение каталога и удаление старых файлов ***/
      $ad_dir      =opendir($ad_DirName)
          or die('Отсутствует директория для временных файлов');
      $ad_now      =time();
      $ad_forbid  =$ad_now-$ad_delay;
      /* IP-адрес в имени файла, начинающегося на букву a, 
          а время обращения - время изменения файла */
      while (false!==($ad_FName=readdir($ad_dir))){
          if (ereg('^a[1-9]',$ad_FName)
            && (@ filemtime($ad_DirName.'/'.$ad_FName)<$ad_forbid)){
            @ unlink($ad_DirName.'/'.$ad_FName);
          }
      }
      closedir($ad_dir);
      /*** Проверка на существование пометки
          о недавнем обращении с данного ip-адреса ***/
      if (file_exists($ad_DirName.'/a'.$_SERVER['REMOTE_ADDR'])){
          /* Если обращение было недавно, то выводим сообщение об ошибке */
          header('HTTP/1.0 503 Service Unavailable');
          header('Status: 503 Service Unavailable');
          header('Retry-After: '.$ad_delay*3);
    ?>
    <!doctype html public "-//W3C//DTD HTML 4.01//EN"
    "http://www.w3.org/TR/html4/strict.dtd">
    <html>
    <head>
    <title>Ошибка 503</title>
    <meta http-equiv="Content-Type" content="text/html; charset=Windows-1251" />
    </head>
    <body>
    <h1>Ошибка 503 (Service Unavailable)</h1>
    <p>Сервер не может в данный момент выдать запрашиваемую Вами страницу.
    Попробуйте вызвать эту страницу позже (клавиша F5).</p>
    </body>
    </html>
    <?php
          ad_WiteIP($ad_DirName);  // Перед выходом записываем ip
          exit;
      }else{
          ad_WiteIP($ad_DirName);
      }
    }
    ?>
    Антиддос скрипт от админа xaknet.ru:

    Код:
    <?php
     
    class antiDdos
    {
        // дебаг
        public $debug = false;
        // директория для хранения файлов индефикации запросов
        public $dir = '_bots/';
        // номер icq администратора
        public $icq = '123456';
        // сообщение при выключенном сайте
        public $off_message = 'Временные неполадки, пожалуйста, подождите.';
        // индивидуальный индефикатор
        private $indeficator = null;
        // сообщение при бане, работают шаблоны, можно использовать - {ICQ}, {IP}, {UA}, {DATE}
        public $ban_message = 'Вы были заблокированы antiddos системой.
                              Если это ошибка обратитесь к администратору, icq of admin: {ICQ}
                              <hr>(c)XakNet antiddos module, ваш IP - {IP}(<i>{UA}</i>), date - {DATE}';
        // команда выполнения бана в файрволле
        public $exec_ban = 'iptables -A INPUT -s {IP} -j DROP';
        // тип защиты от ддоса:
        /* Возможные значения $ddos 1-5: 
        | 1. Простая проверка по кукам, по умолчанию(рекомендую)   
        | 2. Двойная проверка через $_GET antiddos и meta refresh   
        | 3. Запрос на авторизацию WWW-Authenticate   
        | 4. полное отключение сайта, боты не блокируются!!!   
        | 5. выключать сайт если нагрузка слишком большая на сервере, боты не блокируются!!!   
        */ 
        var $ddos = 1;
        // часть домена поисковых ботов, см strpos()
        private $searchbots = array('googlebot.com', 'yandex.ru', 'ramtel.ru', 'rambler.ru', 'aport.ru', 'sape.ru', 'msn.com', 'yahoo.net');
        // временная переменные нужные для работы скрипта
        private $attack = false;
        private $is_bot = false;
        private $ddosuser;
        private $ddospass;
        private $load;
        public $maxload = 80;
       
        function __construct($debug)
        {
            @session_start() or die('session_start() filed!');
            $this->indeficator = md5(sha1('botik' . strrev(getenv('HTTP_USER_AGENT'))));
            $this->ban_message = str_replace(array('{ICQ}', '{IP}', '{UA}', '{DATE}'), 
                                            array($this->icq, $_SERVER['REMOTE_ADDR'], $_SERVER['HTTP_USER_AGENT'], date('d.m.y H:i')),
                                            $this->ban_message
                                            );
            if (eregi(ip2long($_SERVER['REMOTE_ADDR']), file_get_contents($this->dir . 'banned_ips')))
                die($this->ban_message);
            $this->exec_ban = str_replace('{IP}', $_SERVER['REMOTE_ADDR'], $this->exec_ban);
            $this->debug = $debug;
            if(!function_exists('sys_getloadavg'))
            {
                function sys_getloadavg()
                {
                    return array(0,0,0);
                }
            }
            $this->load = sys_getloadavg();
            if(!$this->sbots())
            {
                $this->attack = true;
                $f = fopen($this->dir . ip2long($_SERVER["REMOTE_ADDR"]), "a"); 
                fwrite($f, "query\n"); 
                fclose($f); 
            }
        }
       
        /**
        * Старт работы антиддоса
        **/
        function start()
        {
            if($this->attack == false)
                return;
            switch($this->ddos)
            {
                case 1:
                    $this->addos1();
                    break;
                case 2:
                    $this->addos2();
                    break;
                case 3:
                    $this->ddosuser = substr(ip2long($_SERVER['REMOTE_ADDR']), 0, 4);
                    $this->ddospass = substr(ip2long($_SERVER['REMOTE_ADDR']), 4, strlen(ip2long($_SERVER['REMOTE_ADDR'])));
                    $this->addos3();
                    break;
                case 4:
                    die($this->off_message);
                    break;
                case 5:
                    if ($this->load[0] > $this->maxload) 
                    {
                        header('HTTP/1.1 503 Too busy, try again later'); 
                        die('<center><h1>503 Server too busy.</h1></center><hr><small><i>Server too busy. Please try again later. Apache server on ' . $_SERVER['HTTP_HOST'] . ' at port 80 with <a href="http://forum.xaknet.ru/">ddos protect</a></i></small>'); 
                    } 
                    break;
                default:
                    break;
            }
            if ($_COOKIE['ddos'] == $this->indeficator) 
                @unlink($this->dir . ip2long($_SERVER["REMOTE_ADDR"])); 
        }
       
        /**
        * Функция проверяет не является ли клиент поисковым ботом
        **/
        function sbots()
        {
            $tmp = array();
            foreach($this->searchbots as $bot)
            {
                $tmp[] = strpos(gethostbyaddr($_SERVER['REMOTE_ADDR']), $bot) !== false;
                if($tmp[count($tmp) - 1] == true)
                {
                    $this->is_bot = true;
                    break;
                }
            }
            return $this->is_bot;
        }
       
        /**
        * Функция бана
        **/
        private function ban()
        {
            if (! system($this->exec_ban))
            { 
                $f = fopen($this->dir . 'banned_ips', "a"); 
                fwrite($f, ip2long($_SERVER['REMOTE_ADDR']) . '|'); 
                fclose($f); 
            }
            die($this->ban_message); 
        }
        /**
        * Первый тип защиты
        **/
        function addos1()
        {
            if (empty($_COOKIE['ddos']) or !isset($_COOKIE['ddos'])) 
            { 
                $counter = @file($this->dir . ip2long($_SERVER["REMOTE_ADDR"]));
                setcookie('ddos', $this->indeficator, time() + 3600 * 24 * 7 * 356); // ставим куки на год.
                if (count($counter) > 10) { 
                    if (! $this->debug)
                        $this->ban(); 
                    else 
                        die("Блокированы."); 
                } 
                if (! $_COOKIE['ddos_log'] == '1') 
                { 
                    if (! $_GET['antiddos'] == 1) 
                    { 
                        setcookie('ddos_log', '1', time() + 3600 * 24 * 7 * 356); //чтоб не перекидывало постоянно рефрешем. 
                        if(headers_sent())
                            die('Header already sended, check it, line '.__LINE__);
                        header("Location: ./?antiddos=1"); 
                    } 
                } 
            } elseif ($_COOKIE['ddos'] !== $this->indeficator) 
            { 
                if (! $this->debug) 
                    $this->ban(); 
                else 
                    die("Блокированы."); 
            } 
        }
       
        /**
        * Второй тип защиты
        **/
        function addos2()
        {
            if (empty($_COOKIE['ddos']) or $_COOKIE['ddos'] !== $this->indeficator) 
            {
                if (empty($_GET['antiddos'])) 
                { 
                    if (! $_COOKIE['ddos_log'] == '1') 
                        //проверям есть ли запись в куках что был запрос 
                        die('<meta http-equiv="refresh" content="0;URL=?antiddos=' . $this->indeficator . '" />'); 
                } elseif ($_GET['antiddos'] == $this->indeficator) 
                { 
                    setcookie('ddos', $this->indeficator, time() + 3600 * 24 * 7 * 356); 
                    setcookie('ddos_log', '1', time() + 3600 * 24 * 7 * 356); //типо запрос уже был чтоб не перекидывало постоянно рефрешем. 
                } 
                else 
                { 
                    if (!$this->debug) 
                        $this->ban(); 
                    else 
                    { 
                        echo "May be shall not transform address line?"; 
                        die("Блокированы."); 
                    } 
                } 
            } 
        }
       
        /**
        * Третий тип защиты
        **/
        function addos3()
        {
            if (! isset($_SERVER['PHP_AUTH_USER']) || $_SERVER['PHP_AUTH_USER'] !== $this->ddosuser || $_SERVER['PHP_AUTH_PW'] !== $this->ddospass) 
            { 
                header('WWW-Authenticate: Basic realm="Vvedite parol\':  ' . $this->ddospass . ' | Login: ' . $this->ddosuser . '"'); 
                header('HTTP/1.0 401 Unauthorized'); 
                if (! $this->debug) 
                    $this->ban(); 
                else 
                    die("Блокированы."); 
                die("<h1>401 Unauthorized</h1>"); 
            }
        }
    }
    /*
    // Exmaple
    $ad = new antiDdos(false);
    $ad->dir = 'bots/';
    $ad->ddos = 2;
    $ad->start();
    */
    ?>

    Скрипт Boolean

    Код:
    <?php 
    #(c) Boolean. 
    ##################################################################################### 
    ##################################################################################### 
    ##################################################################################### 
    ##################################################################################### 
     
    $config['time']                = 2; 
    #Время обращения к скрипту, после которого будет(возможно) выдан бан. 
    $config['countaban']            = 5; 
    #количество возможных нарушений времени обращения, такая возможность введена для более детально точного отделения пользователей от атакующих ботов. 
    $config['directory']            = '_temp'; 
    #временна директория, должна существовать, и иметь права на запись. 
    $config['checkmask']            = 'check'; 
    #маска для проверки, не стоит трогать. 
    $config['banmask']              = 'ban'; 
    #маска для бана, не стоит трогать. 
     
    #Комманды после нарушения времени и кол-ва обращений. Используйте константу [IP] - IP Бота. 
    $config['commands'][]          = 'iptables -A ISPMGR -s [IP] -j DROP'; 
    $config['commands'][]          = 'iptables -I INPUT -s [IP] -j DROP'; 
     
    #Доверенные IP. 
    $config['white']['ip']          = @file('whiteips.txt'); 
    #Доверенные ЮзерАгенты. 
    $config['white']['useragent'][] = 'Google bot'; 
    $config['white']['useragent'][] = 'Yasha bot'; 
     
    #Сообщение для пользователя. HTML Работает. 
    $config['message']              = file_get_contents("ddosmessage.html"); 
     
    ##################################################################################### 
    ##################################################################################### 
    ##################################################################################### 
    ##################################################################################### 
     
    $ip                            = $_SERVER['REMOTE_ADDR']; 
    $useragent                      = $_SERVER['HTTP_USER_AGENT']; 
    if ( ! is_dir($config['directory']) ) 
        exit("Temp directory not found."); 
     
    if ( ! is_writable($config['directory']) ) 
        exit("Temp directory is not writable."); 
     
    if ( @in_array($ip,$config['white']['ip']) || @in_array($useragent,$config['white']['useragent']) ) 
        $white = true; 
     
    if ( ! $white ){ 
         
        if ( file_exists( $config['directory'] . "/" . $config['checkmask'] . $ip ) ){         
             
            $time = filemtime($config['directory'] . "/" . $config['checkmask'] . $ip); 
     
            $f=fopen( $config['directory'] . "/" . $config['checkmask'] . $ip , 'w' ); 
            fclose($f); 
                     
            if ($time >= time() - $config['time']){ 
                 
                if (file_exists($config['directory'] . "/" . $config['banmask'] . $ip)){ 
                     
                    $count = file_get_contents($config['directory'] . "/" . $config['banmask'] . $ip); 
                    if ($count >= $config['countaban']){             
                        for($i = 0; $i <= count($config['commands']) - 1; $i++) 
                            @system(str_replace("[IP]",$ip,$config['commands'][$i]));                     
                    }else{ 
                        $time = filemtime($config['directory'] . "/" . $config['banmask'] . $ip); 
                        if ($time >= time() - $config['time']){ 
                            $count++; 
                            $f=fopen( $config['directory'] . "/" . $config['banmask'] . $ip , 'w' ); 
                            fwrite($f,$count); 
                            fclose($f); 
                        }else{ 
                            $f=fopen( $config['directory'] . "/" . $config['banmask'] . $ip , 'w' ); 
                            fwrite($f,"1"); 
                            fclose($f);                         
                        } 
                    }       
                         
                }else{ 
                    $f=fopen( $config['directory'] . "/" . $config['banmask'] . $ip , 'w' ); 
                    fwrite($f,"0");   
                    fclose($f); 
                } 
     
                exit($config['message']); 
            } 
             
        }else{     
            $f=fopen( $config['directory'] . "/" . $config['checkmask'] . $ip , 'w');     
            fclose($f);     
        }   
           
    }   
    ?>
     
    17 авг 2013
    Seruy нравится это.
  2. Подскажите пожалуйста где и какую дерикторию создать для скрипта AntiOverload. Я создал DOCUMENT_ROOT в папке tmp и ничего. Пробовал в корневой папке сайта и в папке Punlick_HTML, и в папке php всё в бестолку - пишет не найдена временная папка
     
    3 авг 2014
  3. Скрипт нужно инклюдить в исполняемый файл, в index.php, например.

    Создаем файл, допустим, antiddos.php, туда копируем любой код из вышеприведенных, затем в файле index.php пишем вверху:
    PHP:
    include("antiddos.php");

    exit; 
    // нужно дать скрипту побанить ботов некоторое время, а потом можно закомментировать exit.

    Список забаненных IP, пожалуйста, оставляйте у нас на форуме. Мы будем делать базы.
     
    Последнее редактирование: 8 авг 2014
    8 авг 2014
  4. У меня вопрос по Антиддос скрипт от админа xaknet.ru

    // директория для хранения файлов индефикации запросов
    public $dir = '_bots/';

    Ето нужно создать папку _bots и положить в корень? И нужен ли слеш / в конце?
    И нужно ли в папке _bots создавать какие то файлы или скрипт сам создаст?
     
    8 фев 2016
  5. Я правильно понял, ети скрипты нужно подключать во всремя атаки а не все время они должны быть на сайте?
    у меня если exit; не закомментирован то сайт не работает! Так и должно быть?
     
    8 фев 2016
  6. Скрипты это бред, настраивайте фаервол.
     
    9 фев 2016
  7. Не такой уж и бред. Их можно в совокупности с файерволлом использовать для тех, кто в администрировании не очень силен.
    Если ддос не сильный можно вывесить проверку на бота.

    Алгоритм следующий.
    Сначала делаем проверку на поискового бота по юзер агенту. Если поисковой бот, то пускаем на сайт. Для остальных вывешиваем заглушку подобно той, что у CloudFlare. Можно просто ссылками: при слабых ддос атаках боты глупые (иногда у них одинаковые юзер агента или вообще юзер агентов нет, что сильно облегчает нам работу). Все, кто нажал по ссылке "я не бот" добавляются в белый список. Через какое-то время заносим скриптом все IP черного списка в iptables, а потом из iptables удаляем ip из белого списка. Либо сохраняем ip не бота в сессию и удаляем его из черного списка.
     
    13 май 2018

Поделиться этой страницей