Защита от DDoS атак при помощи скрипта (D)DoS Deflate

На днях сервер упал под DDoS натиском. До этого момента защищался от подобного только самопальным скриптом и модулем GeoIP для nginx. Однако в этот раз нагрузка была слишком большая, поэтому скрипт и nginx попросту не справились.

Надумал искать другое решение этой проблемы. Вспомнил про популярный скрипт, который позволяет защититься от некоторых видов DDoS. От атак при которых забивается канал он конечно не спасёт, но блокировать множество подключений с одних и тех же IP адресов для понижения нагрузки на сервер он способен.

В своей основе скрипт использует команду/программу netstat, которая выявляет число открытых соединений с каждого адреса, и в случае если соединений много, то адрес блокируется на определённое время.

Команда netstat с параметрами взятая прямо из скрипта ddos.sh:

netstat -ntu | awk '{print $5}' | cut -d: -f1 | sort | uniq -c | sort -nr

Команда выводит сортированный по убыванию список ip адресов и количество подключений с них в момент времени. Очень полезная команда, поэтому и взял её для скрипта сюда в статью.

Но да ладно, давайте перейдём непосредственно к самому скрипту.

Скрипт (D)DoS Deflate

Пробежимся по всем этапам установки и настройки (D)DoS Deflate. Я буду показывать на примере Linux Debian, в Linux Ubuntu всё почти точно так же.

Установка

Установка производится следующим образом:

# cd /tmp
# wget http://www.inetbase.com/scripts/ddos/install.sh
# chmod 0777 install.sh
# ./install.sh

Т.е. переходим во временную папку, качаем скрипт, ставим права 777 (разрешено всё) на установочный файл install.sh и запускаем его.

Редактируем конфигурационный файл скрипта:

# nano /usr/local/ddos/ddos.conf

Вместо APF используем IPTables:

APF_BAN=0

Куда отправляем письма:

EMAIL_TO="admin@admin.loc"

Сколько одновременных соединений с одного IP считать за вредные:

NO_OF_CONNECTIONS=500

На сколько банить в секундах

BAN_PERIOD=600

Если надо, то добавляем адреса, которые будут игнорироваться скриптом:

# nano /usr/local/ddos/ignore.ip.list

Пишем список по одному IP на строку что-то в таком виде:

127.0.0.1
1.2.3.4
2.2.2.2

Скрипт не идеален и в нём много косяков, по крайней мере на Debian 7. Будем исправлять.

Сразу скажу что весь скрипт описан в одном файле ddos.sh поэтому его мы и будет по ходу исправлений постоянно править.

Пробуем запустить скрипт и передадим ему ключ -c, что бы он попытался сам добавить себя в cron:

# /usr/local/ddos/ddos.sh -c

В ответ получаем что-нибудь в таком стиле:

./ddos.sh: 13: [: /usr/local/ddos/ddos.conf: unexpected operator
DDoS-Deflate version 0.6
Copyright (C) 2005, Zaf <zaf@vsnl.com>

$CONF not found.

Для устранения этой проблемы нужно исправить в файле «/usr/local/ddos/ddos.sh» запись «#!/bin/sh» на «#!/bin/bash» (естественно всё без кавычек).

Проверяем снова:

# /usr/local/ddos/ddos.sh -c

Ответ:

./ddos.sh: 14: ./ddos.sh: source: not found
crond: unrecognized service
./ddos.sh: 72: ./ddos.sh: cannot create : Directory nonexistent
./ddos.sh: 73: [: -le: unexpected operator
./ddos.sh: 78: ./ddos.sh: let: not found
./ddos.sh: 79: ./ddos.sh: cannot create : Directory nonexistent
crond: unrecognized service

В Debian сервис крона называется cron, а не crond. Нужно исправить в файле «/usr/local/ddos/ddos.sh» везде «crond» заменить на «cron». Исправить придётся только в двух местах, а точнее в функции add_to_cron(), которая и добавляет запись запуска скрипта в список заданий cron.

Проверяем:

# /usr/local/ddos/ddos.sh -c

На сей раз я получил это:

[ ok ] Restarting periodic command scheduler: cron[....] Stopping periodic command scheduler: cron.
[ ok ] Starting periodic command scheduler: cron.
[ ok ] Restarting periodic command scheduler: cron[....] Stopping periodic command scheduler: cron.
[ ok ] Starting periodic command scheduler: cron.

Теперь всё ок.

Удаление скрипта

:
Удаление скрипта производится следующим образом:

# cd /tmp
# wget http://www.inetbase.com/scripts/ddos/uninstall.ddos
# chmod 0777 uninstall.ddos
# ./uninstall.ddos

Т.е. так же переходим во временную папку, качаем скрипт удаления uninstall.ddos ставим на него chmod права 777 и запускаем его, что бы он всё удалил касательно (D)DoS Deflate.

Доработанная версия (D)DoS Deflate

Если хотите, то можете установить себе более продвинутую доработанную версию этого скрипта, которую сделал один хороший человек. Находится это дело тут: https://github.com/Amet13/ddos-deflate

Справка по скрипту (D)DoS Deflate

Решил написать так же короткую справку действий касательно настройки скрипта на всякий случай.

Запустим скрипт:

/usr/local/ddos/ddos.sh

Скажем скрипту добавить себя в cron:

/usr/local/ddos/ddos.sh -c

Надо проверить добавился ли скрипт в задания cron.

Заходим в задания cron:

crontab -e

Проверяем есть ли тут задание на запуск скрипта ddos.sh, если нет дописываем сами:
* * * * * /usr/local/ddos/ddos.sh >/dev/null 2>&1
Т.е. каждую минуту (минимальное время запуска заданий в cron) запускаем скрипт «/usr/local/ddos/ddos.sh», вывод ведём в «/dev/null» (никуда), второй поток (поток ошибок) перенаправляем в первый, который ведёт в «/dev/null». Сохраняем файл заданий cron после редактирования.

Перезапускаем cron:

service cron restart

Смотрим логи cron. По-умолчанию cron пишет свои логи сюда: «/var/log/syslog». Там записи не только от cron, поэтому что бы посмотреть только логи cron используем утилиты, например, так:

grep CRON /var/log/syslog

или

tail -f /var/log/syslog | grep CRON

Каждую минуту cron будет запускать скрипт «/usr/local/ddos/ddos.sh» и писать об этом в логи.

Этап тестирования

Запуск с другого компьютера DOS атаки:
user@192.168.0.100 ~ $ ab -n 200000 -c 100 http://server-ip/

Проверка новых IPTables правил на сервере:

iptables -L INPUT

Ответ примерно такой:

Chain INPUT (policy ACCEPT)
target prot opt source destination
DROP all -- 192.168.0.100 anywhere

Т.е. скрипт отследил множественные частые запросы с одного IP адреса и добавил IP адрес как игнорируемый в правила фаервола iptables.

Написано на основе статьи отсюда: blog.amet13(точка)name/2014/08/ddos-ddos-deflate.html