Крайне полезное серверное приложение Linux – настраиваем под себя
Про установку и запуск читаем здесь
Для самостоятельной настройки нужно:
- лог с данными
- настроить фильтр (получение IP из лога)
- действия (что делать с этими IP)
- и джайл – связать фильтр и действие :)
Например, как это сделать для блокировки ботов-подборщиков логина и пароля в WordPress – читаем статью
Блокируем ботов-подборщиков через fail2ban
Или создаем свой вариант.
Делаем свой лог
Например в корневой папке web-server (в папках выше политика безопасности сервера не даст доступа нашему php-скрипту)
<?php
$root_webserver = '/var/www/user/data/www/';
// это корневая папка web server, а не DOCUMENT_ROOT сайта
$my_dir = $root_webserver.'_mylog';
if (! file_exists ($my_dir)){
mkdir ($my_dir, 0777);
}
$file_var = $my_dir.'/test.log';
$size_log = filesize ($file_var); //при отсутствии файла будет false
$bot_info = date("Y-m-d H:i:s").' '.'192.168.1.1 и другая информация'.PHP_EOL; // перевод строки
if ( $size_log === FALSE || $size_log > 300000 ) {
// файла нет или он больше 300 000 байт - делаем новый
file_put_contents($file_var, $bot_info, LOCK_EX);
}else{ // в остальных случаях дописываем в старый
file_put_contents($file_var, $bot_info, FILE_APPEND | LOCK_EX);
}
?>
Дата и время должны записываться в лог в определенном формате, что бы фильтр fail2ban можно было настроить корректно (там потом будет анализ периода заходов бота). Основной стандартный формат ниже (но fail2ban понимает и другие варианты)
год-месяц-день часы:минуты:секунды
поэтому используем php – date(“Y-m-d H:i:s”)
В результате этого колдунства у нас получилось:
- в папке /var/www/user/data/www/ (на Вашем сервере может быть другой путь) появилась новая папка “_mylog“
- в этой папке файл “test.log” (общий лог для всех Ваших сайтов на VPS)
- при превышении размера ~300kb – файл создается заново (или можно сделать ротацию логов)
- переменную $bot_info можно собрать как удобнее – главное дата/время и IP
Итого мы имеет лог-файл с адресом вида (в который пишутся строки с IP-адресами ботов)
/var/www/user/data/www/_mylog/test.log
который мы и будет “скармливать” fail2ban
Делаем свой фильтр (что бы вытащить IP из лога)
- Вопрос – может ли fail2ban работать без файла фильтра?
- Нет, не может. Приложению fail2ban необходимо получить IP-адрес из лога – а это как раз делает фильтр с помощью regex
Пишем свой фильтр. Свой фильтр можно создавать с названием myfilter.conf в папке filter.d/
Общая структура фильтра. В файле фильтра может быть два раздела:
- [INCLUDES} – необязательно
- before = common.conf
- after = filtername.local
- [Definition]
- failregex = ….
- ignoreregex = ….
Раздел [INCLUDES] указывает на файлы фильтров, которые читаются до или после этого файла. Файл common.conf считывается и помещается перед другими строками в этом файле, а файл filtername.local – после . Эти файлы устанавливают некоторые параметры, которые будут использоваться далее в конфигурации.
Раздел [Definition] указывает на выражения regex, которые нужно применить к файлу лога или исключить из обработки.
Формат выражения failregex:
- должно начинаться с символа ^ – это означает для fail2ban, что будет анализироваться текст после формата даты Y-m-d H:i:s. Есть недокументированная возможность вместо символа ^ использовать свое выражения для формата даты (если в Вашем логе дата формируется по другому), cм. ошибку Debian # 491253
- директива <HOST> – для определения IP-адреса в строке лога (для версии ниже 0.10 работает только для IP v4). Этот тэг <HOST> – внутренняя замена fail2ban регулярного выражения (?:::f{4,6}:)?(?P<host>\S+)
Итого вида failregex = ^ регулярное выражение <HOST> регулярное выражение
Правила, используемые вашей версией fail2ban, зависят от версии питона, используемого в системе.
# python -V Python 2.7.13
У нас фильтр будет относительно простой, т.к. в логе уже собраны адреса IP только “вредителей”, не нужно дополнительно искать по условию regex текстовую строку с описанием ошибки. Нам нужно простое регулярное выражение, которое будет “видеть” IP в строках лога.
failregex = ^ <HOST>
Проверим, как работает фильтр (команда + лог + фильтр). Для проверки может быть в качестве фильтра использован или файл с фильтром или сам фильтр (в кавычках)
fail2ban-regex /var/www/user/data/www/_mylog/test.log '^ <HOST>'
удобно тестировать по одной строке.
Результат
- 311 совпадений найдено
- формат даты распознан
Итого наш вариант файла testfilter.conf для папки filter.d
[Definition] failregex = ^ <HOST> ignoreregex =
Проверяем полностью
fail2ban-regex /var/www/user/data/www/_mylog/test.log /etc/fail2ban/filter.d/testfilter.conf
Вот кстати, полный отчет fail2ban по обнаружению формата даты в логе
Date template hits: |- [# of hits] date format | [311] Day(?P<_sep>[-/])MON(?P=_sep)Year[ :]?24hour:Minute:Second(?:.Microseconds)?(?: Zone offset)? | [0] (?:DAY )?MON Day 24hour:Minute:Second(?:.Microseconds)?(?: Year)? | [0] Year(?P<_sep>[-/.])Month(?P=_sep)Day 24hour:Minute:Second(?:,Microseconds)? | [0] Day(?P<_sep>[-/])Month(?P=_sep)(?:Year|Year2) 24hour:Minute:Second | [0] Month/Day/Year:24hour:Minute:Second | [0] Month-Day-Year 24hour:Minute:Second.Microseconds | [0] TAI64N | [0] Epoch | [0] Year-Month-Day[T ]24hour:Minute:Second(?:.Microseconds)?(?:Zone offset)? | [0] ^24hour:Minute:Second | [0] ^<Month/Day/Year2@24hour:Minute:Second> | [0] ^Year2MonthDay ?24hour:Minute:Second | [0] MON Day, Year 12hour:Minute:Second AMPM | [0] ^MON-Day-Year2 24hour:Minute:Second
Делаем JAIL (файл, в котором укажем лог и необходимые действия)
указываем название фильтра и лога, к которому он применяется.
Тюрьму (“JAIL”) будем делать нестандартную. Обычно используется вариант вида “пять одинаковых адресов IP за период” – и в бан на 15 мин.
Можно сделать расширенный вариант – если в логе есть три раза один и тот же IP – то это точно “вредитель”.
Баним его сразу на 30 дней (и время обнаружения тоже 30 дней). Не забываем установить время хранения IP в базе хотя бы 31 день. Период хранения IP адреса в базе находится в файле fail2ban.conf. Необходимо создать и использовать файл fail2ban.local, в котором мы изменим время хранения.
# 31 days dbpurgeage = 2678400
Т.к. файл логов периодически начинает вестись с нуля – какие-то IP будут из бана возвращаться через месяц. При наборе очередных 3 попыток – опять бан. Это будет работать и для любителей делать 10 запросов в секунду. Тоже будут заблокированы на 30 дней.
[test] enabled = true filter = testfilter logpath = /var/www/user/data/www/_mylog/test.log # 30 days bantime = 2592000 findtime = 2592000 maxretry = 3
Перезапускаем fail2ban
смотрим в логах /var/log/fail2ban.log
вот всё и заработало:
- Jail ‘test’ создан
- лог-файл добавлен
- наши параметры добавлены
- jail ‘test’ запущен
- три обнаружения и бан
ВАЖНО fail2ban начинает парсить лог по умолчанию с момента своего запуска! Более ранняя часть лога не анализируется. Т.е. если у Вас, например, время обнаружения 1 час, а Вы перезапустили сервис полчаса назад = лог будет просмотрен только на полчаса назад. Это не особо критично для коротких времен обнаружения findtime, но нужно учитывать при больших периодах (т.е. время обнаружения сильно больше, чем время с момента перезапуска fail2ban) |
Посмотрим, что у нас там в “клетке” набралось
sudo iptables -L -n
да, через серверную утилиту iptables
Да, всё хорошо – вот они “вредители” с блоком на 30 дней.
А потом начинается “дискотека” в логе fail2ban – забаненные пытаются еще раз что-то сделать нехорошее.
За 20 секунд – 19 попыток… В среднем 1 раз в секунду.
И все они закончились на входе на сервер (на уровне netfilter), ни до Apache, ни до WordPress запросы уже не дошли.
Долговременный бан для тупых ботов
Например, по умолчанию боты, которые пытаются сломать SSH – блокируются на 10 мин (со временем обнаружения 10 мин и 5 попытками).
Потом netfilter выводит их из бана. Результат ниже.
Через 1 минуту после снятия блокировки бот занялся подбором…
Нехорошо. Как с этим бороться?
Можно увеличить сразу время бана для таких ботов. А можно пойти другим путем.
У fail2ban есть же свой лог :)
tail -f /var/log/fail2ban.log
/var/log/fail2ban.log – вот этот его собственный лог мы еще раз отдадим на анализ в fail2ban:
- три попадания IP в бан
- период – сутки
- бан для такого IP – на месяц
в результате совсем “тупые” боты будут блокированы на 30 дней.
пишем фильтр fail2ban_f.conf:
- первое выражение regex ищет IP-адреса, которые получили Ban
- второе выражение regex исключает из списка баны, полученные уже правилом {fail2ban}
[Definition] failregex = ^.*?fail2ban\.actions.*?Ban\s+<HOST>$ ignoreregex = ^.*?fail2ban\.actions.*?\[fail2ban\]\sBan
и джайл fail2ban_d.conf
[fail2ban] enabled = true filter = fail2ban_f # block all ports action = iptables-allports[name=FAIL2BAN] logpath = /var/log/fail2ban.log maxretry = 3 # 1 day findtime = 86400 # 30 days bantime = 2592000
Проверяем и запускаем.
ВАЖНО При ограниченных ресурсах VPS возможно получение ошибок вида “iptables: Memory allocation problem”. Это желающих сломать (например SSH) больше, чем место под правила блокировок в iptables. Т.е. работает такой себе хороший ботнет с большим количеством IP. Смотрим: cat /proc/user_beancounters Параметр numiptent определяет количество правил iptables, которые мы можем создать. |
Но результат работы jail [fail2ban] того стоит, 30 дней побудут в бане