We are happy to announce that Vesta is back under active development as of 25 February 2024. We are working on Vesta 2.0 and expect to release it by the end of 2024. Read more about it: https://vestacp.com/docs/vesta-2-development
Борьба с DDoS
Борьба с DDoS
Добрый день...
Попробую немного описать как удалось избавиться от DDoS атак, которые идут с 26 сентября.
Начну с того, что мной был успешно geoip для iptables и модуль testcookie-nginx-module. Это расписывать не буду, т.к. geoip мало кому подойдет, а testcookie не помог (ботнет по расчётам около 100к).
Отталкиваться буду от "голой" vestacp.
1. Устанавливаем ipset, создаём сет, я создал типа nethash для блокировки целых подсетей. По желанию можно наполнить её каким нибудь списком из инета. Далее нужно добавить правило в iptables, который будет отбивать коннекты с адресов по созданному сету, я просто добавил строку в файл /usr/local/vesta/bin/v-update-firewall, после строки:
добавляем
где dropnet - имя сета созданного с типом nethash
Как работать с ipset много инфы в инете, не буду останавливаться на этом
Выполняем v-update-firewall что бы обновить правила iptables...
МИНУС - при обновлении панели это может слетать! На вопрос как этого избежать, пока ответа нет. Вообще неплохо было бы встроить ipset в панель.
2. Создаём фильтр и jail для fail2ban
Новый файл /etc/fail2ban/filter.d/apache-ddos.conf с содержимым:
Тут всё индивидуально, у меня шли атаки на форму авторизации и восстановления пароля POST запросами.
Открываем /etc/fail2ban/jail.local и добавляем jail:
Если несколько сайтов - несколько логов и не забываем тогда про регулярку фильтра!
В моём случае бан выдается на сутки, если по фильтру фиксируется 10 запросов в 2 минуты. Опять же это в моём случае, т.к. человек 10 POST запросов в 2 минуты на форме авторизации вряд ли сделает.
Перезапускаем fail2ban или fail2ban-client reload
3. Теперь fail2ban начал банить ботов, спустя какое то время набираются адреса. Данный шаг очень главный, пожалуйста не игнорируйте его, т.к. мы будем уведомлять по whois владельцев IP адресов, с которых долбятся боты! Это работает, у меня идёт рассылка и люди отвечают, один раз даже звонили :)
Уведомления строятся на двух скриптов, один собирает информацию, второй рассылает письма.
Первый скрипт whois_parse.sh:
На выходе в текущем каталоге получим файл ip.emails где будет сопоставлен каждый IP эмейлам из whois - по нему желательно пробежаться вручную, если файл не большой, очистив от лишних адресов. Так же будет каталог ip_logs, в котором выдернутые логи по каждому IP адресу в виде файлов <IP>.log
4. Второй скрипт группирует IP адреса из файла ip.emails по получателям, что бы не отправлять по каждому IP отдельного письма! Формируется список получателей и сгруппированные IP адреса, логи этих адресов объединяются в один файл-отчёт и отправляется получателям с сопроводительным текстом из шаблона.
Скрипт рассылки send_ddos_report.sh:
Файл шаблона текста письма send_ddos_report.tpl:
Использовать скрипт сбора whois и рассылки можно раз в неделю, если кто предпринял действия, их IP адрес выпадет из fail2ban и в следующую рассылку не попадут.
Первую свою рассылку я делал без лога, 90% ответивших на письмо их запросили!
У меня стоит ограничение по geoip только RU, по этому мои рассылки не столь большие.
Дальше всё на ваше усмотрение! Можно каждый IP адрес забаненый на текущий момент fail2ban проверять по логу /var/log/fail2ban.log*, выяснять сколько раз по логу он уже банился, если например более 5 раз (а это 5 дней подряд с текущим jail), заносить этот адрес в список ipset - он больше не попадёт в fail2ban и по нему не будет рассылки.
Я просто поделился своим опытом, т.к. преследую цель имено борьбы с ддос, а не только защиту. Мои познания в bash не на столько круты и возможно где то можно сделать лучше и проще.
UPD 2022-10-03: Погоняв ещё скрипт пришел к выводу, что нужно читать все логи, в том числе и ротацию, а так же нужна проверка перед отправкой, не пустой ли файл логов который собираемся отправлять (если пустой, не отправляется письмо). Изменения внёс.
Попробую немного описать как удалось избавиться от 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
Как работать с 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 =
Открываем /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
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
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]
Первую свою рассылку я делал без лога, 90% ответивших на письмо их запросили!
У меня стоит ограничение по geoip только RU, по этому мои рассылки не столь большие.
Дальше всё на ваше усмотрение! Можно каждый IP адрес забаненый на текущий момент fail2ban проверять по логу /var/log/fail2ban.log*, выяснять сколько раз по логу он уже банился, если например более 5 раз (а это 5 дней подряд с текущим jail), заносить этот адрес в список ipset - он больше не попадёт в fail2ban и по нему не будет рассылки.
Я просто поделился своим опытом, т.к. преследую цель имено борьбы с ддос, а не только защиту. Мои познания в bash не на столько круты и возможно где то можно сделать лучше и проще.
UPD 2022-10-03: Погоняв ещё скрипт пришел к выводу, что нужно читать все логи, в том числе и ротацию, а так же нужна проверка перед отправкой, не пустой ли файл логов который собираемся отправлять (если пустой, не отправляется письмо). Изменения внёс.