Files
Portainer/crowdsec/README.md
T
2026-07-25 11:20:27 +00:00

463 lines
14 KiB
Markdown

# 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
1. **Red Docker**: La red `proxy` debe existir
```bash
docker network create proxy
```
2. **Registro DNS**: Configura el registro A para el dashboard
- `grafana.tudominio.com` → IP del servidor
3. **Directorios**: Créalos automáticamente con el setup:
```bash
cd crowdsec && ./setup.sh
```
### Paso 1: Configurar variables de entorno
Edita el `.env` local con las variables reales:
```bash
nano crowdsec/.env
```
Variables críticas:
```env
# 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
```bash
cd crowdsec
./setup.sh
```
El script:
1. Genera una clave aleatoria para el bouncer (si no está definida)
2. Crea los directorios necesarios en `/opt/crowdsec/` y `/opt/traefik/logs`
3. Genera la configuración dinámica de Traefik (`crowdsec-bouncer.yml`)
4. Crea los archivos `acquis.yaml` para leer logs de Traefik y Docker
5. 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:
```bash
cd Traefik
docker compose --env-file .env up -d
```
### Paso 4: Desplegar CrowdSec
```bash
cd crowdsec
docker compose --env-file .env up -d
```
### Paso 5: Verificar el despliegue
```bash
# 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:
1. **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)`
2. **Crear Application**:
- Ve a **Applications** → **Create**
- Name: `CrowdSec Grafana`
- Slug: `grafana`
- Provider: selecciona el creado en paso 1
- UI Settings: opcional (icono, descripción)
3. **Asociar al Embedded Outpost**:
- Ve a **Outposts** → `authentik Embedded Outpost` → **Edit**
- Asegúrate de que la aplicación `CrowdSec Grafana` está seleccionada
- Haz clic en **Update**
> El middleware `ths-authentik@docker` ya está configurado en las labels del servicio `crowdsec-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:
```yaml
labels:
# ... labels existentes ...
traefik.http.routers.mi-app.middlewares: "ths-authentik@docker,crowdsec-bouncer@file"
```
> Importante: los middlewares se encadenan en orden. `crowdsec-bouncer` primero bloquea IPs maliciosas, luego `ths-authentik` autentica.
### Método 2: Solo CrowdSec (sin Authentik)
Para servicios que no requieren login pero sí protección anti-ataques (ej: APIs):
```yaml
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
```bash
# 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
```bash
# 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.
```bash
# 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:
```bash
# 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
```bash
# 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:
```env
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`:
```bash
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:
```yaml
---
# 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:
1. Añade la IP a la allowlist persistente del bot
2. Sincroniza `ignoreip` en fail2ban
3. Permite la IP en firewalld (ipset)
4. Elimina cualquier decisión activa en CrowdSec (`cscli decisions delete`)
5. Añade la IP a la allowlist `telegram-bot` en 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:
1. **Bot de Telegram**: `/allow <ip>` desbanea y allowlistea de inmediato en fail2ban + firewalld + CrowdSec.
2. **WireGuard VPN**: Acceso por `10.8.0.0/24`, en la allowlist `vpn-local` → nunca baneada.
3. **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:
```env
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 en `127.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`, sin `CAP_SYS_ADMIN` ni privilegios elevados
- **SELinux**: Volúmenes con contexto `:Z` para entornos con SELinux habilitado
- **Key del bouncer**: Generada aleatoriamente y almacenada solo en `.env` (gitignorado)
## 🛠️ Troubleshooting
### El bouncer no bloquea
1. Verifica que el plugin está cargado en Traefik:
```bash
docker logs traefik | grep crowdsec
```
2. Verifica que el middleware está configurado:
```bash
docker exec traefik wget -qO- http://localhost:8080/api/http/middlewares | grep crowdsec
```
3. Verifica que CrowdSec tiene decisiones activas:
```bash
docker exec crowdsec cscli decisions list
```
4. Comprueba conectividad entre Traefik y CrowdSec:
```bash
docker exec traefik wget -qO- http://crowdsec:8080/v1/heartbeat
```
### CrowdSec no detecta ataques
1. Verifica que los logs de Traefik se están generando:
```bash
ls -lh /opt/traefik/logs/access.log
tail -f /opt/traefik/logs/access.log
```
2. Verifica el acquis de CrowdSec:
```bash
docker exec crowdsec cat /etc/crowdsec/acquis.yaml
```
3. Revisa los logs del engine:
```bash
docker logs -f crowdsec
```
4. Simula un ataque de prueba:
```bash
curl -H "User-Agent: Nikto" https://tu-dominio.com/
docker exec crowdsec cscli decisions list
```
### El dashboard pide login pero Authentik no redirige
1. Verifica que el middleware está correctamente referenciado en las labels:
```bash
docker inspect crowdsec-grafana | grep -A 20 Labels
```
2. Revisa que la aplicación existe en Authentik y está asociada al Embedded Outpost
3. Comprueba los logs de Authentik:
```bash
docker logs ths-authentik-server
```
## 💾 Backups
Incluye en tus backups de Kopia (ya configurados en `backups/kopia/`):
```bash
# Datos de CrowdSec (decisiones, bouncers, config)
/opt/crowdsec/data/
# Configuración personalizada
/opt/crowdsec/config/
```
## 🔄 Actualizaciones
Para actualizar CrowdSec:
1. Edita `.env` y actualiza la versión si es necesario:
```env
CROWDSEC_IMAGE=crowdsecurity/crowdsec:latest
GRAFANA_IMAGE=grafana/grafana:latest
```
2. Redespiega:
```bash
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](https://github.com/crowdsecurity/crowdsec/releases).
## 📚 Recursos
- [Documentación oficial de CrowdSec](https://docs.crowdsec.net/)
- [CrowdSec + Traefik Plugin](https://plugins.traefik.io/plugins/6335349fe93a526d1ec2aed6/crowdsec-bouncer)
- [CrowdSec Hub (colecciones)](https://hub.crowdsec.net/)
- [Grafana Docs](https://grafana.com/docs/grafana/latest/)
- [CrowdSec Discord](https://discord.gg/crowdsec)