• Форум посвящен самостоятельной (бесплатной) защите от ддос атак.
    Есть мануалы по настройке сервера от Ddos для сисадминов и готовые инструменты от ддос-атак для вебмастеров.

    Простое, эффективное, точное и проверенное бесплатное решение от мощных ддос-атак: PHP скрипт + Cloudflare, с панелью управления.

Быстрый php-скрипт для защиты от мощных ддос атак

admin

admin

Администратор
Администрация
#1
PHP-скрипт для защиты от ддос, способный противостоять даже сильным ддос-атакам, благодаря связке с iptables или Cloudflare.
Информация по обновлениям внизу темы.

Внимание данная версия скрипта больше не поддерживается. Доступна для скачивания здесь https://github.com/Roscenzura-com/antiddos-old
По ссылке https://github.com/Roscenzura-com/antiddos выложена новая версия скрипта, тема поддержки: https://ddosforum.com/threads/1045/

Внимание! Любые вопросы по работе и установке скрипта пишите в теме! Оперативно отвечаю.
Приватные консультации только после платной установки скрипта.


Алгоритм работы скрипта с iptables
  • IP проверяется на принадлежность к поисковому боту. Если это поисковой бот, то добавляем в исключения и пускаем на сайт (больше не проверяем).

  • Если IP обращается к странице слишком часто (кол-во обращений в минуту регулируется в настройках), то показывается капча (при желании, можно прикрутить гугл капчу).

  • Если каптча не пройдена, последующие обращения к сайту блокируются.

Алгоритм работы скрипта с Cloudflare
  • Проверка ip на бота и на подлинность.

  • Если IP обращается к странице слишком часто (кол-во обращений в минуту регулируется в настройках), то IP добавляется в файрвол Cloudflare. В соответствии с настройками, выставляется капча (challenge) или блок. В зависимости от настроек: IP больше не сможет попасть на сайт или сможет, после прохождения капчи Cloudflare.
Я рекомендую Cloudflare, особенно если у вас маленькая впс-ка, во избежании риска отключения хостером за превышение нагрузки. К тому же, возможны другие типы атак на ваш сервер, а через Cloudflare вы можете спрятать свой IP.


В версии от 31.05.2022 добавлена функция автоматической приостановки работы сайта в случае ддос атаки (режим "Под атакой"). Как только боты будут заблокированы и нагрузка спадет, работа сайта автоматически восстановится.

Алгоритм работы режима "Под атакой" (включается в настройках)
  • В случае превышения лимита общего числа обращений к сайту (за минуту), показывается заглушка "сайт под ддос атакой, зайдите попозже".

  • Все IP, превысившие лимит, попадают в бан. В отличии от обычного режима, лимит считается для всех обращений каждого IP к сайту, а не для каждой отдельной страницы (обычный пользователь не будет перемещаться по разным страницам сайта, пока сайт отключен, таким образом, можно установить лимит обращений небольшой).

  • Как только общее число обращений к сайту станет ниже установленного лимита, работа сайта восстанавливается.

Режим "Под атакой" был добавлен для борьбы с "умным ддосом", когда боты стараются имитировать поведение обычного пользователя.


В чем преимущество php-скрипта над bash скриптом?
  • bash скрипт будет выполняться не чаще раза в минуту, а php скрипт обновляет счетчик при каждом обращении. Таким образом, бот будет забанен сразу, как только исчерпает разрешенный лимит, хоть через 5 секунд.
  • bash скрипту приходится анализировать лог, что ресурсоемкая операция, а php скрипт только обновляет счетчик в файле, который создается по хешу запроса: md5($_SERVER['REMOTE_ADDR'].$_SERVER['REQUEST_URI'].$_SERVER['HTTP_USER_AGENT'].date("mdhi"))
  • При работе через Cloudflare в заголовках передается страна и вы сможете задать для нужных стран лимиты помягче, а для не целевых стран, наоборот, жестче. При этом поисковые боты не попадут в бан. В случае bash-скрипта такое реализовать сложно.
  • Можно выставлять разные сроки и режимы блокировки в зависимости от страны.
  • Удобная админка, где можно проанализировать работу скрипта, посмотреть браузеры и страны ботов, даты атаки и т.д.

Скрипт неоднократно испытан на практике - форум атакуют регулярно.

Результат работы скрипта в связке с Cloudflare, с разными настройками режима блокировки по странам.

бан ддос ботов в cloudflare

Страна целевого трафика (в моем случае Россия) банится точечно, по IP, страны СНГ по маске 24, все прочие - по стране. То есть, если на ваш сайт резко пошел трафик из страны нецелевой аудитории, то скрипт выставляет заглушку на всю страну (реальный пользователь пройдет капчу), а если боты из страны целевой аудитории - банит точечно. Это очень экономит ресурсы сервера. Российские боты дороже, их меньше и они хорошо абузятся (можно их собрать и сделать рассылку провайдерам). На моем опыте, при самой мощной атаке, было не больше 1000 российских ботов или около 10% от общего ботнета.

Теперь в админку добавлена функция, позвляющая удалить из Cloudflare забаненые в ходе атаки сайты.

Файл настроек скрипта.
PHP:
$config=['whitetime'=>31536000, /*месяц*/ 'bantime'=>604800, /*неделя*/ 'proactivetime'=>3600, /*час*/ 'referertime'=>604800];

$config['limit']=5; // Количество заходов в минуту, после превышения появляется капча. Убедитесь, что нет никаких ajax скриптов, которые обращаются чаще (чат, например).

/*
Количество заходов со всех IP в минуту при которых включается режим "под атакой".
Режим "под аттакой" предназначен для противодействия "умному"/медленному ддосу, желательно не включать, если срабатывает обычная защита.
Добавьте исключения на кешируемые данные, если используете Cloudflare, для избежания ложного срабатывания счетчика. Пример есть в инструкции.
*/
$config['limit_attack_mode']=88; // Рекомендуемое значение примерно 1/24 от среднего числа просмотров в сутки во избежании ложных срабатываний. Установите 0 для отключения срабатывания режима "под аттакой".
$config['limit_attack_mode_ban']=3;  // Количество заходов в минуту для срабатывания бана в режиме "под атакой". Если выставить 1, то будут залетать все IP, кроме поисковых ботов.

// Настройки счетчика, если url=1 то считает заходы для каждой страницы сайта, если 0, то для всего сайта. Если user_agent=1, то учитывает браузер.
$config['counter']=['url'=>1, 'user_agent'=>0];


//$config['referer']=[$_SERVER['HTTP_HOST'], 'yandex.ru', 'google.com', 'google.ru'];
$config['referer']=false; // Рефереры для исключения, ддос боты обычно шлют пустые реферы
$config['adminEmail']=''; // Емейл для связи (ошибочня блокировка)

$config['search_bots']=['Googlebot'=>'Google', 'yandex.com/bots'=>'Yandex', 'mail.ru'=>'mail.ru'];  // 'msn.com','bing.com'
$config['search_hosts']=['Google'=>['.googlebot.com', '.google.com'], 'Yandex'=>['.yandex.com', '.yandex.ru', '.yandex.net'], 'mail.ru'=>['.mail.ru'], 'msn.com'=>['.msn.com'], 'bing.com'=>['.msn.com'] ];

//Cloudflare
$configCF=
[
    'email'=>'',  // email вашего аккаунта в Cloudflare
    'key'=>'', // Узнать можно на странице dash.cloudflare.com/profile, Global API Key
    'zone'=>'', // ID домена в Cloudflare, есть во вкладке Overview

    'countries'=>['RU'=>1, 'UA'=>1, 'BY'=>1, 'KZ'=>1, 'LV'=>1], // страны целевого трафика
    'limit'=>15 // Лимит в минуту для IP, прошедших капчу Cloudflare. При превышении лимита, IP банится полностью
];

$config['admin']['pass']=''; // Пароль админки

----
Ссылка для скачивания и инструкция по установке:
Для просмотра содержимого вам необходимо авторизоваться.
Для просмотра содержимого, просто зарегистрируйтесь на форуме и отпишитесь в теме, зачем вам нужен скрипт.

Внимание: по ссылке
Для просмотра содержимого вам необходимо авторизоваться.
выложена новая версия скрипта, тема поддержки здесь: https://ddosforum.com/threads/1045/

Требования: PHP 5.4 и выше, модуль curl

Узнать о наличии модуля curl можно через phpinfo();

----
Если не можете настроить скрипт самостоятельно пишите мне в ЛС или [email protected]. Помогу защитить сайты любой тематики (ну кроме совсем чернухи детского порно и т.п.).
Предложения по улучшению или свои доработки присылайте на Email или выкладывайте здесь. Если доработки будут интересными, добавлю ваше имя в число авторов на Гитхабе и ссылку на ваш сайт.

Если скрипт не помог - пишите в теме.

-----
Важное обновление от 23.01.2020.

Добавлена возможность менять конфигурацию хэша счетчика запросов.
$config['counter']=['url'=>1, 'user_agent'=>0];

Если url установить в 0, то счетчик на IP будет работать для всего сайта, а не на каждую отдельную страницу. Это пригодится в случае, если ддос-боты атакуют несколько внутренних страниц одновременно. На моей практике такого еще не бывало - ддосят либо главную, либо внутренние по-очереди, - в таком случае настройку менять не нужно.

Если user_agent установить в 1, то будет учитываться браузер для конфигурации хэша счетчика. Это пригодится в случае, если пользователи вашего сайта используют популярные прокси: ускорители трафика, бесплатные VPN для обхода блокировок и т.п. Теоретически, ддосер может менять User Agent при каждом обращении бота, поэтому включайте User Agent с осторожностью.

-----

Ссылка для тестирования: https://antiddos.ddosforum.com

-----

Обновления 23.01.2020
  • Добавлена возможность менять конфигурацию хэша в config.php
  • Добавлена возможность блокировки ботов даже в случае ручного прохождения капчи ддосером
  • В админке добавлен подраздел "География ботов" к разделу Cloudflare


Обновления 31.05.2022
  • Добавлен режим "Под атакой".
  • Добавлен подраздел меню "Фейковые поисковые боты".
 
Последнее редактирование:
admin

admin

Администратор
Администрация
#2
Версия без связки с Cloudflare. Устаревшая версия
Пишите в теме, если нужен скрипт именно под iptables.

Код скрипта. Можно инклудить или вставить вверху исполняемого файла (index.php).
В качестве белого и черного списков я использую файловую систему - так быстрее, чем обрабатывать файл. Список забаненых IP вы сможете сгенерировать через админку.
PHP:
function isBot()
{
  $bots = ['Google','Yandex','mail.ru'];
  foreach($bots as $b) { if( stripos($_SERVER['HTTP_USER_AGENT'], $b) == true ) return $b; }

  return false;
}


$enter=true;
$ip=$_SERVER['REMOTE_ADDR']; // Убедитесь, что переменная $_SERVER['REMOTE_ADDR'] содержит IP пользователя, а не сервера, как иногда бывает при кривых настройках, либо при проксировании домена через сервисы типа Cloudflare

define('DIR', $_SERVER['DOCUMENT_ROOT'].'/antiddos/');
define('BAN', DIR.'ban/'.$ip);
//$ip=rand(1,255).'.'.rand(1,255).'.'.rand(1,255).'.'.rand(1,255); // это для теста


// Настройки
$url=false; // Атакуемая страница. Обычно это главная или страница с авторизацией (POST запросы создают максимальную нагрузку на сервер). Если боты атакуют разные внутряки, оставить false.
$count=1; // Лимит запросов в минуту, при превышении которого IP попадает в черный список. Если установлено false, то нужно будет пройти каптчу для захода на сайт или атакуемую страницу.

// !!! ВАЖНО !!! Для работы скрипта необходимо создать папку antiddos в корне сайта, а в этой папке еще три папки с правами 777: ban, white и count.


function antiddos($ip, $url, $count)
{
    if ($url)
    {
        list(,$url)=explode($_SERVER['HTTP_HOST'], $url);
        if ($_SERVER['REQUEST_URI']!=$url) return true; // Если не целевая страница, то пропускаем. Например, ддосят только главную, а пользователь зашел с поисковой системы на внутреннюю
    }

    // Отсеиваем глупых ботов с пустым юзер-агентом. Если в логах таких нет, можно закомментить.
    if (strlen($_SERVER['HTTP_USER_AGENT'])<3)
    {
        file_put_contents(BAN, '');
        return false;
    }

    // Если пользователь зашел с поисковиков, добавляем в белый список.
    if (strpos($_SERVER['HTTP_REFERER'],'yandex.')!==false || strpos($_SERVER['HTTP_REFERER'],'google.')!==false) return true;

    if (isBot()) // Если ддос-боты подменяют User Agent, то отключить проверку
    {
        file_put_contents(DIR.'white/'.$ip, $_SERVER['HTTP_USER_AGENT']); // Добавляем IP поисковых ботов в белый список
        return true;
    }

    if (!$count) // Если лимит запросов не задан, добавляем все IP в бан. Для удаления из бана пользователь должен будет пройти каптчу
    {
        file_put_contents(BAN, '');

        return false;
    }
    else
    {
        if ($url)
        {
            $cf=date("m-d-h-i.").$ip;  // Метод не точен, так как минута будет не полная. Но даже если бот не израсходует свой лимит на остатке минуте, то срежется на следующей минуте. Делать более сложную проверку - лишняя нагрузка

        }
        else $cf=md5($_SERVER['REQUEST_URI'].$_SERVER['HTTP_USER_AGENT'].date("mdhi")).$ip; // Если ддосят разные страницы, то делаем счетчик для каждой страницы. Более ресурсоемкий вариант.

        $cf=DIR.'count/'.$cf;

        if (!is_file($cf)) file_put_contents($cf, "1"); // папку antiddos/count рекомендуется переодически очищать через админку
        else
        {
            $c=file_get_contents($cf);
            if ($c>$count) // лимит превышен
            {
                file_put_contents(BAN, $_SERVER['HTTP_USER_AGENT'].PHP_EOL.$_SERVER['REQUEST_URI']); // отправляем в бан

                return false;
            }
            else
            {
                file_put_contents($cf, $c+1);
            }
        }

        return true;
    }
}

//
if (isset($_GET['nebot']) )  // Пользователь проходит каптчу
{
    $time=time();

    if ($_GET['nebot']>$time-60 && $_GET['nebot']<$time) // Простая timestamp-каптча. Большинство ддосеров не смогут (не будут пытаться) ее обойти, не смотря на кажущуюся простоту.
    {
        file_put_contents(DIR.'white/'.$ip, ""); // Добавляе IP в белый список.

        if (is_file(BAN)) unlink(BAN); // Удаляем IP из черного списка, если он там есть

        // Сбрасываем счетчик обращений
        $items = glob(DIR.'count/*'.$ip);
        foreach ($items as $fip) unlink($fip);

    /*    sleep(1);

        header("Location: http://".$_SERVER['HTTP_HOST']);  // Редиректим на главную  */
        exit;
    }

}
elseif (is_file(BAN))
{
    exit; // Если ip в черном списке, прерываем исполнение. Вместо exit можно вывести заглушку (как ниже), если вы опасаетесь что пользователь может попасть в черный список случайно, но тогда увеличится нагрузка на сервер.
}
else
if ( !is_file(DIR.'white/'.$ip) && !antiddos($ip, $url, $count)) // Если нет в белом списке и не прошел проверку, показываем заглушку только первый раз. В дальнейшем IP будет отсеиваться на предыдущем шаге.
{
    echo '<script>window.location="/?nebot='.time().'";</script>';     // Боты обычно не видят редиректов
    echo '<h1>На сайт идет ддос. Нажмите, если вы не бот: <a href="?nebot='.time().'">я не бот</a></h1>'; // Примитивная заглушка-каптча без html-разметки, если по каким то причинам не сработал редирект выше
    exit;
}
Обычно ддос-боты не видят куки и редиректы, поэтому вы можете инклюдить скрипт на свой сайт таким образом.
PHP:
if (@empty($_COOKIE))
{
    include($_SERVER['DOCUMENT_ROOT'].'/antiddos/include.php');
}
Тогда легитимные пользователи проверяться не будут. Только проверьте сначала, устанавливает ли ваш сайт куки. Для этого пропишите в исполняемом файле.
PHP:
var_dump($_COOKIE);
exit;
И обновите страницу 2 раза.
Если движок куки не устанавливает для незарегистрированных пользователей, тогда придется установить их самостоятельно.
PHP:
if (!isset($_COOKIE['checkuser']))
{
    setcookie("checkuser", 1, time()+43200); // устанавливаем куку на месяц
    include($_SERVER['DOCUMENT_ROOT'].'/antiddos/include.php');
}
Добавление ддос ботов в iptables по крону.
Файл banip.sh и помещаем в папку root сервера или даже в директорию antiddos в корне сайта.
Код:
#!/bin/bash

cd /var/www/user/data/www/vashsait.com/antiddos/

# Лучше вызывать этот скрипт отдельно кроном чуть раньше баш-скрипта, чтобы не допустить попадания в бан пользователей, не успевших пройти капчу
# /usr/bin/php ban.php 1

if [[ -s ipban.txt ]]
then
    echo -e "\n" >> ipbanlog.txt

    while read ip
    do
       /sbin/iptables -A INPUT -s "$ip" -j DROP  # баним IP
       echo "$ip"
    done < ipban.txt
  
    cat ipban.txt >> ipbanlog.txt  # полный список забаненых IP
    cat /dev/null > ipban.txt # обнуляем банлист
else
    echo "file empty"
fi

exit
Код файла ban.php из папки antiddos.
PHP:
if (isset($_GET['start']) || $argv[1]==1)
{
    $dir='путь/antiddos/';
    $list=file_get_contents($dir.'ipban.txt');
    if ($list) $list=explode(chr(10), substr($list,0,-1) ); else $list=array();
    $items = glob($dir.'ban/*');

    $log=array();
    foreach ($items as $ip)
    {
        $list[]=str_replace($dir.'ban/','',$ip);
        unlink($ip);
  
    }
    if (empty($list)) exit;
    $list=array_unique($list);
  
    file_put_contents($dir.'ipban.txt', implode(chr(10), $list).chr(10) );
  
    exit;
}
Добавляем в кроне исполнение скрипта banip.sh, скажем, раз в 10 минут, если исполняем вместе со скриптом ban.php. Если отдельно, то указываем исполнение banip.sh каждую 10, 20, 30, 40, 50 и 1 минуты, а ban.php соответственно каждую 9, 19, 29, 39 , 49 и 59 минуты.
 
Последнее редактирование:
M

MrKira

New Member
#7
Все, выложил на Гитхабе, смотрите в теме.
Если будут вопросы, пишите здесь.
Подскажите, если у меня одностраничный лэндинг, на html. Как к нему скрипт подключить?
вот это: include($_SERVER['DOCUMENT_ROOT'].'/<папка скрипта>/include.php');
если прописать в index.html файл, оно же не будет работать..

-----
Разобрался.
 
Последнее редактирование модератором:
admin

admin

Администратор
Администрация
#9
По поводу общедоступности файла /<папка скрипта>/cron/run.php
Для большей безопасности вы можете вызывать крон через wget со своим значением user_agent

/usr/bin/wget --user-agent="pass123" "<ваш сайт>/<ваша папка>/cron/run.php?action=clearcount
В run.php есть закомментированая строчка.
if (!isset($_SERVER['HTTP_USER_AGENT']!='pass123') exit('tuk-tuk');

Либо просто придумайте сложное название для папки и никто ее не найдет. А если атакующий получит вашу файловую структуру, то его знание доступа к run будет не самой большой проблемой )

-----

По поводу белого экрана - включите ошибки. Видимо, у вас старый php. Если древний PHP, то просто поменяйте везде массивы на array, других проблем быть не должно.
Ладно, если не разберетесь, создам тестовый сайт.
 
Последнее редактирование:
M

MrKira

New Member
#10
Вы не смотрите ветку вопросов на гитхабе? Мы там описали свою проблему 15 дней назад, посмотрите пожалуйста. Проблема не в версии пхп.
 
Последнее редактирование модератором:
admin

admin

Администратор
Администрация
#11
Сейчас создаю тестовый сайт.
Уже заметил, что папки count не хватает. Буду тестировать админку.
 
M

MadBadJack

New Member
#13
Спасибо за интересный скрипт. Пока не разобрался с админкой, но вижу не толкьо у меня трабла. php 5.6.40. т.ч. проблема не в нем.
 
Y

yermakov

New Member
#19
Вы писали, что за помощью можно обращаться на [email protected] , но письмо не доходит.
У меня сайт car-hobby.ru/ . Установил Ваш скрипт, только вот не уверен, что все правильно сделал. Можете помочь с этим? Сайт на Wordpress
 
Сверху