Делать будем на примере панельки 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

Теперь в директории /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 тут:

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