463 lines
14 KiB
Markdown
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)
|