CrowdSec на Linux в 2026: коллективная защита, AppSec WAF и bouncers для nftables и nginx

Пошаговая настройка CrowdSec 1.6 на Linux: агент, LAPI, bouncer для nftables, AppSec WAF перед nginx, защита SSH от bruteforce и подключение к коллективному Blocklist API с примерами команд и типичными ошибками.

Обновлено: 31 августа 2026 г.

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:

curl -s https://install.crowdsec.net | sudo sh
sudo apt update
sudo apt install crowdsec crowdsec-firewall-bouncer-nftables
sudo systemctl enable --now crowdsec

На RHEL/Rocky/AlmaLinux 9:

curl -s https://install.crowdsec.net | sudo sh
sudo dnf install crowdsec crowdsec-firewall-bouncer-nftables
sudo systemctl enable --now crowdsec

Проверьте, что агент поднялся и 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'ам.

Структура каталогов:

/etc/crowdsec/
├── acquis.yaml                 # источники логов
├── config.yaml                 # основной конфиг агента
├── parsers/
│   ├── s00-raw/                # syslog, cri
│   ├── s01-parse/              # nginx, sshd, apache
│   └── s02-enrich/             # geoip, whitelists
├── scenarios/                  # правила детекции
├── postoverflows/              # реакция на алерт
├── profiles.yaml               # маппинг алерт → decision
└── notifications/              # slack, http, splunk

Хаб (cscli hub), это git-репозиторий с готовыми парсерами и сценариями для сотен сервисов. Установка коллекций одной командой:

sudo cscli collections install crowdsecurity/nginx
sudo cscli collections install crowdsecurity/sshd
sudo cscli collections install crowdsecurity/appsec-virtual-patching
sudo cscli collections install crowdsecurity/appsec-generic-rules
sudo systemctl reload crowdsec

Коллекция, это метапакет: 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 часа).

# Регистрация bouncer в LAPI
sudo cscli bouncers add firewall-bouncer

# Записать полученный ключ в конфиг bouncer'а
sudo nano /etc/crowdsec/bouncers/crowdsec-firewall-bouncer.yaml
# api_key: <вставить сюда>
# api_url: http://127.0.0.1:8080/

sudo systemctl enable --now crowdsec-firewall-bouncer
sudo nft list table inet crowdsec

После первого синка вы должны увидеть таблицу с 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-стека.

Установка на nginx:

sudo apt install crowdsec-nginx-bouncer
sudo cscli bouncers add nginx-bouncer
# Ключ вписать в /etc/crowdsec/bouncers/crowdsec-nginx-bouncer.conf

# Включить AppSec-listener
sudo cscli collections install crowdsecurity/appsec-virtual-patching
sudo cscli collections install crowdsecurity/appsec-crs

# В /etc/crowdsec/acquis.yaml добавить:
# ---
# appsec_config: crowdsecurity/appsec-default
# labels:
#   type: appsec
# listen_addr: 127.0.0.1:7422
# source: appsec

sudo systemctl reload crowdsec nginx

Затем в nginx-конфиге в блоке server:

location / {
    access_by_lua_file /etc/crowdsec/bouncer/crowdsec.lua;
    proxy_pass http://backend;
}

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.
# /etc/crowdsec/acquis.yaml
source: journalctl
journalctl_filter:
  - _SYSTEMD_UNIT=ssh.service
labels:
  type: syslog

После 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 и меньше строк в аудит-логе.

name: mycompany/whitelists
description: "Whitelist office and CI"
whitelist:
  reason: "internal networks"
  ip:
    - "10.0.0.5"
    - "203.0.113.44"
  cidr:
    - "10.10.0.0/16"
    - "192.0.2.0/24"

Что такое Blocklist API и Console CrowdSec

Console (app.crowdsec.net), это SaaS-панель, куда агент отсылает анонимизированные метаданные алертов: тип сценария, timestamp, метаданные (без содержимого запросов и логинов). Взамен ваш инстанс подписывается на CTI-фиды: community blocklist (адреса, замеченные в атаках у других участников за последние 24 часа), премиальные threat-intel листы (VPN, Tor-выходы, известные C2), а с 2025 года ещё и профильные листы «attacks-on-nginx», «ssh-brute», «wordpress-probing».

sudo cscli console enroll -e context,manual,tainted <enrollment_key>
sudo cscli decisions list --origin lists

Флаг -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-режим:

sudo cscli explain --file /var/log/nginx/access.log --type nginx
sudo cscli explain --log '...сырую строку лога...' --type sshd

Он покажет, какие парсеры сработали, какие ключи заполнились и какие сценарии подхватили событие. В разы быстрее, чем ковырять 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 Ramaswamy

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.