freebsd_shield

HTTP-флуд — это массированная атака на веб-сервер, которая сопровождается посылкой огромного кол-ва http-запросов.

Три ступени борьбы с HTTP-флудом

  1. Активируем IPFW
  2. Пишем наш файерволл
  3. Пишем парсер логов и добавляем их в черный список

Активируем IPFW

Добавим в /etc/rc.conf

firewall_enable="YES"
firewall_script="/etc/fw.sh"
firewall_logging="YES"

Внимание! Не перезагружайтесь сразу же, так как получите бан по сети и не сможете влезть в ssh. Тем у кого есть физический доступ — это не касается естественно! :)

Пишем наш файерволл

Создаем наш файерволл в файл /etc/fw.sh

#!/bin/sh

FwCMD="/sbin/ipfw"

${FwCMD} -f flush
${FwCMD} 10 add check-state

${FwCMD} 40 add allow all from "table(1)" to me
cat /etc/fw_white_list | awk '{ if ($1!="") {system("ipfw table 1 add "$1"")} }' > /dev/null

${FwCMD} 50 add deny all from "table(2)" to me
cat /etc/fw_black_list | awk '{ if ($1!="") {system("ipfw table 2 add "$1"")} }' > /dev/null

${FwCMD} 100 add allow ip from any to any


с правами файлов надеюсь сами разберетесь...

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



Теперь потестим наши правила!

# ipfw show

Будет что-то типа того:

00040     0      0 allow ip from table(1) to me
00050     0      0 deny ip from table(2) to me

Если есть table (1) и table (2), то все в порядке, если нет, то попробуйте создать их вручную:

# ipfw 40 add allow all from "table(1)" to me
# ipfw 50 add deny all from "table(2)" to me



Тестим содержимое наших table

# ipfw table 1 list
# ipfw table 2 list

Должны быть списки вида:

111.111.111.111/32 0
222.222.222.222/32 0

Если ipfw не запускается, то используйте полный путь /sbin/ipfw.
Теперь можно и перезагрузить сервер, для применения настроек.

Пишем парсер логов и добавляем их в черный список

Я использую nginx для фронтенда, поэтому буду анализировать его access-логи, но вы можете сами написать регулярку для парсинга логов apache например...

Для nginx надо создать дополнительный файл access-лога «/var/log/nginx/access-ddos.log», просто мне так удобнее, но вы можете не заморачиваться, а использовать один лог. Мне просто удобно с двумя, один имеет в себе полный лог, а второй я порой подчищаю.

Создадим файл /etc/banip.sh, который будет собирать IP и добавлять их в бан!

#!/bin/sh

# зачищаем fw_black_list
echo '' > /etc/fw_black_list

# выберем с помощью регулярок IP, у которых нет Useg-Agent'а, отсортируем с уникальным ключом
cat /var/log/nginx/access-ddos.log | awk ' match($0, /(\d*.\d*.\d*.\d*).*"-" "-"/) {print $1}' | sort | uniq >> /etc/fw_black_list

# чистим лог
# echo '' > /var/log/nginx/access-ddos.log

# сбрасываем таблицу с забаненными IP
/sbin/ipfw table 2 flush

# добавляем в таблицу список забанненых IP
cat /etc/fw_black_list | awk '{ if ($1!="") {system("/sbin/ipfw table 2 add "$1"")} }' > /dev/null



Вот пример лога с http-флудом + нормальные запросы от пользователей (162.115.149.232)

111.111.111.111 - - [31/Mar/2009:14:00:00 +0000] "GET / HTTP/1.1" 304 0 "-" "-"
162.115.149.232 - - [31/Mar/2009:14:01:00 +0000] "GET / HTTP/1.1" 200 8960 "http://example.com./" "Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.1; Trident/4.0; .NET CLR 1.1.4322)"
111.111.111.111 - - [31/Mar/2009:14:02:00 +0000] "GET / HTTP/1.1" 304 0 "-" "-"
222.222.222.222 - - [31/Mar/2009:14:03:00 +0000] "GET / HTTP/1.1" 304 0 "-" "-"

С помощью регулярки

/(\d*.\d*.\d*.\d*).*"-" "-"/

можно и без регулярки см. каммент

получим

111.111.111.111
111.111.111.111
222.222.222.222

после чего переведем поток и отсортируем уникальные IP в списке

sort | uniq

и получим в результате:

111.111.111.111
222.222.222.222

вот этот результат и пойдет в черный список!

Добавить в cron задание

Ставим в cron задание, пусть сам проверяет теперь и добавляет IP в бан.
С установкой времени думаю сами разберитесь, потому что зависит от конкретной ситуации.

0 * * * * /etc/banip.sh| mail -s"`uname -n` backup report" root

Шпаргалка по крону



P.S. Написал этот пост как можно проще, для того чтобы каждый мог легко разобраться с этой напастью и решить проблему. Рекомендую изучить или хотябы ознакомится с AWK прежде чем что-то менять, так же без регулярных выражений здесь никуда...

UPD: Забыл сказать, думаю назревает вопрос зачем нам «/etc/fw.sh»? Это для того чтобы перезагружать файерволл и изменять правила.


Комментарии (45) на запись «FreeBSD. Боремся с HTTP-флудом средствами IPFW»

» Трекбеки скрыты, показать их?
  1. vasa_c | 31.03.2009 в 16:28

    Прекольно

  2. adw0rd | 31.03.2009 в 16:36

    Прикольно? А что ава тогда грусная? :)

  3. Seodigger.com заговорил по русски! | Мастерская интернет-разработчика | 01.04.2009 в 00:26

    [...] ipfw ddos Оставить комментарий | Comment RSS | Теги: SEO, Сервисы Назад: Hello, World! Далее: Начинающим блоггерам! Выбор блога, регистрация в каталогах, поисковиках и закладках. [...]

  4. CTAPbIu_MABP | 01.04.2009 в 11:34

    /d*.d*.d*.d*.*"-" «-»/

    шо за кривая регулярка?

  5. Zhilinsky | 01.04.2009 в 11:40

    Вот так я и узнал, что у меня на серваке с надписью FreeBSD 7 на самом деле крутится FreeBSD 5.2.1, в которой ipfw ещё команду table не знает %)

  6. adw0rd | 01.04.2009 в 12:43

    Mabp, отличная регулярка, что работает то лучше не менять :P

  7. adw0rd | 01.04.2009 в 12:45

    Zhilinsky, будешь обновлять систему?

  8. CTAPbIu_MABP | 01.04.2009 в 12:54

    врешь ты все ©

    у тебя под нее вот такая строка пройдет как дети в школу

    0000 text «-» «-»

  9. adw0rd | 01.04.2009 в 13:00

    И пройдет туда «0000», в чем проблема то? У меня IP пишет nginx, считаешь он может туда добавить «0000»?

  10. adw0rd | 01.04.2009 в 13:03

    Заключил выборку в круглые скобки, может ты поэтому паришься?

  11. CTAPbIu_MABP | 01.04.2009 в 13:04

    бля, напиши как человек

    /\d+\.\d+\.\d+\.\d+.*"-" «-»/

  12. adw0rd | 01.04.2009 в 13:08

    Мавр, так регулярка не будет работать, проверено. Почитай про AWK...

  13. Zhilinsky | 01.04.2009 в 13:08

    Неа, мне лень... Да и работает. Может ipfw обновлю.

  14. adw0rd | 01.04.2009 в 13:10

    Zhilinsky, ты просто список IP через запятую добавляешь чтоли?

  15. Zhilinsky | 01.04.2009 в 13:15

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

  16. CTAPbIu_MABP | 01.04.2009 в 13:16

    херня какаято

  17. adw0rd | 01.04.2009 в 13:20

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

  18. adw0rd | 01.04.2009 в 13:22

    CTAPbIu_MABP, попробуй потестить сам, если не веришь...

  19. CTAPbIu_MABP | 01.04.2009 в 13:45

    верю, читал, просто странно что там не pcre

  20. dallone | 01.04.2009 в 13:53

    Что-то мне подсказывает, что это обходится, но сформулировать алгоритм обхода я не могу :)

  21. Zhilinsky | 01.04.2009 в 13:58

    IP-адрес хранится в пакете, приходящем снаружи, а не определяется на месте. Следственно, его можно хитро подделать :-)

    По крайней мере, меня так учили =)

  22. adw0rd | 01.04.2009 в 14:01

    dallone, от любого ддоса нельзя защитится на 100%, даже с железками.

    А в моем алгоритме учитываются юзеры без User-Agent, если боты начнут засылать UA, то я поменяю алгоритм :)

  23. adw0rd | 01.04.2009 в 17:12

    Mabp, ты был прав, что-то странно в регулярке, парсер вордпресса съел бекслеши пере «d»

  24. CTAPbIu_MABP | 01.04.2009 в 17:19

    я ж говорил.

    но перед точкой по идеи тоже надо она же за любой символ идет

  25. adw0rd | 01.04.2009 в 17:27

    >я ж говорил.

    я знаю что парсер бесится из-за плагина keywords... только пока не знаю что поправить.

  26. adw0rd | 01.04.2009 в 17:35

    >но перед точкой по идеи тоже надо она же за любой символ идет

    думаю так как нет за точкой литерала указывающего кол-во, то она и не срабатывает как маска.

    но когда использую \.\d*

    то не работает...

  27. CTAPbIu_MABP | 01.04.2009 в 17:41

    литералы количество не указывают, его указывают квантификаторы (от слова quantity — количество)

  28. adw0rd | 01.04.2009 в 18:00

    угу, все время забываю это слово...

  29. Макака | 21.04.2009 в 01:29

    хммм... странно...

    Почему рег. /(\d*.\d*.\d*.\d*).*"-" «-»/ ?

    А разве проблема сделать запрос 162.115.149.232 — — [31/Mar/2009:14:01:00 +0000] «GET / HTTP/1.1» 200 8960 «http://example.com./» «Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.1; Trident/4.0; .NET CLR 1.1.4322)» ?

    Что то не пому как он отличает ддос бота от человека = )))))

  30. adw0rd | 21.04.2009 в 01:37

    Макака, читайте внимательнее пост, я рассказывал про свою проблему и в следствии анлиза выяснилось что боты не передавали UA. И камменты.

  31. phpdude | 30.05.2009 в 23:28

    да ты дарагой см не знаешь авк. и видимо не понимаешь как он работает))

  32. adw0rd | 31.05.2009 в 03:07

    В результате обсуждений с дудом в скайпе — awk, пришол к выводу что я awk знаю плохо...

    if( $12=="-") { print $1; }

    решит мою проблему без регулярки

  33. phpdude | 01.06.2009 в 00:26

    кросавчеги :)

  34. epsyl.home » Архив блога » Досеры, сосните хуйца! | 10.07.2009 в 19:41

    [...] новомодной технологии пыхо-специалистов сегодня удалось раз и навсегда посадить на осиновый [...]

  35. epsyl | 10.07.2009 в 19:43

    Вы еще не поняли, насколько это охуенная статья!

    epsyl.ru/web/dos-xyu/

  36. alpha_Qu4z4r | 13.07.2009 в 23:21

    прогнал парсер через свой лог и не получил на выходе ничего, хотя посещалка на ресурсе порядка 200к уников в сутки. Решил телнетом запросить страницу, поскольку он никаких UA передавать не должен. В ответ получил странную картину:

    [root@travka /usr/home/alp]# cat /var/log/httpd/xyy***x-access.log| awk ' match ($0, /(\d*.\d*.\d*.\d*).*"-" «-»/) {print $1}' | sort | uniq

    Тут пустота. И тут же делаю выборку своего телнетного запроса:

    [root@travka /usr/home/alp]# grep 188.*.*.99 /var/log/httpd/xyyandex-access.log

    188.*.*.99 — — [13/Jul/2009:17:31:53 +0000] «GET / HTTP/1.0» 200 83576

    Никаких «-» «-» в конце нет, странно.

  37. adw0rd | 13.07.2009 в 23:22

    Какой лог ты анализируешь? nginx'a и дефолтный, не перенастраивал?

    покажи кусок лога, с ддосерами

  38. alpha_Qu4z4r | 13.07.2009 в 23:31

    Апач и нгинкс валят лог в один и тот же файл. В нгинксе указана такая строка:

    access_log /var/log/httpd/xyyandex-access.log main;

  39. adw0rd | 13.07.2009 в 23:39

    Апач и нгинкс валят лог в один и тот же файл. В нгинксе указана такая строка:

    так не должно быть? ты для себя так настроил? в чем удобство?

    access_log /var/log/httpd/xyyandex-access.log main;

    ты настроил фильтр main прежде чем его юзать? при ребуте нгинкса ошибки есть?

  40. alpha_Qu4z4r | 14.07.2009 в 05:31

    Удобство в остутсвии стопицот мильёнов логов и присутствии всего одного.

    Я думал, что main, это некий пресет, который уже настроен определённым образом.

  41. adw0rd | 14.07.2009 в 05:51

    alpha_Qu4z4r, ну и оставь один от nginx :)

    Мой анализатор работает только с логом нгинска, не перенастроенным...

    Если хочешь и свой чудо-лог оставить, то создай еще один только для nginx и юзай его в анализаторе!

  42. Sinkler | 30.07.2009 в 23:17

    крут. и вобще все на этом блоге круто =) так держать

  43. adw0rd | 31.07.2009 в 09:27

    Ага, спасибо :)

  44. Илья | 05.09.2009 в 20:17

    у меня заработало с одним равно

    if ( $12="-") { print $1; }

  45. adw0rd | 05.09.2009 в 20:23

    Илья, вы уверены что результат верный? Просто в основном, при

    $12 = "-"

    будет выполняться присваивание, и «if» получит от операции — TRUE

Оставить комментарий


cкачать бесплатно фильмы