Fail2ban следит за лог-файлами, и когда один и тот же адрес слишком много раз подряд не проходит аутентификацию, добавляет правило firewall, которое на время отбрасывает его пакеты. Вот и весь продукт. Двадцать минут настройки убирают большую часть шума из журнала аутентификации и заметную долю нагрузки с небольшого сервера, и это одна из четырёх-пяти вещей, которые стоит сделать в первый же день на новом VDS.
Его также регулярно переоценивают. Fail2ban не остановит распределённую атаку, где каждая попытка идёт с нового адреса, не остановит объёмный поток, а если вы уже отключили вход по паролю в SSH, то подбор, который он блокирует, всё равно никогда бы не удался. Ставьте его потому, что он сохраняет журналы читаемыми, а процессор свободным, а не потому, что он делает машину безопасной. Безопасным SSH делает отключение паролей - но это тема другой статьи: SSH-ключи и укрепление защиты.
Как он на самом деле работает#
Три части, и понимание этого разделения облегчает диагностику любой проблемы.
Фильтр - набор регулярных выражений, распознающих неудачу в конкретном формате лога. Они лежат в /etc/fail2ban/filter.d/, по файлу на службу, и дистрибутив поставляет их десятками: sshd.conf, nginx-http-auth.conf, postfix.conf и так далее.
Jail связывает фильтр с источником лога и набором чисел: сколько неудач, за какое окно и как долго длится бан. Jail-ы определены в /etc/fail2ban/jail.conf и, что важно, переопределяются вами в другом месте.
Действие - то, что происходит, когда jail срабатывает. По умолчанию оно пишет правило iptables или nftables, отклоняющее адрес на портах, которые охватывает jail. Действия лежат в /etc/fail2ban/action.d/, и есть альтернативы, вызывающие ufw, отправляющие почту или обращающиеся к API.
Из этой схемы вытекают два следствия. Fail2ban реагирует постфактум: он читает строку, которая уже записана, так что неудачные попытки всегда происходят первыми, а бан вступает в силу секундой-двумя позже. И бан - всегда только правило firewall, поэтому всё, что обходит ваш firewall, обходит и fail2ban. У этого пункта есть очень распространённая форма, о ней ближе к концу статьи.
Установка и единственный файл, который стоит править#
$ apt update && apt install fail2ban$ systemctl enable --now fail2ban$ fail2ban-client statusНе правьте jail.conf. Это файл из пакета, он заменяется при каждом обновлении, и ваши изменения тихо пропадают. Вместо этого создайте /etc/fail2ban/jail.local, который читается позже и имеет приоритет. Всё, что вы не указали в jail.local, берётся из значений по умолчанию, так что в файле должно быть только то, что вы меняете.
[DEFAULT]bantime = 1hfindtime = 10mmaxretry = 5ignoreip = 127.0.0.1/8 ::1 203.0.113.42# Ban for longer each time the same address comes back.bantime.increment = truebantime.maxtime = 5w[sshd]enabled = truemode = aggressivemaxretry = 4bantime = 2hЗначения по умолчанию: bantime = 10m, findtime = 10m и maxretry = 5. Десять минут - срок, почти декоративный против терпеливого сканера, поэтому первое, что большинство людей меняют, - это bantime.
bantime.increment - настройка, о которой стоит знать и которую пропускают чаще всего. Когда она включена, адрес, снова получивший бан после истечения первого, банится вдвое дольше, затем вчетверо, вплоть до bantime.maxtime. Одиночный любопытный посетитель выбывает на час; тот, кто возвращается целую неделю, в итоге выбывает на пять недель. Это ничего не стоит и делает почти всю полезную работу.
ignoreip - ваш ремень безопасности. Впишите туда домашний или офисный адрес, если он у вас статический. Если нет, пропустите и лучше прочитайте раздел о разбане ниже.
Jail sshd и лог, который он не может найти#
Jail sshd включён по умолчанию в большинстве дистрибутивов и является единственным важным на свежей машине. Современная неприятность здесь не в конфигурации, а в источнике лога.
Традиционно fail2ban читает /var/log/auth.log, который пишет rsyslog. Свежие минимальные образы Debian и Ubuntu rsyslog вообще не устанавливают, и всё идёт в журнал systemd. В таких системах jail sshd не запускается, а ошибка в journalctl -u fail2ban говорит об отсутствующем пути к логу, а не о чём-то, что вы сделали. Исправление - одна строка:
[sshd]enabled = truebackend = systemdПроверьте, в какой вы ситуации, прежде чем что-то предполагать: ls -l /var/log/auth.log. Если файл существует и растёт, бэкенд file по умолчанию подходит. Если его нет, укажите backend = systemd, и jail будет читать журнал напрямую.
Параметр mode у фильтра sshd стоит задать. normal ловит простые неудачи аутентификации. aggressive добавляет строки о закрытии соединения до аутентификации и шум от некорректных пакетов, который создают сканеры, - это ловит ботов, которые зондируют, ни разу не отправляя пароль. На сервере с уже отключённой аутентификацией по паролю именно aggressive - режим, который вообще кого-то банит, потому что бот, перебирающий пароли у демона только для ключей, никогда не порождает классическую строку неудачи.
Время бана, время поиска и что означают числа#
Поведение определяют три числа, и взаимодействуют они так, что легко понять наоборот.
| Настройка | По умолчанию | Что означает |
|---|---|---|
maxretry | 5 | Число неудач до бана |
findtime | 10m | Окно, в которое эти неудачи должны уложиться |
bantime | 10m | Как долго действует правило firewall |
bantime.increment | выкл. | Умножать бан при каждом повторном нарушении |
bantime.maxtime | нет | Потолок для нарастающего бана |
findtime - скользящее окно, а не корзина, сбрасываемая по часам. Четыре неудачи, растянутые на одиннадцать минут при findtime в десять минут, не вызывают ничего, потому что ни в какой момент четырёх внутри десятиминутного отрезка не набралось. Медленный сканер, пробующий один пароль раз в три минуты, невидим для значений по умолчанию, - это реальный приём и одна из причин расширять findtime, а не снижать maxretry.
Разумные начальные числа для сервера, на который заходите только вы: maxretry = 4, findtime = 30m, bantime = 1h при включённом bantime.increment. Если машиной пользуются и другие, будьте мягче к первому нарушению и позвольте нарастанию наказывать упорство, потому что единственный человек, который гарантированно попадётся в строгий jail, - коллега со старым ключом, всё ещё лежащим в его агенте.
Вместе с fail2ban поставляется jail второго порядка, который стоит включить, когда остальное заработает, и который почти никто не включает:
[recidive]enabled = truebantime = 1wfindtime = 1dmaxretry = 5Jail recidive читает собственный лог fail2ban и банит адреса, которые получили бан от любого другого jail пять раз за сутки. Он ловит всё, что возвращается после истечения бана, и охватывает хосты, которые медленно переходят между вашими службами. Ему нужен существующий /var/log/fail2ban.log; если ваша установка пишет в журнал, укажите backend = systemd и для этого jail.
Jail-ы для веб-сервера#
Если на VDS работает nginx, три поставляемых jail-а оправдывают себя. Добавьте их в jail.local, подставив пути к логам под свою конфигурацию.
[nginx-http-auth]enabled = truelogpath = /var/log/nginx/error.log[nginx-botsearch]enabled = truelogpath = /var/log/nginx/access.log[nginx-limit-req]enabled = truelogpath = /var/log/nginx/error.logmaxretry = 10findtime = 1mnginx-http-auth ловит подбор пароля к HTTP basic-аутентификации. nginx-botsearch находит запросы к путям, которые сканеры спрашивают всегда, - на сайте WordPress это постоянная капель весь день. nginx-limit-req интереснее всех: он ничего не делает, пока вы не настроили собственные зоны limit_req в nginx, а потом переводит клиента, который продолжает упираться в ограничение частоты, из «притормаживаемого» в «забаненного на firewall», что обслуживать гораздо дешевле.
Это общий принцип. Fail2ban - тупой инструмент в конце цепочки. Ограничивать частоту в первую очередь должно приложение, потому что оно отличает настоящего пользователя от бота способами, недоступными строке лога, а правила firewall заслуживают только клиенты, проигнорировавшие ограничение. О том, где какой уровень уместен, рассказывает ограничение частоты и злоупотребления.
Если для firewall вы используете ufw, направьте fail2ban на него, чтобы два инструмента не писали конкурирующие правила:
[DEFAULT]banaction = ufwИначе fail2ban вставляет собственные цепочки перед цепочками ufw - это работает, но оставляет вам два места, куда смотреть, когда адрес неожиданно заблокирован. Остальная история про firewall - в руководстве по firewall ufw.
Проверка, что всё работает#
Непроверенная установка fail2ban - это предмет для успокоения. Четыре проверки по порядку, и каждая отвечает на свой вопрос.
$ fail2ban-client status # which jails are running$ fail2ban-client status sshd # counters and current bans$ fail2ban-regex /var/log/auth.log /etc/fail2ban/filter.d/sshd.conf$ iptables -S | grep f2b # the rules that exist right now$ nft list ruleset | grep -i f2b # on nftables systemsfail2ban-client status sshd выводит текущие неудачи, всего неудач, текущие баны, всего банов и список забаненных адресов. Если общее число неудач растёт, а общее число банов остаётся нулевым, фильтр срабатывает, а числа слишком мягкие. Если общее число неудач застряло на нуле, хотя journalctl -u ssh явно показывает попытки, фильтр вообще не совпадает с логом, и это почти всегда неверный бэкенд или неверный logpath.
fail2ban-regex - инструмент, который ставит точку. Направьте его на настоящий лог и файл фильтра, и он скажет, сколько строк совпало, сколько было проигнорировано и сколько он не смог разобрать. Добавьте --print-all-missed, чтобы увидеть пропущенные строки, - так выясняется, что в вашем формате лога есть метка времени, которую он не узнаёт.
Чтобы проверить всё от начала до конца, намеренно провалите вход со второй машины или с телефона в режиме модема по мобильным данным - не с того адреса, с которого вы сейчас подключены. Введите неверный пароль пять раз, затем проверьте вывод статуса из своей существующей сессии. Затем разбаньте себя.
$ fail2ban-client set sshd unbanip 203.0.113.9$ fail2ban-client unban 203.0.113.9 # every jail at once$ fail2ban-client unban --all # clear everythingЧего fail2ban не сделает за вас#
Неприятные стороны нужно называть вслух, потому что многие руководства этого не делают.
- Распределённые попытки проходят. Ботнет с десятью тысячами адресов, делающий по три попытки с каждого, ни на одном отдельном адресе не достигает
maxretry. Fail2ban создан для одиночного настойчивого сканера, а это большая часть трафика, но защитой от терпеливого атакующего он не является. - Он ничего не делает с объёмными потоками. Пакеты всё равно приходят, всё равно занимают ваш аплинк и всё равно требуют работы ядра. Фильтрация должна происходить выше вашей машины, а что тут можно и нельзя сделать, описано в DDoS-атаках на игровые серверы простыми словами.
- Docker публикует порты мимо него. Это главное. Контейнер, запущенный с
-p 5432:5432, достигается через цепочкиDOCKER-USERиFORWARD, а правила fail2ban по умолчанию живут вINPUT, так что бан ни на что внутри контейнера не влияет. Либо привяжите контейнер к localhost с-p 127.0.0.1:5432:5432, либо скажите действию писать в нужную цепочку черезbanaction = iptables-allports[chain=DOCKER-USER]. Остальное об этой оговорке - в Docker на VDS. - Он не спасает слабый пароль. Пяти попыток хватит, если пароль -
admin123. Fail2ban повышает цену подбора, но не настолько, чтобы это имело значение против действительно плохого секрета. - Он не заменяет отключение паролей. С
PasswordAuthentication noи доступом только по ключам подбор, который он блокирует, и так не удавался. Это всё равно стоит делать ради шума в логах и процессора, но будьте честны насчёт порядка действий.
Если что-то уже пошло не так, а не было предотвращено, fail2ban - не тот инструмент, который вам нужен, а вот что делать, если ваш сервер взломали - тот.
Повседневная работа#
После любого изменения jail.local делайте reload, а не restart, чтобы существующие баны сохранились:
$ fail2ban-client reload # all jails$ fail2ban-client reload sshd # one jail$ fail2ban-client get sshd bantime$ fail2ban-client set sshd banip 198.51.100.7$ journalctl -u fail2ban -n 50 --no-pagerБаны сохраняются в небольшой базе SQLite по адресу /var/lib/fail2ban/fail2ban.sqlite3, так что они переживают перезапуск службы и перезагрузку машины. Там же хранится история нарастания, и поэтому у постоянного нарушителя растущий бан сохраняется и после перезагрузок.
Раз в месяц заглядывайте в fail2ban-client status sshd и на размер журнала аутентификации. Резкое изменение в любую сторону - это информация: лог, который стих, обычно означает, что остановился rsyslog или сломался jail, а не что интернет стал вежливым. Более широкая привычка решать, какие логи хранить и как долго, изложена в каких логах стоит хранить, а команды для их быстрого чтения - в командах Linux для администраторов серверов.
На управляемом тарифе RE:NODE fail2ban не устанавливают, потому что нет оболочки хоста, куда его ставить. Эквивалентная защита встроена: панель ставит captcha и ограничения частоты на вход, хранит хэши паролей с bcrypt, предлагает двухфакторную аутентификацию с кодами из приложения и одноразовыми резервными кодами, ведёт список сессий, из которых можно выйти, и позволяет ограничивать ключи API по адресу. Внешняя фильтрация отсекает очевидные объёмные потоки до того, как они дойдут до ноды. На VDS всё это вам предстоит собрать самим, и fail2ban - один из кирпичей.
FAQ#
Замедляет ли fail2ban сервер?
Заметно нет. Это процесс Python, читающий строки логов, обычно с несколькими десятками мегабайт памяти и почти без нагрузки на процессор. Сами баны - правила firewall, которые ядро вычисляет за микросекунды. Заметен он бывает только у jail с огромным списком банов и очень коротким findtime на загруженном веб-логе.
Почему мой jail sshd сообщает ноль неудач?
Почти всегда причина в источнике лога. Проверьте, существует ли /var/log/auth.log; в образах без rsyslog его нет, и в jail нужен backend = systemd. Подтвердите через fail2ban-regex на настоящем логе, он точно скажет, сколько строк совпало.
Забанит ли он меня, если я ошибусь при вводе пароля?
Да, и так и должно быть. Поэтому существует ignoreip для статического адреса, поэтому вы держите вторую сессию открытой при любых изменениях, и поэтому стоит проверить консольный доступ у провайдера до того, как он понадобится. Используйте ключи, и вопрос перестанет возникать.
Достаточно ли одного fail2ban?
Нет. Это один слой поверх SSH только по ключам, firewall с запретом по умолчанию, свежих пакетов и непривилегированных пользователей служб. Он убирает шум и останавливает ленивые атаки. Все серьёзные меры находятся в другом месте, и первый час на новом VDS перечисляет их по порядку.
Может ли он защитить порт игрового сервера?
Только если игра пишет разбираемый лог неудачных попыток, чего большинство не делает, и только от злоупотреблений на уровне соединений, а не от потоков. Кроме того, бан по адресу плохо подходит для игроков, которые делят адреса и меняют их. Для игроков используйте собственный бан-лист игры и RCON, а fail2ban оставьте для административных интерфейсов.
Как увидеть все адреса, забаненные сейчас?
fail2ban-client status <jail> выводит список для одного jail. В недавних версиях есть и fail2ban-client banned, который печатает списки всех jail сразу. Чтобы увидеть, что на самом деле применяет ядро, - iptables -S | grep f2b или nft list ruleset.




Комментарии
Полностью анонимно: без аккаунта, без почты, без cookie. Мы храним имя, которое вы ввели, текст и время - больше ничего. Количество ссылок ограничено, разметка не отображается.