Введение
SSH – это фактический метод подключения к облачному серверу. Он надежен и расширяем — по мере разработки новых стандартов шифрования можно создавать новые ключи SSH, что гарантирует безопасность базового протокола. Однако ни один протокол или стек программного обеспечения не является абсолютно непроницаемым, и то, что SSH настолько широко распространен в интернете, означает, что он представляет собой очень предсказуемую поверхность атаки или вектор атаки, через который люди могут пытаться получить доступ.
Любой сервис, который подключен к сети, может быть потенциальной целью такого рода атак. Если вы просмотрите журналы вашего службы SSH, работающей на любом широко используемом сервере, вы часто увидите повторяющиеся систематические попытки входа, которые представляют собой атаки методом перебора паролей как со стороны пользователей, так и со стороны ботов. Хотя вы можете внести некоторые оптимизации в свою службу SSH, чтобы снизить вероятность успеха таких атак почти до нуля, например, отключив аутентификацию по паролю в пользу ключей SSH, они все равно могут представлять небольшую и продолжающуюся угрозу.
Крупные производственные развертывания, для которых это ответственность совершенно неприемлема, обычно реализуют VPN, такой как WireGuard, перед своим службой SSH, чтобы невозможно было подключиться напрямую к стандартному порту SSH 22 из внешнего интернета без дополнительной абстракции программного обеспечения или шлюзов. Эти решения VPN широко доверяются, но добавляют сложности и могут нарушить некоторые автоматизации или другие небольшие программные хуки.
Перед принятием решения о полной настройке VPN или дополнительно к ней можно реализовать инструмент под названием Fail2ban. Fail2ban может значительно смягчить атаки методом перебора путем создания правил, которые автоматически изменяют конфигурацию вашего брандмауэра, чтобы блокировать определенные IP-адреса после определенного числа неудачных попыток входа. Это позволит вашему серверу укрепить защиту от этих попыток доступа без вашего вмешательства.
В другом руководстве мы обсудили Как защитить SSH с помощью Fail2ban. В этом руководстве мы подробно рассмотрим, как на самом деле работает Fail2ban, и как вы можете использовать эти знания, чтобы изменить или расширить поведение этого сервиса.
Основы Fail2ban
Цель Fail2ban состоит в мониторинге журналов обычных служб для выявления шаблонов в неудачных попытках аутентификации.
Когда fail2ban настроен на мониторинг журналов службы, он просматривает фильтр, который был настроен специально для этой службы. Фильтр предназначен для выявления неудач аутентификации для этой конкретной службы с помощью сложных регулярных выражений. Регулярные выражения являются общим языком шаблонов, используемым для сопоставления шаблонов. Он определяет эти шаблоны регулярных выражений во внутренней переменной, называемой failregex
.
По умолчанию Fail2ban включает файлы фильтров для общих служб. Когда журнал от любой службы, например, веб-сервера, соответствует failregex
в своем фильтре, выполняется предопределенное действие для этой службы. Действие
– это переменная, которую можно настроить для выполнения множества различных действий, в зависимости от предпочтений администратора.
По умолчанию действие заключается в блокировке атакующего хоста/IP-адреса путем изменения локальных правил брандмауэра. Можно расширить это действие, например, отправив электронное письмо вашему системному администратору.
По умолчанию действие будет предпринято при обнаружении трех неудачных попыток аутентификации за 10 минут, а время блокировки по умолчанию составляет 10 минут. Это настраивается.
При использовании брандмауэра iptables
по умолчанию fail2ban
создает новый набор правил брандмауэра, также называемый цепочкой, при запуске службы. Он добавляет новое правило в цепочку INPUT, которая отправляет весь TCP-трафик, направленный на порт 22, в новую цепочку. В новой цепочке вставляется одно правило, возвращающееся к цепочке INPUT. Цепочка и связанные с ней правила удаляются, если служба Fail2ban останавливается.
Изучение настроек службы Fail2ban
Fail2ban настраивается через несколько файлов, расположенных в иерархии в каталоге /etc/fail2ban/
.
Файл fail2ban.conf
настраивает некоторые операционные параметры, такие как способ регистрации информации демона, а также сокет и файл PID, которые будут использоваться. Основная конфигурация, однако, указывается в файлах, определяющих “тюрьмы” для каждого приложения.
По умолчанию fail2ban поставляется с файлом jail.conf
. Однако это может быть перезаписано при обновлениях, поэтому вы должны скопировать этот файл в файл jail.local
и внести в него изменения.
Если у вас уже есть файл jail.local
, откройте его с помощью nano
или вашего любимого текстового редактора:
Если у вас нет файла jail.local
, или открытый вами файл был пустым, скопируйте файл jail.conf
, а затем откройте новый файл:
Мы рассмотрим здесь доступные опции и увидим, как этот файл взаимодействует с другими конфигурационными файлами в системе.
Секция по умолчанию
Первая часть файла определит значения по умолчанию для политики fail2ban. Эти параметры могут быть переопределены в разделе конфигурации каждой отдельной службы.
После удаления комментариев, весь раздел по умолчанию выглядит примерно так:
[DEFAULT]
ignoreip = 127.0.0.1/8
bantime = 10m
findtime = 10m
maxretry = 3
backend = auto
usedns = warn
destemail = root@localhost
sendername = Fail2Ban
banaction = iptables-multiport
mta = sendmail
protocol = tcp
chain = INPUT
action_ = %(banaction)s[name=%(__name__)s, port="%(port)s", protocol="%(protocol)s", chain="%(chain)s"]
action_mw = %(banaction)s[name=%(__name__)s, port="%(port)s", protocol="%(protocol)s", chain="%(chain)s"]
%(mta)s-whois[name=%(__name__)s, dest="%(destemail)s", protocol="%(protocol)s", chain="%(chain)s", sendername="%(sendername)s"]
action_mwl = %(banaction)s[name=%(__name__)s, port="%(port)s", protocol="%(protocol)s", chain="%(chain)s"]
%(mta)s-whois-lines[name=%(__name__)s, dest="%(destemail)s", logpath=%(logpath)s, chain="%(chain)s", sendername="%(sendername)s"]
action = %(action_)s
Давайте разберем, что означает некоторое из этого:
- ignoreip: Этот параметр определяет IP-адреса, которые должны быть проигнорированы системой блокировки. По умолчанию здесь указано игнорировать трафик, идущий с самого устройства, чтобы не заполнять собственные журналы или не заблокировать себя.
- bantime: Этот параметр устанавливает продолжительность блокировки, в секундах. По умолчанию это 10 минут.
- findtime: Этот параметр устанавливает временное окно, на которое Fail2ban будет обращать внимание при поиске повторных неудачных попыток аутентификации. По умолчанию установлено 10 минут, что означает, что программа будет считать количество неудачных попыток за последние 10 минут.
- maxretry: Это устанавливает количество неудачных попыток, которые будут допущены в течение окна
findtime
, прежде чем будет введена блокировка. - backend: Эта запись указывает, как Fail2ban будет мониторить файлы журналов. Настройка
auto
означает, что fail2ban попробует использоватьpyinotify
, затемgamin
, а затем алгоритм опроса на основе доступного.inotify
– это встроенная функция ядра Linux для отслеживания доступа к файлам, аpyinotify
– это интерфейс Python кinotify
, используемый Fail2ban. - usedns: Это определяет, будет ли использоваться обратное DNS для помощи в реализации запретов. Установка этого значения на «нет» приведет к блокировке самих IP-адресов, а не их доменных имен хостов. Настройка
warn
будет пытаться выполнить поиск имени хоста и блокировать таким образом, но будет регистрировать действие для просмотра. - destemail: Это адрес, на который будет отправляться уведомительное письмо, если настроены оповещения по электронной почте.
- sendername: Это будет использоваться в поле отправителя электронного письма для сгенерированных уведомлений по электронной почте
- banaction: Это устанавливает действие, которое будет использоваться, когда будет достигнут порог. Это фактически путь к файлу, расположенному в
/etc/fail2ban/action.d/
под названиемiptables-multiport.conf
. Этот файл обрабатывает фактическое управление брандмауэромiptables
для блокировки IP-адреса. Мы рассмотрим это позже. - mta: Это агент пересылки почты, который будет использоваться для отправки уведомлений по электронной почте.
- protocol: Это тип трафика, который будет отбрасываться при реализации запрета на IP. Это также тип трафика, который отправляется в новую цепочку iptables.
- chain: Это цепочка, которая будет настроена с правилом перехода для отправки трафика в воронку fail2ban.
Остальные параметры определяют различные действия, которые могут быть указаны. Они передают некоторые из параметров, которые мы определили выше, с помощью подстановки переменных в текстовые строки, подобные этому:
%(var_name)s
Строка выше будет заменена содержимым var_name
. Используя это, мы можем сказать, что переменная action
по умолчанию устанавливается на определение action_
(только запрет, без уведомлений по почте).
Это, в свою очередь, настраивается путем вызова действия iptables-multiport
с набором параметров (имя службы, порт, протокол и цепочка), необходимых для выполнения запрета. __name__
заменяется именем службы, указанным в заголовках разделов ниже.
Специфичные разделы для служб
Под разделом по умолчанию находятся разделы для конкретных служб, которые можно использовать для переопределения настроек по умолчанию. Это следует соглашению о том, что следует изменять только параметры, отличающиеся от нормальных значений (соглашение предпочтительнее конфигурации).
Каждый заголовок раздела указывается следующим образом:
[имя_службы]
Любой раздел, в котором указана строка enabled = true
, будет прочитан и активирован.
В каждом разделе настраиваются параметры, включая файл фильтра, который должен использоваться для анализа журналов (без расширения файла), и местоположение самих файлов журналов.
Имея это в виду, раздел, который определяет действия для службы SSH, выглядит следующим образом:
[SSH]
enabled = true
port = ssh
filter = sshd
logpath = /var/log/auth.log
maxretry = 6
Это позволяет активировать этот раздел и устанавливает порт по умолчанию «ssh» (порт 22). Он сообщает Fail2ban о необходимости просмотра журнала, расположенного по адресу /var/log/auth.log
для этого раздела, и разбора журнала с использованием механизмов фильтрации, определенных в каталоге /etc/fail2ban/filters.d
в файле с именем sshd.conf
.
Все остальные необходимые сведения берутся из параметров, определенных в разделе [DEFAULT]
. Например, действие будет установлено на action_
, которое заблокирует атакующий IP-адрес с помощью действия запрета iptables-multiport
, которое ссылается на файл iptables-multiport.conf
, найденный в /etc/fail2ban/action.d
.
Как видно, действия в разделе [DEFAULT]
должны быть общими и гибкими. Использование подстановки параметров вместе с параметрами, обеспечивающими разумные значения по умолчанию, позволит переопределять определения при необходимости.
Анализ файла фильтра
Чтобы понять, что происходит в нашей конфигурации, нам нужно понять файлы фильтра и действия, которые выполняют основную работу.
Файл фильтра определит строки, которые fail2ban будет искать в журнальных файлах для выявления признаков нарушения. Файл действия реализует все необходимые действия, начиная с построения структуры брандмауэра при запуске службы, заканчивая добавлением и удалением правил и разрушением структуры брандмауэра при остановке службы.
Давайте посмотрим на файл фильтра, который вызвал нашу службу SSH в конфигурации выше:
[INCLUDES]
before = common.conf
[Definition]
_daemon = sshd
failregex = ^%(__prefix_line)s(?:error: PAM: )?[aA]uthentication (?:failure|error) for .* from <HOST>( via \S+)?\s*$
^%(__prefix_line)s(?:error: PAM: )?User not known to the underlying authentication module for .* from <HOST>\s*$
^%(__prefix_line)sFailed \S+ for .*? from <HOST>(?: port \d*)?(?: ssh\d*)?(: (ruser .*|(\S+ ID \S+ \(serial \d+\) CA )?\S+ %(__md5hex)s(, client user ".*", client host ".*")?))?\s*$
^%(__prefix_line)sROOT LOGIN REFUSED.* FROM <HOST>\s*$
^%(__prefix_line)s[iI](?:llegal|nvalid) user .* from <HOST>\s*$
^%(__prefix_line)sUser .+ from <HOST> not allowed because not listed in AllowUsers\s*$
^%(__prefix_line)sUser .+ from <HOST> not allowed because listed in DenyUsers\s*$
^%(__prefix_line)sUser .+ from <HOST> not allowed because not in any group\s*$
^%(__prefix_line)srefused connect from \S+ \(<HOST>\)\s*$
^%(__prefix_line)sUser .+ from <HOST> not allowed because a group is listed in DenyGroups\s*$
^%(__prefix_line)sUser .+ from <HOST> not allowed because none of user's groups are listed in AllowGroups\s*$
ignoreregex =
В заголовке раздела [INCLUDES]
указываются другие файлы фильтра, которые считываются до или после этого файла. В нашем примере файл common.conf
считывается и размещается перед другими строками в этом файле. Это настраивает некоторые параметры, которые мы будем использовать в нашей конфигурации.
Затем у нас есть раздел [Definition]
, который определяет фактические правила для сопоставления наших фильтров. Сначала мы устанавливаем имя демона, который мы мониторим, используя параметр _daemon
.
Затем мы переходим к фактическому определению failregex
, который устанавливает шаблоны, которые будут срабатывать, когда будет найдена соответствующая строка в журнальном файле. Это регулярные выражения, которые соответствуют различным ошибкам и сбоям, которые могут возникать, когда пользователь не аутентифицируется правильно.
Части строки, такие как %(__prefix_line)s
, будут заменены значением параметра, настроенного в файле common.conf
, который мы использовали. Это используется для сопоставления различной ведущей информации, которую операционные системы записывают в журнальные файлы, когда они используют стандартные методы. Например, некоторые строки из /var/log/auth.log
могут выглядеть примерно так:
May 6 18:18:52 localhost sshd[3534]: pam_unix(sshd:auth): authentication failure; logname= uid=0 euid=0 tty=ssh ruser= rhost=101.79.130.213
May 6 18:18:54 localhost sshd[3534]: Failed password for invalid user phil from 101.79.130.213 port 38354 ssh2
May 6 18:18:54 localhost sshd[3534]: Received disconnect from 101.79.130.213: 11: Bye Bye [preauth]
Выделенная часть представляет собой стандартный шаблон, который вставляет операционная система для предоставления дополнительного контекста. После этого существует несколько различных способов, которыми служба брандмауэра iptables записывает попытки нарушения в журнал.
Мы видим два отдельных сбоя в первых двух строках выше (ошибка аутентификации PAM и ошибка пароля). Регулярные выражения, определенные в фильтре, разработаны для сопоставления любых возможных строк сбоя. Вам не нужно будет изменять какие-либо из этих строк, но вы должны быть в курсе необходимости перехвата всех записей в журнале, сигнализирующих о ошибке несанкционированного использования для приложения, которое вы пытаетесь защитить, если вам когда-нибудь придется создать файл фильтра самостоятельно.
Внизу вы можете видеть параметр ignoreregex
, который в настоящее время пуст. Его можно использовать, чтобы исключить более конкретные шаблоны, которые обычно совпадают с условием сбоя, в случае если вы хотите отменить триггер сбоя для fail2ban для определенных сценариев. Мы не будем этого настраивать.
Сохраните и закройте файл, когда закончите его изучение.
Изучение файла действия
Теперь давайте взглянем на файл действия. Этот файл отвечает за настройку брандмауэра с такой структурой, которая позволяет вносить изменения для блокировки вредоносных хостов, а также добавлять и удалять этих хостов по мере необходимости.
Действие, которое вызывает нашу службу SSH, называется iptables-multiport
. Откройте соответствующий файл сейчас:
С удаленными комментариями этот файл выглядит примерно так:
[INCLUDES]
before = iptables-blocktype.conf
[Definition]
actionstart = iptables -N fail2ban-<name>
iptables -A fail2ban-<name> -j RETURN
iptables -I <chain> -p <protocol> -m multiport --dports <port> -j fail2ban-<name>
actionstop = iptables -D <chain> -p <protocol> -m multiport --dports <port> -j fail2ban-<name>
actioncheck = iptables -n -L <chain> | grep -a 'fail2ban-<name>[ \t]'
actionban = iptables -I fail2ban-<name> 1 -s <ip> -j <blocktype>
actionunban = iptables -D fail2ban-<name> -s <ip> -j <blocktype>
[Init]
name = default
port = ssh
protocol = tcp
chain = INPUT
Файл начинается с подключения другого файла действий под названием iptables-blocktype.conf
, который определяет параметр blocktype
, который настраивает ограничение, установленное при блокировке клиента. По умолчанию blocktype
установлен на отклонение пакетов и ответ на запросы пингов от заблокированных клиентов сообщением о том, что порт недоступен. Мы будем использовать это в наших правилах блокировки ниже.
Затем мы переходим к определениям самих правил. Действие actionstart
настраивает брандмауэр iptables при запуске службы fail2ban. Оно создает новую цепочку, добавляет правило в эту цепочку для возврата к вызывающей цепочке, а затем вставляет правило в начало цепочки INPUT, которое передает трафик, соответствующий правильному протоколу и портам назначения, в новую цепочку.
Оно делает это, используя значения, которые мы передали с помощью action
, которое мы определили в нашем файле jail.local
. name
берется из заголовка раздела для каждой службы. chain
, protocol
и port
берутся из самой строки action
в этом файле.
Здесь все параметры, установленные в другом файле, ссылается, включая имя параметра в угловых скобках:
<param_name>
Когда мы переходим к определению сопутствующего действия actionstop
, мы видим, что команды брандмауэра реализуют отмену команд actionstart
. Когда служба Fail2ban останавливается, она чисто удаляет любые правила брандмауэра, которые она добавила.
Другое действие, называемое actioncheck
, проверяет, была ли создана соответствующая цепочка до попытки добавления правил блокировки.
Затем мы переходим к фактическому правилу блокировки, называемому actionban
. Это правило работает путем добавления нового правила в нашу созданную цепочку. Правило сопоставляет исходный IP-адрес нарушителя – этот параметр считывается из журналов авторизации, когда достигается предел maxretry
. Оно вводит блок, определенный параметром blocktype
, который мы указали в разделе [INCLUDE]
в начале файла.
Правило actionunban
удаляет это правило. Это происходит автоматически с помощью fail2ban, когда истекает время блокировки.
Наконец, мы переходим к разделу [Init]
. Здесь просто указываются некоторые значения по умолчанию, если файл действия вызывается без передачи всех соответствующих значений.
Как служба Fail2ban обрабатывает файлы конфигурации для применения блокировок
Теперь, когда мы рассмотрели детали, давайте рассмотрим процесс, который происходит при запуске fail2ban.
Загрузка начальных файлов конфигурации
Сначала основной файл fail2ban.conf
читается для определения условий, в которых должен работать основной процесс. При необходимости создаются сокеты, файлы pid и журналы, и начинается их использование.
Затем fail2ban читает файл jail.conf
для получения деталей конфигурации. Затем он читает, в алфавитном порядке, любые файлы, найденные в каталоге jail.d
, оканчивающиеся на .conf
. Он добавляет настройки, найденные в этих файлах, в свою внутреннюю конфигурацию, предпочитая новые значения значениям, описанным в файле jail.conf
.
Затем он ищет файл jail.local
и повторяет этот процесс, адаптируя новые значения. Наконец, он снова ищет в каталоге jail.d
, читая файлы, оканчивающиеся на .local
, в алфавитном порядке.
В нашем случае у нас есть только файл jail.conf
и файл jail.local
. В нашем файле jail.local
нам нужно только определить значения, отличающиеся от значений в файле jail.conf
. Теперь у процесса fail2ban есть набор загруженных в память директив, представляющих собой комбинацию всех найденных файлов.
Он анализирует каждый раздел и ищет директиву enabled = true
. Если находит ее, то использует определенные параметры в этом разделе для создания политики и определения необходимых действий. Любые параметры, которые не найдены в разделе службы, используют параметры, определенные в разделе [DEFAULT]
.
Анализ Файлов Действий для Определения Начальных Действий
Fail2ban ищет директиву action
, чтобы определить, какой скрипт действия вызывать для реализации политики блокировки/разблокировки. Если он не найден, он использует действие по умолчанию, определенное выше.
Директива действия состоит из имени файла(ов) действия, которые будут прочитаны, а также словаря ключ-значение, который передает параметры, необходимые этим файлам. Значения этих параметров часто принимают форму подстановок параметров, обращаясь к настройкам, настроенным в разделе службы. Ключ “name” обычно получает значение специальной переменной __name__
, которая будет установлена в значение заголовка раздела.
Затем Fail2ban использует эту информацию, чтобы найти связанные файлы в каталоге action.d
. Сначала он ищет связанный файл действия с расширением .conf
, а затем дополняет найденную информацию любыми настройками, содержащимися в сопровождающем файле .local
, также найденном в каталоге action.d
.
Он анализирует эти файлы, чтобы определить действия, которые ему нужно выполнить. Он считывает значение actionstart
, чтобы увидеть действия, которые он должен выполнить для настройки среды. Это часто включает создание структуры брандмауэра для обработки правил запрета в будущем.
Действия, определенные в этом файле, используют переданные ему параметры из директивы action
. Он будет использовать эти значения для динамического создания соответствующих правил. Если определенная переменная не была установлена, он может посмотреть на установленные значения по умолчанию в файле действия, чтобы заполнить пробелы.
Анализ файлов фильтрации для определения правил фильтрации
Параметры для службы в файлах jail.*
также включают местоположение файла журнала, а также механизм опроса, который должен использоваться для проверки файла (это определяется параметром backend
). Он также включает фильтр, который должен использоваться для определения, представляет ли строка в журнале сбой.
Fail2ban ищет в каталоге filter.d
соответствующий файл фильтра, который заканчивается на .conf
. Он считывает этот файл, чтобы определить шаблоны, которые могут использоваться для сопоставления нарушающих строк. Затем он ищет соответствующий файл фильтра, заканчивающийся на .local
, чтобы увидеть, были ли перезаписаны какие-либо из параметров по умолчанию.
Он использует регулярные выражения, определенные в этих файлах, когда считывает файл журнала службы. Он проверяет каждую строку failregex
, определенную в файлах filter.d
, по отношению к каждой новой строке, записанной в файл журнала службы.
Если регулярное выражение находит соответствие, он проверяет строку на соответствие регулярным выражениям, определенным в ignoreregex
. Если это также соответствует, fail2ban игнорирует это. Если строка соответствует выражению в failregex
, но не соответствует выражению в ignoreregex
, внутренний счетчик увеличивается для клиента, вызвавшего строку, и создается связанный событием временной штамп.
Как только истекает заданный параметром findtime
интервал времени в файлах jail.*
(определяемый временным штампом события), внутренний счетчик снова уменьшается, и событие больше не рассматривается как соответствующее политике блокировки.
Если в течение времени ведения журнала зарегистрировано дополнительное количество неудачных попыток аутентификации, каждая попытка увеличивает счетчик. Если счетчик достигает установленного значения параметром maxretry
в настроенном интервале времени, fail2ban вводит блокировку, вызывая действие actioncheck
для службы, как определено в файлах action.d/
для службы. Это делается для определения того, настроено ли необходимое действие actionstart
. Затем вызывается действие actionban
, чтобы заблокировать нарушителя. Здесь же устанавливается временная метка для этого события.
Когда истекает указанное параметром bantime
время, fail2ban разблокирует клиента, вызывая действие actionunban
.
Заключение
На данный момент у вас есть достаточно глубокое понимание того, как работает fail2ban. Когда вы отклоняетесь от стандартной конфигурации, полезно знать, как работает fail2ban, чтобы можно было предсказуемо влиять на его поведение.
Чтобы узнать, как защитить другие службы с помощью fail2ban, вы можете прочитать Как защитить сервер Nginx с помощью Fail2Ban на Ubuntu 22.04.