Инструменты пользователя

Инструменты сайта


wiki:sistemnoe_administrirovanie:ispolzovanie_bash-skriptov:skript_dlja_fail2ban

Скрипт для fail2ban

Предисловие

Как и многие системные администраторы, при настройке fail2ban, я руководствовался «рекомендациями» из интернета.
Чаще всего «рекомендации» были примерно такими: 10 ошибочных попыток за 30 минут и блокировка на 1 час. И особо не задумывался что будет в реальности при таких настройках.
В конце 2024 года решил более внимательно «поковыряться» со всем этим. Но для «ковыряния» нужен «инструмент». Беглый поиск «инструмента» ничего не дал подходящего для меня. Тогда и был написан этот скрипт для «ковыряния».

Защита сервиса

Защита любого сервиса (ssh, ftp, www, smb…) состоит из двух частей.

  1. Аутентификация самим сервисом. Т.е. сам сервис определяет кому/когда/что он может «предоставить». Здесь используются различные методы: ip, пароли, ключи и т.д. Обрабатывается самим сервисом!
  2. FireWall. Блокировка доступа к сервису. Т.е. допустить или запретить попадание «запросов» к сервису по тем или иным признакам. FireWall ничего не знает про аутентификацию на сервисе (методы, пароли, ключи и т.д.). Его «задача» определить/найти что сервис отверг запрос и выполнить свои действия.

У некоторых системных администраторов есть, например, мнение, что для ssh не нужен FireWall. Достаточно правильно настроить ssh и только. Считаю подобное - ошибочным мнением. И мой аргумент - FireWall блокирует именно доступ к сервису. Запросы не доходят до сервиса и сервисом НЕ обрабатываются! На тот же ssh в день (24 часа) могут приходить десятки тысяч запросов из интернета с одного ip (атака на ssh по словарю, например). И на все эти запросы ssh будет отвечать отказами (обрабатывать!). Зачем такая нагрузка на ssh, если FireWall способен просто блокировать эти ip? Правильная настройка ssh и FireWall дополняют друг друга.

Примечания

1. Далее в тексте буду использовать названия параметров из fail2ban:

  • findtime = скользящее временное окно поиска «ошибочных» подключений
  • maxretry = количество «ошибок» подключений
  • bantime = длительность блокировка (ban)

Пример 1:

  • findtime = 30m
  • maxretry = 30
  • bantime = 1h

Т.е. если fail2ban нашел 30 «ошибок» за 30 минут, то хост (ip) блокируется (ban) на 1 час. Это основные настройки fail2ban, но не единственные.

2. Под «ошибкой» подключения подразумеваю любые ошибки любых протоколов, что найдет fail2ban. У fail2ban достаточно большой набор правил поиска таких ошибок для разных протоколов.

3. fail2ban использует две таблицы: «Found» и «Ban». Таблица «Found» обнуляется при перезапуске сервиса fail2ban! Таблица «Ban» всегда сохраняется. Обнуление таблицы «Found» приводит к тому, что fail2ban счетчик «ошибок» обнуляется! Это надо иметь в виду при больших значениях findtime (дни, недели и т.д.)!
Но если был добавлен/изменен фильтр, то нужно перезапустить сервис fail2ban!

Простая/жесткая настройка fail2ban

Рассмотрим что происходит при настройках из «Пример 1» выше. Допустим хост попал под эти правила и получил ban. Но после окончания bantime этот хост может продолжать свои попытки.

Примеры реальных ситуаций

Примеры реальных ситуаций

 Статистика за 1 день За 1 день (24 часа) fail2ban нашел 13182 «попыток» подключений с 536 хостов (ip). Причем 593 «попыток» было от 185.147.124.54! И на момент получения статистики ни один хост НЕ забанен!

 185.147.124.54 Здесь видно, что с ip 185.147.124.54 приходят 7-9 запросов за 1 минуту, потом идет перерыв 20 минут. Получается, что этот ip даже не подпадает под правила из «Пример 1»!

Причем, под правила из «Пример 1» не подпадают целые сети! Например, 298 хостов (ip) из сети 45.78.* «засветились» (скрин ниже).  45.78.*
Классика. На скрине ниже 59.98.148.5 сделал 31 попытку за 46 минут и не подпал под правила из «Пример 1»!  59.98.148.5


Посчитаем что может получится за 1 день (24 часа) в пределе из «Пример 1» выше.
Для того, чтобы быть «непойманым», атакующему хосту надо делать 30-1=29 попыток за 30 минут. Далее считам. 24 часа / 30 минут = 48 интервалов по 30 минут. 48 интервалов * 29 попыток = 1392 попыток за 24 часа. И это только для одного хоста (ip) за 1 день! Мне это не понравилось.

Плюс надо добавить, что атакующий достаточно легко может получить реальные значения findtime, maxretry и bantime. Это можно сделать в любом скриптовом языке.

Пример простого алгоритма.

Пример простого алгоритма.

Делаем попытки подключения с интервалом, например, 0,5 секунд и считаем сколько будет ответов до получения ban-а. Все, maxretry у нас есть. Присваиваем time_min=0
Далее. Произвольно берем time_max=2 часа.

int=time_max/(maxretry-1)

- это будет интервал наших попыток. После снятия ban (получили выше) делаем попытки с интервалом int. Если по прошедствии time_max мы Не получили ban, то новый

time_max=time_max/2
int=time_max/(maxretry-1)

и повторяем этот этап. И так до тех пор пока не получим ban. И теперь присваиваем

time_min=time_max

Если же по прошедствии time_max мы получили ban, то новый

time_max=time_max*2
int=time_max/(maxretry-1)

и умножаем на 2 до тех пор, пока не перестанем получать ban!
На данный момет findtime находится между time_min и time_max!
Далее используем метод половинного деления (метод сходится хорошо).
Вычисляем очередной интервал

int=((time_min+time_max)/2)/(maxretry-1)

посылок запросов. Если за время

(time_min+time_max)/2

получили ban, то

time_min=(time_min+time_max)/2

(увеличиваем time_min),

int=((time_min+time_max)/2)/(maxretry-1)

Если за время

(time_min+time_max)/2

НЕ получили ban, то

time_max=(time_min+time_max)/2

(уменьшаем time_max),

int=((time_min+time_max)/2)/(maxretry-1)

И опять делаем запросы с новым значением int. С каждой такой итерацией границы time_min и time_max будут сближаться достаточно быстро. Можно остановиться когда

time_max-time_min

будет, например, меньше 5 минут. И тогда искомый findtime будет равен time_max. Все! ;))
Это примерный алгоритм (не единственный). Достаточно простой для реализации в скрипте.


По сути подобные настройки не годятся для интернета.

Настройка fail2ban с "Increase Ban"

В основе этой настройки тоже лежат findtime, maxretry и bantime. Но к ним добавляются параметры bantime.factor, bantime.increment, bantime.formula и еще несколько.
Опишу только идею «Increase Ban».
Если с простыми/жесткими настройками после снятия очередного ban-а fail2ban «работает» с атакующим хостом как с новым, то с настройками «Increase Ban» fail2ban запоминает что атакующий хост уже получал ban и их количество.
Далее все зависит от количества ban-ов, полученных хостом. А именно, геометрическое увеличение времени блокировки и уменьшение попыток подключений за время findtime.
Как пример (работающий, bantime.factor = 1).
Хост получил первый ban. fail2ban запомнил (таблица «Ban»). После снятия ban-а и при попытках хоста опять подключиться, каждая такая попытка будет считаться за 2 попытки. Т.е. хосту дозволено за время findtime сделать не более maxretry/2 попыток. При превышении хост получает очередной ban, но уже на время bantime*2. После снятия этого ban-а (bantime*2) любая попытка этого хоста будет считаться за 3 попытки. Т.е. дозволено за время findtime сделать не более maxretry/3 попыток и за нарушение - ban уже на bantime*4.
Получается, что с каждым последующим ban-ом количество разрешенных попыток за время findtime уменьшается, а время ban-а растет геометрически (1, 2, 4, 8, 16…).
При настройке «Increase Ban» все зависит от фантазии настраивающего. ;))
Только с «Increase Ban» настройками получается успешно блокировать атакующиее хосты интернета у которых интервал попыток 2-3 часа и более. Такие интервалы имеют сеточки хостов при распределенной атаке.

Пример реальной ситуации для сети 45.78.*

Пример реальной ситуации для сети 45.78.*

bantime.increment: True («Increase Ban»)
bantime.factor = 1

Статистика (сравните со статистикой выше)  Статистика за 1 день
Текущий список забаненых IP из сети 45.78.*.  Список забаненых IP (lnav) из сети 45.78.*
Далее смотрим что было с, например, 45.78.6.213 при настройках из «Пример 1». 45.78.6.213 НЕ попал ни разу!  45.78.6.213_01
Первый ban 45.78.6.213 получил 2025-01-10 05:03:34. Но это уже с другими настройками fail2ban и с «Increase Ban».  45.78.6.213_02 2025-01-11 05:03:34 этот хост получил Unban.
Но с 025-01-11 17:10 хост опять стал пытаться подключиться и в логе появились строчки с «bad - …, 1 # → 2.0»
Эти строчки означают, что fail2ban каждую попытку считает за две (maxretry/2). И уже после 15-ти попыток 2025-01-13 09:47:35 ip 45.78.6.213 получил очередной ban.
Причем «Increase Ban 45.78.6.213 (2 # 2 days, 0:00:00 → 2025-01-15 09:47:34)» показывает что теперь ban на «2 days» (bantime*2)!

И еще один скрин.  45.78.6.213_03 На нем все понятно.

Еще реальный пример с 211.253.9.49

Еще реальный пример с 211.253.9.49

 211.253.9.49_01  211.253.9.49_02 Т.е. 211.253.9.49 получил уже ban на «4w 4d» до «2025-02-18 18:37:58»!


Статистики

Анализ эффективности настроек fail2ban невозможен без сбора статистик и их анализа. Причем, нужно собирать статистики с разными интервалами.

Разбор статистик

Разбор статистик

Статистики за 1 день.  Статистика за 1 день  Статистика за 1 день Сравнивая эти два скрина выше, видим, что максимальное количество подключений от одного ip стало 32. Т.е. эффективность настроек fail2ban стала существенно выше (явно сменились настройки). И все ip с количеством подключения больше 29 заблокированы (banned).

Статистики за 3 дня.  Статистика за 3 дня  Статистика за 3 дня
На скрине выше виден нюанс - есть разрывы ip с (banned)! Т.е. «32 96.78.175.43 (banned)», а «35 186.179.165.28» без (banned), хотя у «186.179.165.28» больше число подключений (35).
И это есть повод для «разборок» с ip 186.179.165.28.

 186.179.165.28 ip «186.179.165.28» получил ban и unban.  186.179.165.28 В данном случае все нормально. ip «186.179.165.28» попал в статистику за 3 дня на 2025-01-19 00:12 (35 подключений), но с 2025-01-16 07:51:54 запросы перестали поступать от него.


Пример реальных DDoS атак

Нажмите, чтобы отобразить

Нажмите, чтобы скрыть

Ниже статистики за 1 день (24 часа) атак на sshd одного сервера. fail2ban настроен с «Increase Ban».
Пояснения:

  • «Всего попыток подключений:» - количество неудачных попыток всех хостов (IP).
  • «Забанено в jail «sshd»:» - количество забаненых IP на момент получения статистики.
  • «Количество попыток подключений» - «первые 20 из 3938». Т.е. атаковали 3938 хостов (IP).

Первая волна атак началась 2025-09-27 (по статистике на 2025-09-28 00:11).  Общая картина Видно, что 2025-09-27 резко увеличилось количество попыток подключений, число атакующих хостов и забаненых хостов.
Пик атак пришелся на 2025-09-30 (статистика на 2025-10-01 00:21): 28249 попыток, 6700 атакующих хостов (IP).

Вторая волна атак началась 2025-10-05 (по статистике на 2025-10-06 00:06).  Общая картина Здесь дополнительно показаны строчки «Получили «Increase Ban»:».
Это и есть проявление режима «Increase Ban». Т.е. количество хостов, которые после снятия ban-ов опять пытались атаковать сервер.


Скрипт Fail2Ban

Собственно описывать скрипт нет смысла - есть «Информация о скрипте» в самом скрипте.
Писал его для себя и он помог и помогает в «разборках» атак и настройках fail2ban, правильных для моих серверов. ;))

Несколько скринов меню

Несколько скринов меню

 Главное меню  Сбор статистик  Просмотр файлов статистик (lnav)


Скрипт рабочий, мной активно используется.
Скрипт можно сохранить под именем, например, «Скрипт для fail2ban» (без кавычек).
Файл скрипта Fail2Ban.bash
Файл описания для скрипта Fail2BanInfo.txt

wiki/sistemnoe_administrirovanie/ispolzovanie_bash-skriptov/skript_dlja_fail2ban.txt · Последнее изменение: 2025-11-09 13:22 — nik

Если не указано иное, содержимое этой вики предоставляется на условиях следующей лицензии: GNU Free Documentation License 1.3
GNU Free Documentation License 1.3 Donate Powered by PHP Valid HTML5 Valid CSS Driven by DokuWiki