Fail2ban против сканирования сайтов под ISPConfig

Недавно на одном из проектов хитрая секьюрити компания из Америки взялась проверить безопасность сервера. Для этого она принялась усиленно сканировать все сайты произвольными адресами, в попытке найти уязвимость. Все эти запросы, понятное дело, приводили к ответу 404 от Drupal, но проблема в том, что Drupal при таком ответе не использует кеширование, получается, что каждый 404 запрос дергает базу и напрягает сервер… Это неприятно. И с этим нужно что-то делать.

Остановить злоумышленников можно разными способами, один из них — утилита Fail2ban (fail2ban.org). Идея проста: демон, сканируя логи, проверяет наличие записей о неудачных попытках ввода пароля или попытке входа в запрещенную область сети. Если таковые будут найдены, то подозрительный IP блокируется средствами iptables/ipwf или TCP Wrapper (/etc/hosts.allow|deny). Со временем бан может сниматься автоматически, без вмешательства юниксоида, что очень удобно, ведь под раздачу может попасть и легитимный хост. О блокировке пользователь/админ получает сообщение по e-mail. Изначально Fail2ban разрабатывался для защиты SSH, сегодня это уже фреймворк, который можно легко настроить под любые приложения и события, в том числе и прописать свои методы блокировки IP. Удобно также, что один процесс может защищать сразу несколько сервисов.

Установить fail2ban на CentOS можно используя yum

yum install fail2ban

Демон стартует с установками по умолчанию, защищая только SSH. Все настройки производятся в нескольких файлах, размещенных в каталоге /etc/fail2ban. В fail2ban.conf хранятся параметры запуска самого демона, внутри ничего интересного в плане настроек для нас нет. Начиная с версии 0.7, фильтры и действия прописываются в разных файлах. После установки их можно найти соответственно в подкаталогах filter.d и action.d. Файлы внутри этих директорий могут иметь расширения .conf и .local. Параметры из второго замещают установки из первого, то есть чтобы что-то переопределить, вносить изменения непосредственно в .conf не нужно. Таким образом облегчается последующее обновление и возврат к дефолтным настройкам.

Теперь в директории /etc/fail2ban/filter.d создаем файл apache-404.conf со следующим содержимым

  1. [Definition]
  2. failregex = (?P<host>[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}) .+ 404 [0-9]+ "
  3. ignoreregex = favicon\.ico

а в директории /etc/fail2ban создаем файл jail.local внутри которого подключаем наш новый фильтр. Есть один важный момент, из-за которого некоторые правила могут не работать — отсутствие деолтных настроек в файле jail.local. Поэтому в самом начале файла прописываем их, а уже затем наши правила

  1. [DEFAULT]
  2.  
  3. bantime  = 600
  4. findtime  = 600
  5. maxretry = 3
  6. backend = auto
  1. [apache-404]
  2.  
  3. #принимает значения true или false
  4. enabled = true
  5. port = http,https
  6. filter = apache-404
  7. action = iptables[name=404, port=http, protocol=tcp]
  8.         sendmail-whois[name=404, dest=адрес@вашей.почты, sender=fail2ban@сервер]
  9. logpath = /var/log/ispconfig/httpd/*/access.log
  10.                 /var/www/*/log/access.log
  11.                 /var/www/*/logs/access_log
  12. #Время блокировки узла в секундах, при отрицательном значении блокировка постоянная
  13. bantime = 3600
  14. #Промежуток времени необходимый для блокировки
  15. findtime = 60
  16. #количество неудачных попыток, необходимых для блокировки
  17. maxretry = 5

Проверить выражение fail2ban можно с помощью его же встроенного проверяльщика 

fail2ban-regex /путь/до/лог/файла /путь/до/конфига

например

fail2ban-regex /var/log/mail.log /etc/fail2ban/filter.d/sasl.conf

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

fail2ban-regex /var/log/mail.log /etc/fail2ban/filter.d/sasl.conf /etc/fail2ban/filter.d/sasl.conf

Посмотреть статистику по каждому конфигу можно вот так:

  1. fail2ban-client status ssh-iptables
  2. fail2ban-client status apache-404

Должно отобразиться что-то вроди этого:

  1. Status for the jail: ssh-iptables
  2. |- filter
  3. |  |- File list:        /var/log/secure
  4. |  |- Currently failed: 0
  5. |  `- Total failed:     5
  6. `- action
  7.    |- Currently banned: 1
  8.    |  `- IP list: 123.123.123.123
  9.    `- Total banned:     1

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

Заблокировать ip адрес с помощью iptables (-A (append), есть еще -I (insert)) 

iptables -A INPUT -s 123.123.123.123 -j DROP

Разблокировать:

iptables -D INPUT -s 123.123.123.123 -j ACCEPT

Заблокировать диапазон адресов

iptables -I INPUT -m iprange --src-range 123.123.123.0-123.123.123.123 -j DROP

Вывести список заблокированных ip адресов можно с помощью команды:

  1. iptables -L -v
  2. iptables -L INPUT -v
  3. iptables -L INPUT -v -n

Поискать конкретный ip в списках блокировки

iptables -L INPUT -v -n | grep 123.123.123.123

Удалить ip, например, из таблицы fail2ban-404 можно с помощью команды:

iptables -D fail2ban-404 -s xxx.xxx.xxx.xxx -j DROP

При этом учтите, что при перезапуске сервера заблокированные в ручную ip сбросятся. Чтобы этого не происходило, нужно подгружать правила iptables при каждой загрузке. Сделать это можно вот так.

Создаем файл /sbin/ifup-local (это аналог Debian /etc/network/if-up.d/00-iptables) следующего содержания:

  1. #!/bin/bash
  2. iptables-restore < /etc/firewall.conf
  3. ip6tables-restore < /etc/firewall6.conf

Даем ему право на выполнение

chmod +x /sbin/ifup-local

Выполняем команды, чтобы сохранить текущую конфигурацию iptables

  1. iptables-save >/etc/firewall.conf
  2. ip6tables-save >/etc/firewall6.conf

После перезагрузки правила iptables не сбросятся (точнее, будут прочитаны из конфиг файла — т.е. будут соответствовать правилам на момент сохранения конфигурации). Однако, при частом изменении правил такой вариант будет неудобен тем, что нужно постоянно сохранять текущую конфигурацию. Банально, можно забыть это сделать.

В случае, если редактирование правил iptables производится постоянно, нужно создать файл /sbin/ifdown-local, который выполняется системой при каждом выключении, дать ему права на выполнение и вписать в него следующие строки

  1. #!/bin/bash
  2.  
  3. iptables-save > /etc/firewall.conf
  4. ip6tables-save > /etc/firewall6.conf

Немного иначе дело обстоит в Debian, там нужно будет добавить следующие строки в файл /etc/network/interfaces

  1. pre-up iptables-restore < /etc/iptables.rules
  2. post-down iptables-save > /etc/iptables.rules

Вот еще пара конфигов, защищающих от различных атак.

Этот я накидал сам. Здесь мы пытаемся отловить слишком частый доступ к сайту в единицу времени. Попытку выкачать наш контент. Этим скриптом я поймал сайт BESTCLONNAME.RU, например.

Со значениями findtime = 60 и maxretry = 10 можно поиграться и подобрать лучший вариант…

Файл конфига apache-ddos.conf

  1. # Fail2Ban configuration file
  2. # Author: AmiGator
  3.  
  4. [Definition]
  5.  
  6. failregex = ^<HOST> -.*"(GET|POST).*HTTP.*"
  7.  
  8. # Option:  ignoreregex
  9. # Notes.:  regex to ignore. If this regex matches, the line is ignored.
  10. #
  11. ignoreregex =

Подключение в jail.local

  1. [apache-ddos]
  2.  
  3. enabled  = true
  4. filter   = apache-ddos
  5. action   = iptables-multiport[name=ddos, port="http,https"]
  6.            sendmail-buffered[name=ddos, lines=5, dest=root]
  7. logpath  = /var/www/*/log/access.log
  8. bantime  = 1800
  9. findtime = 60
  10. maxretry = 10
  11.  
  12. ignoreregex = \.(jpg|jpeg|png|gif|js|css)

Защита от попытки доступа к различным директориям и админкам разных CMS. Тут все индивидуально и я не советую тупо копировать содержимое. Нужно настроить под себя!

Создаем файл apache-nokiddies.conf

  1. # Fail2Ban configuration file
  2. # Author: Miniwark
  3.  
  4. [Definition]
  5. failregex = ^<HOST> .*"GET .*w00tw00t
  6. # try to access to admin directory
  7.            ^<HOST> .*"GET .*admin.* 403
  8.             ^<HOST> .*"GET .*admin.* 404
  9. # try to access to install directory
  10.            ^<HOST> .*"GET .*install.* 404
  11. # try to access to phpmyadmin
  12.             ^<HOST> .*"GET .*dbadmin.* 404
  13.            ^<HOST> .*"GET .*myadmin.* 404
  14.             ^<HOST> .*"GET .*MyAdmin.* 404
  15.            ^<HOST> .*"GET .*mysql.* 404
  16.             ^<HOST> .*"GET .*websql.* 404
  17.            ^<HOST> .*"GET \/pma\/.* 404
  18. # try to access to wordpress (we use another CMS)
  19.             ^<HOST> .*"GET .*wp-content.* 404
  20.            ^<HOST> .*"GET .*wp-login.* 404
  21. # try to access to typo3 (we use another CMS)
  22.             ^<HOST> .*"GET .*typo3.* 404
  23. # try to access to tomcat (we do not use it)      
  24.            ^<HOST> .*"HEAD .*manager.* 404
  25. # try to access various strange scripts and malwares
  26.             ^<HOST> .*"HEAD .*blackcat.* 404
  27.            ^<HOST> .*"HEAD .*sprawdza.php.* 404
  28.  
  29. ignoreregex =

Подключение

  1. [apache-nokiddies]
  2. # ban script kiddies
  3. enabled  = true
  4. port     = http,https
  5. filter   = apache-nokiddies
  6. action = iptables-multiport[name=nokiddies, port="http,https", protocol=tcp]
  7. logpath  = /var/www/*/log/access.log
  8. maxretry = 1