CrowdSec - Sistema de Seguridad y Prevención de Intrusiones
CrowdSec es un IPS/IDS colaborativo que analiza logs, detecta comportamientos maliciosos y bloquea atacantes en tiempo real. Usa inteligencia comunitaria para compartir reputación de IPs entre todos los usuarios.
📋 Descripción
Este stack despliega:
- CrowdSec Engine: Motor de detección que analiza logs de Traefik y otros contenedores
- CrowdSec Bouncer (Traefik Plugin): Middleware que bloquea IPs maliciosas a nivel HTTP (L7)
- Grafana: Dashboard web para visualizar alertas, decisiones y métricas (protegido con Authentik)
- Baneos automáticos contra ataques de fuerza bruta, escaneos, CVEs conocidos y más
🚀 Despliegue
Prerequisitos
-
Red Docker: La red
proxydebe existirdocker network create proxy -
Registro DNS: Configura el registro A para el dashboard
grafana.tudominio.com→ IP del servidor
-
Directorios: Créalos automáticamente con el setup:
cd crowdsec && ./setup.sh
Paso 1: Configurar variables de entorno
Edita el .env local con las variables reales:
nano crowdsec/.env
Variables críticas:
# Clave API del bouncer (generada automáticamente por setup.sh o pon una manual)
CROWDSEC_BOUNCER_API_KEY=tu-key-de-64-caracteres
# Dominio del dashboard Grafana
CROWDSEC_GRAFANA_DOMAIN=grafana.tudominio.com
# Colecciones a instalar
CROWDSEC_COLLECTIONS=crowdsecurity/traefik
# Rutas de datos
CROWDSEC_CONFIG_PATH=/opt/crowdsec/config
CROWDSEC_DATA_PATH=/opt/crowdsec/data
TRAEFIK_LOG_PATH=/opt/traefik/logs
Paso 2: Ejecutar el script de setup
cd crowdsec
./setup.sh
El script:
- Genera una clave aleatoria para el bouncer (si no está definida)
- Crea los directorios necesarios en
/opt/crowdsec/y/opt/traefik/logs - Genera la configuración dinámica de Traefik (
crowdsec-bouncer.yml) - Crea los archivos
acquis.yamlpara leer logs de Traefik y Docker - Aplica contextos SELinux si es necesario
Paso 3: (Re)desplegar Traefik
Importante: Traefik necesita reiniciarse para cargar el plugin de CrowdSec y los nuevos volúmenes.
Actualiza el archivo .env de Traefik para incluir TRAEFIK_LOG_DIR=/opt/traefik/logs y redespliega:
cd Traefik
docker compose --env-file .env up -d
Paso 4: Desplegar CrowdSec
cd crowdsec
docker compose --env-file .env up -d
Paso 5: Verificar el despliegue
# Ver contenedores
docker ps | grep crowdsec
# Ver logs del engine
docker logs crowdsec
# Verificar decisiones activas
docker exec crowdsec cscli decisions list
# Verificar métricas
docker exec crowdsec cscli metrics
# Verificar estado del bouncer
docker exec crowdsec cscli bouncers list
🔐 Configurar Authentik para el Dashboard (Grafana)
El dashboard de Grafana (grafana.tudominio.com) está protegido con ths-authentik@docker. Para que funcione:
En el panel de Authentik:
-
Crear Proxy Provider:
- Ve a Applications → Providers → Create
- Tipo: Proxy Provider
- Name:
CrowdSec Grafana - External host:
https://grafana.tudominio.com - Authentication flow:
default-authentication-flow - Authorization flow:
default-provider-authorization-implicit-consent - Mode:
Forward auth (single application)
-
Crear Application:
- Ve a Applications → Create
- Name:
CrowdSec Grafana - Slug:
grafana - Provider: selecciona el creado en paso 1
- UI Settings: opcional (icono, descripción)
-
Asociar al Embedded Outpost:
- Ve a Outposts →
authentik Embedded Outpost→ Edit - Asegúrate de que la aplicación
CrowdSec Grafanaestá seleccionada - Haz clic en Update
- Ve a Outposts →
El middleware
ths-authentik@dockerya está configurado en las labels del serviciocrowdsec-grafana. Si otros stacks también lo usan, comparte la misma configuración de Authentik.
🛡️ Proteger servicios con CrowdSec
Método 1: Middleware global (recomendado)
Añade el middleware crowdsec-bouncer@file a los routers de Traefik que quieras proteger:
labels:
# ... labels existentes ...
traefik.http.routers.mi-app.middlewares: "ths-authentik@docker,crowdsec-bouncer@file"
Importante: los middlewares se encadenan en orden.
crowdsec-bouncerprimero bloquea IPs maliciosas, luegoths-authentikautentica.
Método 2: Solo CrowdSec (sin Authentik)
Para servicios que no requieren login pero sí protección anti-ataques (ej: APIs):
labels:
traefik.http.routers.mi-api.middlewares: "crowdsec-bouncer@file"
Lista de servicios recomendados para proteger
| Prioridad | Servicio | Motivo |
|---|---|---|
| Alta | Traefik Dashboard | Expuesto, blanco de escaneos |
| Alta | Authentik | Puerta de entrada SSO, blanco de brute force |
| Alta | Gitea | Expuesto a clonaciones maliciosas |
| Media | n8n | Webhooks públicos, riesgo de SSRF |
| Media | Nextcloud | Login expuesto, brute force |
| Media | Homepage | Aunque es solo dashboard, expuesto |
🔍 Comandos útiles
Ver estado de CrowdSec
# Estadísticas generales
docker exec crowdsec cscli metrics
# Decisiones activas (baneos)
docker exec crowdsec cscli decisions list
# Alertas recientes
docker exec crowdsec cscli alerts list --limit 20
# Inspeccionar una IP específica
docker exec crowdsec cscli decisions inspect --ip 1.2.3.4
# Ver bouncers registrados
docker exec crowdsec cscli bouncers list
Gestión de decisiones
# Banear una IP manualmente (1 hora)
docker exec crowdsec cscli decisions add --ip 1.2.3.4 --duration 1h --reason "manual"
# Desbanear una IP
docker exec crowdsec cscli decisions delete --ip 1.2.3.4
# Listar escenarios activos
docker exec crowdsec cscli scenarios list
Allowlists (IPs que nunca se banean)
Usar cscli allowlists (disponible desde CrowdSec v1.6+) en lugar del antiguo truco de decisions add --duration 99999h. Las allowlists son permanentes y sobreviven a reinicios.
# Crear una allowlist nueva
docker exec crowdsec cscli allowlists create <nombre> -d "Descripción"
# Añadir una IP o CIDR a una allowlist
docker exec crowdsec cscli allowlists add <nombre> <ip-o-cidr>
# Quitar una IP de una allowlist
docker exec crowdsec cscli allowlists remove <nombre> <ip-o-cidr>
# Listar todas las allowlists y su contenido
docker exec crowdsec cscli allowlists list
docker exec crowdsec cscli allowlists inspect <nombre>
Allowlists configuradas en este servidor
| Allowlist | Contenido | Propósito |
|---|---|---|
vpn-local |
10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16, 10.8.0.0/24 |
Redes privadas y WireGuard VPN |
cloudflare |
Todos los rangos IPv4 de Cloudflare | Tráfico legítimo de Cloudflare (si se usa Cloudflare Tunnel) |
telegram-bot |
IPs añadidas dinámicamente con /allow <ip> |
IPs gestionadas por el bot de Telegram |
Para recrearlas desde cero:
# vpn-local
docker exec crowdsec cscli allowlists create vpn-local -d "Redes privadas y VPN"
docker exec crowdsec cscli allowlists add vpn-local 10.0.0.0/8 172.16.0.0/12 192.168.0.0/16 10.8.0.0/24
# cloudflare
docker exec crowdsec cscli allowlists create cloudflare -d "Rangos IPv4 de Cloudflare"
docker exec crowdsec cscli allowlists add cloudflare \
173.245.48.0/20 103.21.244.0/22 103.22.200.0/22 103.31.4.0/22 \
141.101.64.0/18 108.162.192.0/18 190.93.240.0/20 188.114.96.0/20 \
197.234.240.0/22 198.41.128.0/17 162.158.0.0/15 104.16.0.0/13 \
104.24.0.0/14 172.64.0.0/13 131.0.72.0/22
# telegram-bot (vacía, el bot la gestiona)
docker exec crowdsec cscli allowlists create telegram-bot -d "IPs allowlisteadas via bot de Telegram"
Actualizar la blocklist comunitaria
# Actualizar manualmente
docker exec crowdsec cscli hub update
# Ver si hay actualizaciones pendientes
docker exec crowdsec cscli hub list
⚙️ Configuración adicional
Añadir más colecciones
Edita crowdsec/.env y añade colecciones separadas por coma:
CROWDSEC_COLLECTIONS=crowdsecurity/traefik,crowdsecurity/http-cve,crowdsecurity/whitelist-good-actors
Luego redeploya el stack. Colecciones recomendadas:
| Colección | Descripción |
|---|---|
crowdsecurity/traefik |
Parsea logs de acceso de Traefik |
crowdsecurity/http-cve |
Detecta intentos de explotación de CVEs HTTP |
crowdsecurity/whitelist-good-actors |
Whitelist de servicios legítimos (Google, CloudFlare, etc.) |
crowdsecurity/nginx |
Escenarios extra para servidores web |
crowdsecurity/base-http-scenarios |
Escaneos básicos HTTP (path traversal, SQLi, etc.) |
Configurar whitelist de IPs locales
Para que CrowdSec no banee IPs de tu red local/VPN, edita /opt/crowdsec/config/parsers/s02-enrich/whitelists.yaml:
docker exec crowdsec cscli parsers install crowdsecurity/whitelists
O añade manualmente en notifications/http.yaml el parámetro whitelist_ips.
Añadir adquisición de logs adicionales
Edita /opt/crowdsec/config/acquis.yaml para añadir fuentes de log adicionales:
---
# Logs de Traefik (ya configurado)
source: file
filenames:
- /var/log/traefik/access.log
labels:
type: traefik
# Logs de Authentik (ejemplo adicional)
# source: docker
# container_name:
# - ths-authentik-server
# labels:
# type: authentik
🤖 Integración con el bot de Telegram
El bot f2b-telegram-bot (en /home/felidae/f2b-telegram-bot/) gestiona fail2ban, firewalld y CrowdSec de forma unificada. El comando /allow <ip> ejecuta en una sola operación:
- Añade la IP a la allowlist persistente del bot
- Sincroniza
ignoreipen fail2ban - Permite la IP en firewalld (ipset)
- Elimina cualquier decisión activa en CrowdSec (
cscli decisions delete) - Añade la IP a la allowlist
telegram-boten CrowdSec (nunca volverá a banearse)
Comandos relevantes del bot
| Comando | Efecto en CrowdSec |
|---|---|
/allow <ip> |
Unban + añade a allowlist telegram-bot |
/unallow <ip> |
Quita de allowlist telegram-bot |
/unban <ip> |
Solo unban (sin añadir a allowlist) |
/health |
Muestra estado de LAPI + disponibilidad Docker |
Problema CGNAT y mitigación
Si el servidor está en una red sin IP fija o compartida (CGNAT), un atacante en la misma red puede provocar que tu IP legítima quede baneada por CrowdSec. La mitigación implementada:
- Bot de Telegram:
/allow <ip>desbanea y allowlistea de inmediato en fail2ban + firewalld + CrowdSec. - WireGuard VPN: Acceso por
10.8.0.0/24, en la allowlistvpn-local→ nunca baneada. - Cloudflare Tunnel (opcional, ver
cloudflared/README.md): elimina el problema de raíz al ocultar la IP real del servidor.
Configuración del bot para CrowdSec
Variables de entorno relevantes en .env del bot:
CROWDSEC_ENABLED=true
CROWDSEC_ALLOWLIST_NAME=telegram-bot
Requiere que el bot se ejecute en el mismo host que el contenedor crowdsec (acceso a docker exec).
🔒 Seguridad
- API local solo en loopback: La API de CrowdSec (
cscli lapi) solo escucha en127.0.0.1:8080 - Bouncer integrado en Traefik: No expone puertos adicionales, todo el filtrado ocurre dentro de Traefik
- Dashboard protegido por Authentik: Grafana requiere autenticación SSO previa
- Motor con capacidades mínimas: Solo
NET_BIND_SERVICE, sinCAP_SYS_ADMINni privilegios elevados - SELinux: Volúmenes con contexto
:Zpara entornos con SELinux habilitado - Key del bouncer: Generada aleatoriamente y almacenada solo en
.env(gitignorado)
🛠️ Troubleshooting
El bouncer no bloquea
-
Verifica que el plugin está cargado en Traefik:
docker logs traefik | grep crowdsec -
Verifica que el middleware está configurado:
docker exec traefik wget -qO- http://localhost:8080/api/http/middlewares | grep crowdsec -
Verifica que CrowdSec tiene decisiones activas:
docker exec crowdsec cscli decisions list -
Comprueba conectividad entre Traefik y CrowdSec:
docker exec traefik wget -qO- http://crowdsec:8080/v1/heartbeat
CrowdSec no detecta ataques
-
Verifica que los logs de Traefik se están generando:
ls -lh /opt/traefik/logs/access.log tail -f /opt/traefik/logs/access.log -
Verifica el acquis de CrowdSec:
docker exec crowdsec cat /etc/crowdsec/acquis.yaml -
Revisa los logs del engine:
docker logs -f crowdsec -
Simula un ataque de prueba:
curl -H "User-Agent: Nikto" https://tu-dominio.com/ docker exec crowdsec cscli decisions list
El dashboard pide login pero Authentik no redirige
-
Verifica que el middleware está correctamente referenciado en las labels:
docker inspect crowdsec-grafana | grep -A 20 Labels -
Revisa que la aplicación existe en Authentik y está asociada al Embedded Outpost
-
Comprueba los logs de Authentik:
docker logs ths-authentik-server
💾 Backups
Incluye en tus backups de Kopia (ya configurados en backups/kopia/):
# Datos de CrowdSec (decisiones, bouncers, config)
/opt/crowdsec/data/
# Configuración personalizada
/opt/crowdsec/config/
🔄 Actualizaciones
Para actualizar CrowdSec:
- Edita
.envy actualiza la versión si es necesario:CROWDSEC_IMAGE=crowdsecurity/crowdsec:latest GRAFANA_IMAGE=grafana/grafana:latest - Redespiega:
cd crowdsec docker compose --env-file .env pull docker compose --env-file .env up -d
⚠️ Antes de actualizar versiones mayores de CrowdSec, revisa el changelog.