# Создание фильтра для Fail2ban

Fail2ban — приложение, позволяющее контролировать подключения к вашему серверу, отслеживать повторяющиеся попытки входа и блокировать определённые IP-адреса на основе заданных правил.

По умолчанию в Fail2ban встроено несколько фильтров, позволяющих обеспечить базовую защиту большинству веб-интерфейсов вашего сервера: ssh, веб-серверы и т.д.

Но иногда возникают ситуации, когда атака на сервер ведётся более изобретательно, и стандартные шаблоны Fail2ban с ней не справляются. В этом случае можно самостоятельно написать фильтр, который будет отслеживать конкретные паттерны в поведении ботов и блокировать их.

В этой инструкции мы создадим новый фильтр для защиты SSH-подключения.

Для начала работы нам понадобится подготовленный к работе сервер с установленным приложением Fail2ban.

# Признаки атаки

Основной признак попыток взлома вашего сервера — «подозрительная активность» в логах SSH-подключения. Это могут быть регулярные попытки подключения с разных IP-адресов, запросы к различным портам сервера, запросы на получение ключей и т.д.

Прочитать логи ssh-подключения можно с помощью команды:

journalctl -u ssh | tail -20

Она выведет на экран 20 последних записей из лога SSH-подключения. Как правило, этого количества данных бывает достаточно, чтобы визуально определить попытку взлома сервера.

Мы разберём создание фильтра на примере одной из строк из лога ssh-подключения:

Mar 30 14:41:25 host_name sshd[2909]: Disconnected from invalid user ramon 178.128.19.209 port 54288 [preauth]

Нам нужно создать правило, которое будет находить все подобные строки в логах и блокировать указанный здесь IP.

# Создание правила

Начнём с определения правила, по которому будут блокироваться IP. Для этого нам нужно описать строку, в которой фигурирует интересующий нас IP.

Строка, которую мы взяли за основу:

Mar 30 14:41:25 host_name sshd[2909]: Disconnected from invalid user ramon 178.128.19.209 port 54288 [preauth]

Она состоит из временной метки Mar 30 14:41:25, указания имени хоста, обозначения процесса (в данном случае sshd) и собственно описания события Disconnected from invalid user ramon 178.128.19.209 port 54288 [preauth].

Из итоговой строки можно убрать временную метку и обозначение процесса — Fail2ban по умолчанию воспринимает большинство временных меток и игнорирует их при обработке правил. Это упрощает нам задачу.

Остаётся такой вариант строки: Disconnected from invalid user ramon 178.128.19.209 port 54288 [preauth].

Теперь необходимо оставить основной текст, который не будет меняться от одного сообщения к другому, и заменить только переменные, в нашем случае это IP, имя пользователя и порт, по которому происходит подключение. Заменим порт и имя пользователя на выражения, означающие «Любое значение», поскольку они нам не важны. Значение IP-адреса заменим на указание того, что это и есть хост, который нужно заблокировать. В итоге получится следующая строка:

Disconnected from invalid user [A-Z]+ <HOST> port [0-9]+ \[preauth\]

Это и есть готовое выражение, на основании которого мы будем производить фильтрацию логов.

# Создание фильтра

Теперь нужно создать фильтр — текстовый файл, в котором будут указаны правила фильтрации. В нашем случае это будет одна строка.

Создаём файл в директории, где размещаются все фильтры Fail2ban:

sudo vim /etc/fail2ban/filter.d/new_filter.conf

Содержимое файла будет следующим:

[Definition]
failregex = Received disconnect from <HOST> port [0-9]+:11: (Bye Bye)? \[preauth\]

Блок [Definition] здесь определяет исполняемую часть файла. Вариант написания этого блока (с заглавной буквы) также очень важен для синтаксиса программы.

В строке failregex = указываем наше правило, созданное на предыдущем шаге. Здесь можно указывать несколько правил, по которым будет производиться отбор. Разделять правила в таком случае нужно пустой строкой.

Если мы хотим добавить какой-то IP-адрес в список игнорируемых, то можно указать его ниже, добавив параметр ignoregex =.

Основное правило создано, теперь проверим, как оно работает.

# Проверка правила

Для проверки работы созданных правил в Fail2ban существует встроенный инструмент regex. Общий вид команды выглядит следующим образом:

sudo fail2ban-regex <log_file> <filter_file> <ignore_file>

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

Также в этой строке можно указывать не только путь к файлу с правилом, но и непосредственно само правило, заключённое в одинарные кавычки.

Далее введите команду:

sudo fail2ban-regex /var/log/auth.log /etc/fail2ban/filter.d/new_filter.conf

Если мы всё сделали правильно, на выходе будет примерно следующая информация:

# Output
Lines: 16622 lines, 0 ignored, 2738 matched, 13884 missed
[processed in 1.27 sec]

Здесь мы видим количество проанализированных строк, проигнорированных, совпавших и пропущенных, а также время, которое программа потратила.

Эта запись означает, что наш фильтр настроен правильно, можно переходить к созданию jail’а на основе фильтра.

# Создание jail

Мы не будем добавлять новый фильтр в наш основной jail, а создадим новый в общей папке:

sudo vim /etc/fail2ban/jail.d/new_jail.conf

Содержимое jail’а будет следующим:

[myservice]
enabled  = true
port = all
filter = myservice
logpath = /var/log/auth.log
maxretry = 5
findtime = 60
bantime = 600

Основные параметры, указанные здесь, совпадают со стандартными параметрами jail’ов, которые мы описывали в инструкции по настройке Fail2ban:

  • [myservice] — название нашего jail’а;
  • enabled — указание на активность jail’а (включён/выключен);
  • port — здесь указываются порты, для которых будет работать наш фильтр. Можно указать словами или прописать конкретные значения (http, https, all, 22…);
  • filter — здесь указываем название нашего фильтра (имя файла до .conf), в нашем случае это new_filter;
  • logpath — это путь к файлу с логами, которые будет анализировать фильтр, указываем путь к логам /var/log/auth.log;
  • maxretry, findtime, bantime — параметры для поиска и бана — количество попыток, вызывающее срабатывание, время, за которое производится поиск и время бана. Здесь они указаны в секундах, но можно указывать часы, дни и недели, добавляя после значения h, d и w соответственно.

После указания всех нужных параметров и сохранения текстового файла работу можно считать законченной — фильтр создан и готов к началу применения. Осталось только перезагрузить Fail2ban и проверить, что jail определился:

sudo systemctl restart fail2ban
fail2ban-client status

Вторая команда должна вывести в консоль список всех активных jail’ов.

Если вы хотите посмотреть на статус работы конкретного jail’а, можно добавить его имя в строку запроса статуса:

sudo fail2ban-client status new_filter

#Output
Status for the jail: new_filter
|- Filter
|  |- Currently failed: 0
|  |- Total failed:     1707
|  `- File list:        /var/log/auth.log
`- Actions
   |- Currently banned: 409
   |- Total banned:     410
   `- Banned IP list:

Готово! Фильтр настроен и работает. С момента запуска он заблокировал более 400 IP-адресов, удовлетворяющих нашему правилу. Это значит, что на сервер велась атака, и она успешно отражена.