CrowdSec: коллективная защита сервера
Всё началось с того, что я устал смотреть на логи fail2ban. Нет, он работал — банил IP, чистил таблицы, делал своё дело. Но каждый день одно и то же: одни и те же сканеры, одни и те же попытки подбора паролей. Я банил их на своём сервере, а через час они ломились к соседу. А соседский сервер, может, даже не знал про этих гостей. И так по кругу.
Тогда я наткнулся на CrowdSec. Идея простая: ты видишь атаку — ты делишься информацией с сообществом. Кто-то увидел — все узнали. Коллективный иммунитет, мать его. Не нужно ждать, пока злоумышленник постучится лично к тебе — его уже заблокировали за атаки на десять других серверов до того, как он дошёл до твоего.
Как это работает на практике
CrowdSec состоит из двух частей: сам движок, который анализирует логи, и «баунсер» — шлюз, который применяет блокировки. Движок читает логи nginx, Apache, SSH, каких-то специфических сервисов — находит подозрительное поведение, вычисляет IP и решает: банить или нет. А баунсер берёт решение движка и превращает его в правило для nftables, iptables или nginx.
Ставится всё просто. У них есть репозиторий, добавляешь — и порядок:
curl -s https://packagecloud.io/install/repositories/crowdsec/crowdsec/script.deb.sh | sudo bash
sudo apt install crowdsec
sudo apt install crowdsec-firewall-bouncer-nftables
После установки он сам подхватил мои nginx-логи и начал анализировать. Первое, что я заметил — в консоли появились оповещения о детектах. Какие-то сканеры WordPress, попытки брутфорса SSH, перебор путей на сайте. CrowdSec собирает логи, находит подозрительную активность и через bouncer банит IP в nftables.
Я проверил — работает. Сделал пару тестовых запросов к несуществующим путям, подождал пару минут — и получил бан. Надёжно.
Как я настраивал под себя
Основной конфиг лежит в /etc/crowdsec/config.yaml. Я добавил свои пароли для API, включил сбор метрик для Prometheus и настроил уведомления на ntfy (через HTTP endpoint).
Очень полезная вещь — cscli. Это консольный клиент для управления CrowdSec. Через него можно добавлять парсеры для новых форматов логов, управлять бан-листами, смотреть статистику:
sudo cscli decisions list
sudo cscli metrics
sudo cscli collections install crowdsecurity/nginx
Я сразу накатил коллекции для nginx, Apache, WordPress и SSH. Каждая коллекция — это набор парсеров и сценариев для конкретного сервиса. Ставится одной командой и начинает работать сразу. Никаких дополнительных настроек не потребовалось — всё подхватилось автоматом.
Ещё прикрутил баунсер для nginx отдельно — crowdsec-nginx-bouncer. Он работает как lua-скрипт внутри nginx и режет запросы ещё до того, как они долетят до PHP. Это снимает нагрузку с Apache, потому что блочатся даже не открывая соединения с бэкендом:
sudo apt install crowdsec-nginx-bouncer
sudo cscli bouncers add nginx-bouncer
Разница ощутимая. Раньше fail2ban банил на уровне iptables, но nginx всё равно принимал соединение, логировал его и только потом отдавал 403. С nginx-bouncer запрос отбрасывается на уровне lua-скрипта до всякой обработки. Меньше мусора в логах, меньше нагрузки на процессор.
Сравнение с Fail2ban
Fail2ban — это классика. Он работает по принципу «увидел подозрительное в логе — заблокировал». Просто, надёжно, предсказуемо. Но у него есть фатальный недостаток: он видит только то, что происходит на твоём сервере. Если какой-то хакер атакует тысячу серверов, fail2ban на каждом из них будет независимо учиться на своих ошибках.
CrowdSec же использует центральное API. Когда он находит атаку, он проверяет: «Ребята, этот IP уже кого-то доставал?». И если да — блокировка приходит мгновенно, без ожидания, пока злоумышленник начнёт долбиться к тебе. Это называется «коллективная защита». И это реально работает.
Я не стал убирать fail2ban полностью. Оставил для совсем тупых брутфорсов — он быстрее реагирует на примитивные атаки. А CrowdSec поставил как основной слой защиты для сложных скоординированных атак. Связка получилась удачной: fail2ban банит лобовые атаки, CrowdSec — распределённые и хитрые.
Подводные камни
Было пару проблем. Первая — если формат логов нестандартный, придётся писать свой парсер. У меня nginx логи в json, я подкрутил acquis.yaml, но пришлось повозиться с полями. В документации всё описано, но без практики с первого раза не срастается.
Вторая — баунсер на nftables пару раз отваливался после перезагрузки сервера. Решил добавлением Restart=always в systemd-сервис, но это костыль. В новых версиях обещали исправить.
Третья — нужно следить за обновлениями коллекций. Угрозы меняются, сигнатуры устаревают. Я добавил в cron еженедельное обновление:
sudo cscli hub update
sudo cscli collections upgrade crowdsecurity/linux
И ещё важный момент: CrowdSec потребляет ресурсы. На слабом сервере (меньше 1GB RAM) он может быть заметен — особенно если логов много. У меня на сервере 8GB, ему хватает, но на мелких VPS стоит ставить только с осторожностью и ограничением по памяти.
Мониторинг и алерты
У CrowdSec есть встроенные метрики для Prometheus. Я вывел их в Grafana — вижу сколько атак заблокировано, какие типы атак преобладают, какие страны-источники самые агрессивные. Спойлер: Китай, Россия и США стабильно в топе, но это не показатель — просто много запросов идёт оттуда.
Алерты настроил через HTTP endpoint на ntfy. Критичные события (например, атака на WordPress admin) приходят сразу на телефон. Информационные — например, просто бан подозрительного IP — только в дашборд, чтобы не спамить.
Результат
Сейчас CrowdSec работает уже несколько месяцев на всех моих серверах. Я перестал проверять логи каждое утро. Если что-то серьёзное — он сам скажет. А так — работает в фоне, учится на атаках других серверов и делает сеть чище. Реально классная штука.
Из коробки у него куча коллекций. Я использую базовый набор: crowdsecurity/linux, crowdsecurity/nginx, crowdsecurity/wordpress, crowdsecurity/sshd. Всё работает из коробки. Не нужно быть экспертом по безопасности, чтобы защитить сервер — достаточно один раз настроить и забыть.
В общем, если ты ещё не поставил CrowdSec — попробуй. Это не панацея, сигнатуры нужно обновлять, логи настраивать. Но как дополнительный слой защиты — отрабатывает на все сто. Лично я теперь запускаю его на каждом новом сервере в первую очередь, даже до fail2ban. Потому что коллективный иммунитет — это единственный способ бороться с атаками, когда ты не один в интернете.
Честно признаюсь, первое впечатление от CrowdSec было «ещё один инструмент, который надо разбирать полдня». Но нет. После установки я открыл cscli и офигел: всё уже настроено. Движок сам нашёл мои логи, подтянул базовые сценарии и начал работать. За первые сутки он заблокировал несколько сотен IP, и большинство из них — даже не достучавшись до моего SSH. Это было то самое «момент Икс», когда я понял: коллекивный иммунитет — не маркетинг, а рабочая механика.
Какие сценарии я реально использую. Если глянуть в каталог коллекций, глаза разбегаются. Но мне хватило четырёх: linux (базовые события системы), nginx (парсинг access-логов), sshd (брутфорс по SSH) и wordpress (перебор wp-login и атаки на плагины). Каждая коллекция ставится как пакет, и сразу подтягиваются парсеры и сценарии. Проверить, что всё поднялось, можно так:
sudo cscli scenarios list
sudo cscli parsers list
Если увидел свои коллекции в списке со статусом enabled — всё ок. Дальше я рекомендую посмотреть на решения вручную:
sudo cscli decisions list
Там видно, какие IP забанены и почему. Это полезно, чтобы понять, не перегибает ли CrowdSec палку. Пару раз я замечал, что банил свой же домашний IP — когда сидел с телефоном через домашний Wi-Fi, а на сервере стояло правило с низким порогом срабатывания. Тогда я добавил свой IP в whitelist:
sudo cscli decisions delete —ip 192.168.1.100
sudo cscli whitelists add —ip 192.168.1.100
Whitelist — вообще важная штука. Если у тебя есть статический IP дома — обязательно добавь его сразу, чтобы не отловить ложный бан в самый неподходящий момент.
Как я настроил алерты в ntfy. Тут я проявил смекалку. У CrowdSec есть встроенный HTTP-выход для уведомлений, а у меня уже стоял ntfy для других задач. Подключил за пару минут: в конфиге уведомлений указал endpoint ntfy-сервера и тему, куда слать алерты. Теперь критичные события падают на телефон мгновенно. А чтобы не спамить, я отфильтровал: серьёзные инциденты (перебор wp-login, атака на админку) — в телефон, обычные баны — только в метрики.
Что делать, если что-то не так. У CrowdSec есть команда cscli alert list — она показывает активные алерты с деталями. Если какое-то решение было ложным — удаляешь его и добавляешь IP в whitelist. Если парсер не разобрал логи — смотришь /var/log/crowdsec/ и подкручиваешь acquis.yaml. Однажды у меня nginx писал логи в нестандартный формат, и CrowdSec молчал. Помогла команда cscli inspect — она показывает, что именно прочитал движок и где споткнулся. Двадцать минут возни — и всё заработало.
Небольшая ремарка про приватность. Многие боятся, что CrowdSec отправляет куда-то данные. Да, движок отправляет на центральное API только обезличенную информацию: IP атакующего, тип атаки, время. Никаких твоих логов и содержимого запросов он не передаёт. Это ключевая деталь, из-за которой я и решился на него. Всё остальное остаётся локально.
Что я в итоге советую. Начинать с базовой установки и коллекций для nginx и sshd — этого достаточно, чтобы прикрыть 80% атак. Потом, если хочется, добавить wordpress и баунсер для nginx. Обновлять коллекции раз в неделю через cron — и не забыть внести свой домашний IP в whitelist. CrowdSec не заменяет здравый смысл: он не починит криво настроенный сервер и не защитит от атак на уровне приложений. Но от распределённых брутфорсов и сканеров — прикрывает отлично. И главное — делает это за тебя, пока ты пьёшь чай и пишешь статьи в блог.
Если захочешь посмотреть на цифры — у меня в Grafana висит дашборд с блокировками за последние месяцы. Там видно, как CrowdSec отрезает атаки волнами: прилетает пачка запросов из одной страны — и через минуту уже тишина. Это наглядно объясняет, почему я больше не просыпаюсь по ночам проверять логи.