Настраиваем fail2ban и cloudflare для защиты от http флуда

Делать будем на примере панельки vestacp со стандартной связкой nginx + apache. В принципе различий между настройками в иных панельках особо нет, за исключением некоторых моментов с размещением лог файлов и конфигураций nginx или apache.

Цимес заключается в том, что если ваш сайт подключен через cloudflare, то http соединения с вашим сервером происходят  от серверов cloudflare. Однако при этом в логах вы видите реальный ip клиента. И даже если вы внесете в  бан файрвола на своем сервере любой ip из своих логов, эти клиенты всё равно будут подключаться без проблем. Как же это происходит? Загляните в свой /etc/nginx.conf и сразу поймете:

    # Cloudflare https://www.cloudflare.com/ips
    set_real_ip_from 103.21.244.0/22;
    set_real_ip_from 103.22.200.0/22;
    set_real_ip_from 103.31.4.0/22;
    set_real_ip_from 104.16.0.0/12;
    set_real_ip_from 108.162.192.0/18;
    set_real_ip_from 131.0.72.0/22;
    set_real_ip_from 141.101.64.0/18;
    set_real_ip_from 162.158.0.0/15;
    set_real_ip_from 172.64.0.0/13;
    set_real_ip_from 173.245.48.0/20;
    set_real_ip_from 188.114.96.0/20;
    set_real_ip_from 190.93.240.0/20;
    set_real_ip_from 197.234.240.0/22;
    set_real_ip_from 198.41.128.0/17;
    set_real_ip_from 2400:cb00::/32;
    set_real_ip_from 2606:4700::/32;
    set_real_ip_from 2803:f800::/32;
    set_real_ip_from 2405:b500::/32;
    set_real_ip_from 2405:8100::/32;
    set_real_ip_from 2c0f:f248::/32;
    set_real_ip_from 2a06:98c0::/29;
    real_ip_header     CF-Connecting-IP;

IP клиента передается в заголовке CF-Connecting-IP, его и пишет в лог ваш сервер при соединении с данными подсетями сервиса cloudflare. Кстати по ссылке вы можете увидеть все эти подсети.

Следовательно, банить клинтов нужно используя не только файрвол сервера, а также в первую очередь банить через файрвол cloudflare передавая ему по api конфигурацию бана. Для этого в директории /etc/fail2ban/action.d/ создадим соответствующий конфиг действий cloudflare.conf Кстати там уже есть данный файл, но он использует старое api, так что можно смело писать в него новый конфиг такого содержания:

#
# To get your Cloudflare API key: https://www.cloudflare.com/my-account
#

[Definition]

# Option:  actionstart
# Notes.:  command executed once at the start of Fail2Ban.
# Values:  CMD
#
actionstart =

# Option:  actionstop
# Notes.:  command executed once at the end of Fail2Ban
# Values:  CMD
#
actionstop =

# Option:  actioncheck
# Notes.:  command executed once before each actionban command
# Values:  CMD
#
actioncheck =

# Option:  actionban
# Notes.:  command executed when banning an IP. Take care that the
#          command is executed with Fail2Ban user rights.
# Tags:      IP address
#            number of failures
#            unix timestamp of the ban time
# Values:  CMD

actionban = curl -s -X POST "https://api.cloudflare.com/client/v4/user/firewall/access_rules/rules" \
            -H "X-Auth-Email: <cfuser>" \
            -H "X-Auth-Key: <cftoken>" \
            -H "Content-Type: application/json" \
            --data '{"mode":"block","configuration":{"target":"ip","value":"<ip>"},"notes":"Fail2ban"}'

# Option:  actionunban
# Notes.:  command executed when unbanning an IP. Take care that the
#          command is executed with Fail2Ban user rights.
# Tags:      IP address
#            number of failures
#            unix timestamp of the ban time
# Values:  CMD
#

actionunban = curl -s -o /dev/null -X DELETE -H 'X-Auth-Email: <cfuser>' -H 'X-Auth-Key: <cftoken>' \
            https://api.cloudflare.com/client/v4/user/firewall/access_rules/rules/$(curl -s -X GET -H 'X-Auth-Email: <cfuser>' -H 'X-Auth-Key: <cftoken>' \
            'https://api.cloudflare.com/client/v4/user/firewall/access_rules/rules?mode=block&configuration_target=ip&configuration_value=<ip>&page=1&per_page=1' | tr -d '\n' | cut -d'"' -f6)

[Init]

# Option: cfuser
# Notes.: Replaces <cfuser> in actionban and actionunban with cfuser value below
# Values: Your CloudFlare user account

cfuser = YOU_MAIL

# Option: cftoken
# Notes.: Replaces <cftoken> in actionban and actionunban with cftoken value below
# Values: Your CloudFlare API key 
cftoken = YOU_API_TOKEN

свой api токен вы можете посмотреть в профиле аккаунта cloudflare

api cloudflare token
API token cloudflare

Теперь в директории /etc/fail2ban/filter.d/ создадим фильтр с названием http-ddos.conf и таким содержимым:

# Fail2Ban configuration file

[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> -.*"(GET|POST|CONNECT|HEAD).*

# Option: ignoreregex
# Notes.: regex to ignore. If this regex matches, the line is ignored.
# Values: TEXT
#
ignoreregex =

А в директории /etc/fail2ban/jail.d/ создадим конфиг http-ddos.conf

[http-ddos]
enabled = true
filter = http-ddos
action = cloudflare
         iptables-multiport[name=http-ddos, port="http,https", protocol=tcp]
port = http,https
logpath  = /var/log/apache2/domains/*com.log
           /var/log/apache2/domains/*ru.log
findtime = 60
bantime = 86400
maxretry = 1200

С шаблонами логов тут пришлось немного извратиться, поскольку vesta не добавляет access в названиях файлов. А там лежат ещё error логи, которые в данном случае, нам не нужны. А как прописать шаблон с исключением в данном конфиге я не знаю, ведь это не обычная регулярка. Можно конечно настраивать локально CustomLog в дерективах апача для каждого сайта и задать любые названия лог файлов с любыми префиксами, но тогда логи не просматриваются из панельки. И нужно тогда пилить ещё и панельку на строке:

/usr/local/vesta/data/templates/web/apache2/default.tpl:12:    CustomLog /var/log/%web_system%/domains/%domain%.log combined

Решил не заморачиваться и добавить шаблоны по доменным зонам.

  • findtime — это время в секундах по которому будет просматриваться совпадения
  • bantime — время бана
  • maxretry — максимальное количество совпадений за указанный период, после которого наступает банэ

Эти параметры нужно настраивать внимательно и индивидуально, чтобы не забанить лишних юзеров.

И теперь, для того, чтобы каждого клиента fail2ban не писал в свой лог, поменяем loglevel в файле /etc/fail2ban/fail2ban.conf указав loglevel = NOTICE По умолчанию там стоит INFO и в лог пишется каждое совпадение с шаблоном.

Выполним fail2ban-client -d для проверки конфигураций.

В vestacp ротация логов apache почему-то настроена в еженедельном режиме weekly. Это не есть хорошо и может сказаться на производительности при анализе fail2ban-ом больших файлов. Этот режим необходимо поменять на daily в файле /etc/logrotate.d/apache2 Если есть большие лог файлы на данный момент их нужно удалить  и перезапустить апач. Теперь перезапустим сервис systemctl restart fail2ban

Все подключенные джайлы можем видеть по команде fail2ban-client status  Всех забаненных по нашему вновь созданному файлу можем видеть по команде fail2ban-client status http-ddos а также в панельке cloudflare во вкладке firewall тут:

Firewall cloudflare
Firewall cloudflare

Бан и разбан происходит как на уровне iptables сервера, а также отправляется в бан файрвола сервиса cloudflare.

Оставить ответ

Ваш адрес email не будет опубликован. Обязательные поля помечены *