Page 1 of 1

Борьба с DDoS

Posted: Sun Oct 02, 2022 11:28 am
by gloobus
Добрый день...
Попробую немного описать как удалось избавиться от DDoS атак, которые идут с 26 сентября.
Начну с того, что мной был успешно geoip для iptables и модуль testcookie-nginx-module. Это расписывать не буду, т.к. geoip мало кому подойдет, а testcookie не помог (ботнет по расчётам около 100к).
Отталкиваться буду от "голой" vestacp.

1. Устанавливаем ipset, создаём сет, я создал типа nethash для блокировки целых подсетей. По желанию можно наполнить её каким нибудь списком из инета. Далее нужно добавить правило в iptables, который будет отбивать коннекты с адресов по созданному сету, я просто добавил строку в файл /usr/local/vesta/bin/v-update-firewall, после строки:

Code: Select all

echo "$iptables -A INPUT -s 127.0.0.1 -j ACCEPT" >> $tmp
добавляем

Code: Select all

echo "$iptables -A INPUT -m set --set dropnet src -j DROP" >> $tmp
где dropnet - имя сета созданного с типом nethash
Как работать с ipset много инфы в инете, не буду останавливаться на этом
Выполняем v-update-firewall что бы обновить правила iptables...
МИНУС - при обновлении панели это может слетать! На вопрос как этого избежать, пока ответа нет. Вообще неплохо было бы встроить ipset в панель.

2. Создаём фильтр и jail для fail2ban
Новый файл /etc/fail2ban/filter.d/apache-ddos.conf с содержимым:

Code: Select all

[Definition]

# Option: failregex
# Note: This regex will match any GET and POST entry in your logs, so basically all valid and not valid entries are a match.
# You should set up in the jail.conf file, the maxretry and findtime carefully in order to avoid false positives.

failregex = ^<HOST> -.*"POST (/main/login|/main/forgot).*

# Option: ignoreregex
# Notes.: regex to ignore. If this regex matches, the line is ignored.
# Values: TEXT
#
ignoreregex =
Тут всё индивидуально, у меня шли атаки на форму авторизации и восстановления пароля POST запросами.
Открываем /etc/fail2ban/jail.local и добавляем jail:

Code: Select all

[apache-ddos-iptables]
enabled = true
filter  = apache-ddos
action  = vesta[name=WEB]
logpath = /var/log/httpd/domains/domain.ru.log
maxretry = 10
findtime = 120
bantime = 86400
Если несколько сайтов - несколько логов и не забываем тогда про регулярку фильтра!
В моём случае бан выдается на сутки, если по фильтру фиксируется 10 запросов в 2 минуты. Опять же это в моём случае, т.к. человек 10 POST запросов в 2 минуты на форме авторизации вряд ли сделает.
Перезапускаем fail2ban или fail2ban-client reload

3. Теперь fail2ban начал банить ботов, спустя какое то время набираются адреса. Данный шаг очень главный, пожалуйста не игнорируйте его, т.к. мы будем уведомлять по whois владельцев IP адресов, с которых долбятся боты! Это работает, у меня идёт рассылка и люди отвечают, один раз даже звонили :)
Уведомления строятся на двух скриптов, один собирает информацию, второй рассылает письма.
Первый скрипт whois_parse.sh:

Code: Select all

#!/bin/bash
#
# 1. Первый скрипт, который соберёт список айпи адресов, получит по ним эмейлы и выдернет по каждому лог файл
#

tmp=$(mktemp)

# Очищаем файл соответствий айпи и эмейлов из whois
echo -n "" > ip.emails

# Создаём каталог для логов по айпишникам, если такого ещё нет
mkdir -p ip_logs

# Берём список адресов из jail fail2ban, который у нас следит за ддос атакой, сортируем
# Далее можно пробежаться по нему на предмет наличия в блоке адресов похожих на целую подсеть и забанить перманентно через ipset
fail2ban-client status apache-ddos-iptables | grep -i -o '[0-9]\{1,3\}\.[0-9]\{1,3\}\.[0-9]\{1,3\}\.[0-9]\{1,3\}' | sort > ip.list

# Перебираем полученный список забаненых
for ban in $(cat ip.list | tr -d '\r')
do
    # Пробегая по списку получаем данные из whois эмейлы
    emails=$(echo -n $(whois $ban | grep -i -o '[A-Z0-9._%+-]\+@[A-Z0-9.-]\+\.[A-Z]\{2,4\}' | sort | uniq) | tr " " ,)
    if [[ $emails ]]; then
        echo "$ban;$emails" >> ip.emails
    fi

    # Выдергиваем лог по данному айпи адресу пишем в один файл атаки с двух сайтов и лог файл2бан
    echo -n "" >> $tmp
    domain_log=$(zcat /var/log/httpd/domains/domain.ru.log-*.gz | cat /var/log/httpd/domains/domain.ru.log - | grep $ban | sort)
    if [[ $domain_log ]]; then
        echo "=== SITE domain.ru LOG IP:$ban ===" >> $tmp
        echo "" >> $tmp
        printf "%s" "$domain_log" >> $tmp
        echo "" >> $tmp
        echo "" >> $tmp
    fi
    fb_log=$(cat /var/log/fail2ban.log* | grep $ban | sort)
    if [[ $fb_log ]]; then
        echo "=== Fail2ban LOG IP:$ban ===" >> $tmp
        echo "" >> $tmp
        printf "%s" "$fb_log" >> $tmp
        echo "" >> $tmp
        echo "" >> $tmp
    fi

    # Если собрали что из логов, помещаем в отдельный файл <IP>.log
    if [[ $tmp ]]; then
        cat $tmp > ip_logs/$ban.log
    fi

    rm -f $tmp
done
На выходе в текущем каталоге получим файл ip.emails где будет сопоставлен каждый IP эмейлам из whois - по нему желательно пробежаться вручную, если файл не большой, очистив от лишних адресов. Так же будет каталог ip_logs, в котором выдернутые логи по каждому IP адресу в виде файлов <IP>.log

4. Второй скрипт группирует IP адреса из файла ip.emails по получателям, что бы не отправлять по каждому IP отдельного письма! Формируется список получателей и сгруппированные IP адреса, логи этих адресов объединяются в один файл-отчёт и отправляется получателям с сопроводительным текстом из шаблона.
Скрипт рассылки send_ddos_report.sh:

Code: Select all

#!/bin/bash
#
# 2. Второй скрипт, когда мы подправили список IP и эмейлов, удалив лишние адреса, выполняем создание списка рассылки,
#    слияние логов для получаителя и отправка письма
#

tmp=$(mktemp)
attach="DDoS_Report.log"

# Создаем список из получателей со списком адресов получателя
awk -F";" '{if(a[$2])a[$2]=a[$2]", "$1; else a[$2]=$1;}END{for (i in a)print i, a[i];}' OFS=";" ip.emails > ip.send

# Проверяем наличие каталога с логами
if [ ! -d ip_logs ]; then
    echo "Directory IP_LOGS does not exist."
    exit
fi

# В папку с логами переходим мы
cd ip_logs

# Перебираем список получателей и отправляем каждому письмо и отчёт
while IFS=";" read -r emails ips
do
    # Список айпи перврящаем в список лог-файлов
    logs=$(echo -n "$ips" | sed 's/,/.log/g')
    if [[ $logs ]]; then
        # Если есть лог-файлы, сливаем их в один отчёт который будем отправлять
        cat $logs".log" > $attach

        # Получаем текст сообщения из шаблона, вставляя в него список айпишников
        message=$(cat ../send_ddos_report.tpl | sed "s/%%%IPS%%%/$ips/g")

        # Проверим, что файл с логами что сформировался нам не пустой, что бы было что отправлять
        if [[ -s $attach ]]; then
            # Запишем в лог кому отправили и какое письмо
            echo "$(date '+%Y-%m-%d %H:%M:%S') - SEND TO: $emails" >> $tmp
            printf "%s" "$message" | mail -s "DDoS Report" -a $attach -r 'Support Team <[email protected]>' $emails >> $tmp
        else
            # Если лог был пустой, отправлять не будем письмо дабы не тревожить
            echo "$(date '+%Y-%m-%d %H:%M:%S') - ERROR: file $attach for $emails is empty" >> $tmp
        fi
        echo $message >> $tmp
        echo "===" >> $tmp
        echo "" >> $tmp

        # Удаялем слитый лог
        rm -f $attach
        sleep 1
    fi
done < ../ip.send

# Сохраняем лог рассылок
cat $tmp >> ../send_ddos_report.log
rm -f $tmp
Файл шаблона текста письма send_ddos_report.tpl:

Code: Select all

Здравствуйте.
Информируем Вас, что с 26 сентября 2022 года на наши сайты https://domain1.ru и https://domain2.ru производится DDoS-атака сетью ботнетов примерно в 100 тысяч адресов!
Среди них имеются IP адреса %%%IPS%%%, которые по данным WHOIS принадлежат Вашей сети. Во вложении к письму имеется лог-файл с данными Web-server и Fail2ban.

Просим принять срочные меры для прекращения DDoS-атаки с данных IP адресов!


Hello.
We would like to inform you that from September 26, 2022, our websites https://domain1.ru and https://domain2.ru are being subjected to a DDoS attack by a botnet network of approximately 100,000 addresses!
Among them are IP addresses %%%IPS%%%, which according to WHOIS belong to your network. Attached to the letter there is a log file with data Web-server and Fail2ban.

Please take urgent action to stop the DDoS attack from these IP addresses!


--
С уважением, служба технической поддержки.
Support team: [email protected]
Использовать скрипт сбора whois и рассылки можно раз в неделю, если кто предпринял действия, их IP адрес выпадет из fail2ban и в следующую рассылку не попадут.
Первую свою рассылку я делал без лога, 90% ответивших на письмо их запросили!
У меня стоит ограничение по geoip только RU, по этому мои рассылки не столь большие.

Дальше всё на ваше усмотрение! Можно каждый IP адрес забаненый на текущий момент fail2ban проверять по логу /var/log/fail2ban.log*, выяснять сколько раз по логу он уже банился, если например более 5 раз (а это 5 дней подряд с текущим jail), заносить этот адрес в список ipset - он больше не попадёт в fail2ban и по нему не будет рассылки.

Я просто поделился своим опытом, т.к. преследую цель имено борьбы с ддос, а не только защиту. Мои познания в bash не на столько круты и возможно где то можно сделать лучше и проще.

UPD 2022-10-03: Погоняв ещё скрипт пришел к выводу, что нужно читать все логи, в том числе и ротацию, а так же нужна проверка перед отправкой, не пустой ли файл логов который собираемся отправлять (если пустой, не отправляется письмо). Изменения внёс.

Re: Борьба с DDoS

Posted: Fri Jun 16, 2023 7:44 pm
by prmres
gloobus wrote:
Sun Oct 02, 2022 11:28 am
...
МИНУС - при обновлении панели это может слетать! На вопрос как этого избежать, пока ответа нет. Вообще неплохо было бы встроить ipset в панель.
создать /usr/local/vesta/data/firewall/custom.sh
и туда писать свои правила для фаервола