CrowdSec на Linux в 2026: коллективная защита, AppSec WAF и bouncers для nftables и nginx
Пошаговая настройка CrowdSec 1.6 на Linux: агент, LAPI, bouncer для nftables, AppSec WAF перед nginx, защита SSH от bruteforce и подключение к коллективному Blocklist API с примерами команд и типичными ошибками.
CrowdSec, это open-source система обнаружения и предотвращения вторжений (IDS/IPS) для Linux, которая парсит логи локальных сервисов, детектирует злоумышленников по декларативным сценариям и делится IP-адресами атакующих через коллективный Blocklist API. В 2026 году актуальна ветка 1.6.x с встроенным AppSec Component (WAF-модуль на основе Coraza), keyless-регистрацией машин через console.crowdsec.net и bouncer'ами для nftables, nginx, Cloudflare, Traefik и HAProxy. В этой статье я разбираю продакшен-развёртывание с двумя реальными кейсами: защита nginx от credential stuffing и SSH от bruteforce на публичном сервере.
CrowdSec 1.6+ разделяет detection engine (агент) и action engine (bouncers), поэтому один LAPI обслуживает десятки узлов кластера без переписывания правил.
Blocklist API возвращает около 2 миллионов активных вредоносных IP из коллективного пула, на порядок больше, чем локальный fail2ban увидит на одном сервере.
AppSec Component играет роль лёгкого WAF перед nginx или Traefik: блокирует OWASP Top 10 по CRS-совместимым правилам ещё до обращения к приложению.
Связка cs-firewall-bouncer + nftables set даёт O(1) блокировку с миллионами IP-адресов без деградации производительности пакетного фильтра.
Whitelisting через parsers/s02-enrich/whitelists.yaml критически важен, иначе из коробки агент способен забанить ваш CI/CD, мониторинг и uptime-чекеры.
Все команды cscli работают через локальный API, поэтому tuning и разбор алертов возможны без перезапуска демона.
Что такое CrowdSec и чем он отличается от Fail2ban
CrowdSec, это агент на Go, который читает логи (systemd-journal, syslog, файлы), пропускает их через цепочку парсеров и сценариев и генерирует решения (decisions) о блокировке IP. Ключевое архитектурное отличие от Fail2ban в том, что детектирование и блокировка развязаны. Агент только сообщает: «эта скотина брутит SSH, 200 неудачных за 60 секунд». Что делать дальше, решает отдельный процесс, bouncer: добавить IP в set nftables, вернуть 403 в nginx, отправить CAPTCHA через Cloudflare Worker.
На практике это даёт три вещи, которых у Fail2ban нет из коробки:
Коллективный интеллект. Каждая инсталляция, зарегистрированная в Console, отправляет анонимизированные сигналы в централизованный CTI, а взамен получает список из ~2 млн IP, которые прямо сейчас атакуют других участников сети. Fail2ban видит только то, что бьётся в конкретно ваш SSH.
Единый язык детекций. Сценарии CrowdSec, это YAML с типами leaky bucket, trigger, counter. Тот же сценарий работает и для nginx-логов, и для journald, и для кастомного JSON-приложения (при условии, что есть парсер).
Масштабируемость. В Fail2ban всё живёт на одной машине. У CrowdSec один Local API (LAPI) может обслуживать десятки агентов и десятки bouncer'ов; блок IP, обнаруженный на web-фронте, автоматически прилетает и на бастион, и на почтовый узел.
Проект стартовал в 2020 году как форк идей fail2ban с осознанной задачей заменить его на современных инсталляциях. Если вы уже разобрались с nftables и защитой от DDoS, CrowdSec встраивается в этот стек как более умный источник блок-листа.
Как установить CrowdSec на Debian, Ubuntu и RHEL
Установка идёт через официальный репозиторий, потому что версии в дистрибутивных репах отстают на 3–6 месяцев, а сценарии из Hub требуют свежий парсер. На Debian/Ubuntu:
Проверьте, что агент поднялся и LAPI слушает на локалхосте:
sudo cscli metrics
sudo cscli hub list
sudo ss -tlnp | grep 8080
Если cscli ругается на «cannot connect to local API», проверьте /etc/crowdsec/config.yaml: секция api.server.listen_uri должна быть 127.0.0.1:8080, а api.client.credentials_path должен указывать на существующий local_api_credentials.yaml. Честно говоря, у меня 8 из 10 «сломанных» установок падают именно на этом.
Архитектура: LAPI, парсеры, сценарии, bouncers
Разберём поток данных, потому что без понимания этой схемы отладка превращается в гадание. Лог-строка входит в агент через acquisition (модуль-источник: journald, файл, docker, k8s-audit, HTTP endpoint). Дальше она идёт через цепочку парсеров, которые обогащают её метаданными: geo-lookup, парсинг User-Agent, извлечение полей из nginx-формата combined. Обогащённая строка попадает в сценарии, по сути, leaky bucket'ы, которые считают события за окно времени. Когда bucket переполняется, генерируется алерт с меткой (например, crowdsecurity/http-crawl-non_statics), из алерта рождается decision, и decision через LAPI становится доступен всем зарегистрированным bouncer'ам.
Коллекция, это метапакет: crowdsecurity/nginx тянет парсер для combined-логов, набор сценариев (http-crawl, http-bad-user-agent, http-probing), postoverflow для дедупликации и профиль.
Настройка bouncer для nftables
Bouncer, это отдельный процесс, который опрашивает LAPI и применяет decisions. Для cs-firewall-bouncer с backend'ом nftables работает такая схема: bouncer создаёт свою таблицу и chain, а внутри создаёт set типа ipv4_addr с флагом timeout. Каждый забаненный IP превращается в элемент set с TTL, равным сроку decision (по умолчанию 4 часа).
После первого синка вы должны увидеть таблицу с set'ом, содержащим тысячи IP из community blocklist. Проверьте, что chain присоединён к hook prerouting или input:
sudo nft list ruleset | grep -A 5 crowdsec
Если у вас уже есть кастомный nftables-ruleset (см. мою статью про nftables в продакшене), CrowdSec корректно живёт в отдельной таблице и не конфликтует с вашей filter или nat. Единственное, что нужно проверить, это приоритеты hook'ов. По умолчанию bouncer использует priority -150 (раньше conntrack), что и требуется для дропа паразитного трафика до состояния.
Защита nginx через AppSec Component и сценарии
Есть два уровня защиты веб-сервиса. Первый — классический: агент читает nginx access-логи, детектирует паттерны (сканирование, брут форм, аномальные User-Agent) и через bouncer блокирует IP на L3/L4. Это работает, но реагирует пост-фактум: сначала пакет уходит в приложение, потом появляется в логе, потом парсер, потом сценарий, потом decision, потом блок.
Второй уровень, это AppSec Component, добавленный в 1.5 и стабилизированный в 1.6. По сути, это HTTP-endpoint внутри CrowdSec, который принимает запросы от crowdsec-nginx-bouncer (или встроенного модуля Traefik) и синхронно возвращает вердикт allow/deny. Внутри AppSec живёт форк Coraza WAF с поддержкой ModSecurity CRS правил. По сути, лёгкий WAF без Java-стека.
Bouncer перехватывает запрос, отправляет метаданные (метод, путь, заголовки, тело для POST) в AppSec, ждёт вердикт до 100 мс и либо пропускает, либо возвращает 403. У нас в проде такой setup режет типовые сканы (nuclei, nikto, Acunetix ботов) до того, как они догружают payload. Первую неделю после включения я, если честно, каждый час смотрел в cscli alerts list: боялся ложных 403 на нормальных пользователях. Пришлось расширить пару правил по путям /api/v2/*, но потом всё встало на автопилот.
Как настроить CrowdSec для защиты SSH от bruteforce
Классика жанра. После установки коллекции crowdsecurity/sshd и включения journald-источника в acquis.yaml агент видит события sshd. Основные сценарии:
crowdsecurity/ssh-bf, bruteforce (≥6 неудачных за 10 сек).
crowdsecurity/ssh-slow-bf, медленный брут (≥10 за 10 минут).
crowdsecurity/ssh-cve-2024-6387, попытки эксплуатации regreSSHion.
После systemctl reload crowdsec проверить, что метрики растут:
sudo cscli metrics | grep -E "ssh|sshd"
sudo cscli alerts list
sudo cscli decisions list --scope Ip
Если вы уже перевели SSH на сертификаты и бастион по полному руководству по защите SSH, CrowdSec всё равно полезен как второй эшелон: 90% брута идёт в TCP/22 просто потому, что порт открыт. Каждая заблокированная попытка, это освобождённый tcp-connect и меньше строк в аудит-логе.
Console (app.crowdsec.net), это SaaS-панель, куда агент отсылает анонимизированные метаданные алертов: тип сценария, timestamp, метаданные (без содержимого запросов и логинов). Взамен ваш инстанс подписывается на CTI-фиды: community blocklist (адреса, замеченные в атаках у других участников за последние 24 часа), премиальные threat-intel листы (VPN, Tor-выходы, известные C2), а с 2025 года ещё и профильные листы «attacks-on-nginx», «ssh-brute», «wordpress-probing».
Флаг -e context позволяет Console видеть, к какому сервису относится алерт (например, к nginx или sshd), что помогает точнее назначать фиды. Без context вы будете получать только общий community blocklist.
Полный список коллекций доступен в CrowdSec Hub. Официальная документация по Blocklists API объясняет модель origin/scope и особенности decisions с ttl.
Multi-server: один LAPI на кластер
В инсталляции с двумя+ узлами имеет смысл выделить один сервер как LAPI-host, а остальные узлы превратить в агентов, которые пишут алерты в него. Это даёт единую картину атак и один блок-лист, распространяемый на все bouncer'ы одновременно.
# На LAPI-хосте
sudo cscli lapi server add-user webnode-01 --interactive
# На агенте webnode-01
sudo cscli lapi register --url https://lapi.internal:8080 --machine webnode-01
sudo cscli lapi validate # на LAPI подтвердить
# Отключить локальный LAPI на агенте (в /etc/crowdsec/config.yaml)
# api.server.enable: false
Для продакшена включите mTLS между агентами и LAPI (секция api.server.tls), потому что API-ключи в HTTP-трафике, это плохая идея даже во внутреннем VPC. Используйте официальный гайд по TLS-аутентификации: он покрывает генерацию корневого CA и настройку agent-side сертификатов.
Bouncers по-прежнему подключаются к LAPI по HTTP+ключу, но их можно посадить за отдельный listener или reverse proxy с ограничением по IP.
Типичные ошибки и тюнинг в продакшене
За два года эксплуатации у меня скопился список граблей, на которые попадают почти все:
Забыть про uptime-мониторинг. Pingdom, UptimeRobot, StatusCake ходят с публичных IP и в 3 утра решают вас брутфорсить head-запросами. Их подсети надо явно whitelist'ить. CrowdSec поддерживает whitelist через expr-выражения, где можно матчить по User-Agent.
Слишком агрессивные сценарии. Коллекция crowdsecurity/base-http-scenarios содержит http-crawl-non_statics с порогом 40 запросов за 10 сек. Для SPA с ленивой подгрузкой это норма. Копируйте сценарий в /etc/crowdsec/scenarios/ и правьте capacity и leakspeed.
Journald без persistence. Если journald работает в volatile режиме, после ребута агент теряет контекст, и вы получаете фантомные false negatives первые 5 минут после старта. Проверьте Storage=persistent в /etc/systemd/journald.conf.
Bouncer не переживает bounce LAPI. В 1.6.x есть флаг insecure_skip_verify: false и retry_after: 30. Всегда ставьте retry, иначе краткий рестарт LAPI приведёт к тому, что bouncer забудет активный блок-лист.
Метрики не попадают в Prometheus. CrowdSec экспортирует Prometheus-метрики на 127.0.0.1:6060/metrics. Если у вас есть Wazuh (см. статью про Wazuh на Linux), объедините эти два потока: CrowdSec для реактивного блока, Wazuh для расследования и хранения.
Для отладки конкретных алертов используйте explain-режим:
Он покажет, какие парсеры сработали, какие ключи заполнились и какие сценарии подхватили событие. В разы быстрее, чем ковырять debug-логи агента.
Часто задаваемые вопросы
Чем отличается CrowdSec от Fail2ban на практике?
Fail2ban читает логи и сразу пишет в iptables на одном хосте. CrowdSec разделяет детекцию (агент) и блокировку (bouncer), поддерживает центральный API для кластера и получает коллективный блок-лист с ~2 млн активных IP. Fail2ban проще для одиночного VPS; CrowdSec выигрывает на 3+ серверах и там, где важна коллективная защита.
Безопасно ли использовать CrowdSec в продакшене?
Да, при соблюдении двух правил. Первое: whitelist ваших мониторингов, CI/CD и VPN, иначе рискуете забанить сами себя. Второе: не отдавайте LAPI наружу, держите его во внутренней сети и по возможности с mTLS. Проект аудитирован ANSSI (Франция), исходники открыты, версия 1.6 стабильна с середины 2024 года.
Как заблокировать IP вручную через CrowdSec?
Команда sudo cscli decisions add --ip 203.0.113.10 --duration 24h --reason manual создаёт decision, который bouncer подхватит на следующем polling-цикле (по умолчанию каждые 10 секунд). Для сети: --range 203.0.113.0/24. Снять: cscli decisions delete --ip 203.0.113.10.
Заменяет ли AppSec Component полноценный WAF типа ModSecurity?
Не полностью. AppSec подходит для базовой защиты OWASP Top 10, virtual patching CVE и блокировки известных сканеров. Для сложных приложений с высокими требованиями к комплаенсу (PCI DSS 4.0, финтех) я всё ещё рекомендую отдельный WAF типа ModSecurity+CRS или коммерческие решения. AppSec, это «good enough» защита из коробки на 20% усилий.
Как обновить сценарии и коллекции CrowdSec?
Хаб обновляется командами sudo cscli hub update и sudo cscli hub upgrade. Первая тянет свежий индекс, вторая скачивает новые версии установленных коллекций и парсеров. После апгрейда обязательно sudo systemctl reload crowdsec. Автоматизировать можно через systemd timer раз в сутки.
Priya is a threat hunter who spent four years at CrowdStrike on the OverWatch team chasing eCrime intrusions on Linux endpoints, then moved to a mid-size SaaS company in 2023 to build out their detection engineering function from scratch. Her day job is writing Falco rules, tuning auditd, and arguing with developers about why curl-piped-to-bash in a Dockerfile is not, in fact, fine.
She's GCFA and GCIH certified, contributed a handful of Sigma rules to the public repo, and gave a talk at BSides Bangalore on detecting Kinsing miner infections through cgroup anomalies.
Before security she did three years as a Linux sysadmin at Flipkart's logistics arm, which is where she learned that most "sophisticated APT activity" turns out to be a forgotten cron job running as root.
Практическое руководство по настройке auditd на RHEL 9 и Ubuntu 24.04 в 2026: правила sudo, execve и /etc/passwd, поиск через ausearch и пересылка событий в Wazuh или Splunk через audisp-плагины.
Как подписывать контейнеры без приватных ключей: Cosign v2.4 keyless в GitHub Actions, проверка через Kyverno в Kubernetes, SLSA-provenance и SBOM-attestations. Практический пример workflow и типичные ошибки.
Trivy 0.65+ для DevSecOps: сканирование контейнеров, Terraform и Kubernetes YAML, генерация SBOM (CycloneDX, SPDX), поиск секретов и готовые пайплайны для GitHub Actions, GitLab CI и Trivy Operator.