--- title: "Cómo proteger Nginx y Traefik con CrowdSec en Ubuntu 24.04" description: "Instala CrowdSec en Ubuntu 24.04, analiza los logs de Nginx y Traefik y bloquea IPs maliciosas con el bouncer de Nginx y el plugin de CrowdSec para Traefik v3." category: "Herramientas de Servidor" language: es source: https://cubepath.com/es/docs/herramientas-de-servidor/crowdsec-con-bouncers-traefik-y-nginx updated: 2026-09-25 --- # Cómo proteger Nginx y Traefik con CrowdSec en Ubuntu 24.04 CrowdSec es un motor de seguridad de código abierto que lee los logs de tus servicios, detecta comportamientos maliciosos (escaneos, fuerza bruta, explotación de CVE conocidos) y genera decisiones de bloqueo. Esas decisiones las aplican los bouncers, componentes que se integran en el punto de entrada del tráfico. En este tutorial instalarás CrowdSec en Ubuntu 24.04 y lo conectarás a Nginx con el bouncer Lua oficial y a Traefik v3 con el plugin de CrowdSec, comprobando en cada caso que una IP bloqueada recibe un `403`. Las partes 1 y 2 son independientes: sigue la que corresponda al proxy que usas. Si usas los dos, hazlo en servidores distintos, porque ambos necesitan los puertos 80 y 443. ## Requisitos previos Para seguir esta guía necesitas: - Un servidor con Ubuntu 24.04 LTS, por ejemplo un VPS de CubePath, y un usuario no root con privilegios `sudo`. - Para la parte 1: Nginx instalado desde los repositorios de Ubuntu y sirviendo al menos un sitio. - Para la parte 2: Docker Engine y el plugin Docker Compose instalados, y un dominio (`your_domain`) con un registro DNS A que apunte al servidor, para que Traefik obtenga el certificado TLS. - Un segundo equipo con una IP pública distinta desde la que hacer las pruebas de bloqueo. No bloquees la IP desde la que administras el servidor. ## Parte 1: CrowdSec con Nginx En esta parte CrowdSec se ejecuta como servicio del sistema, lee `/var/log/nginx/access.log` y el bouncer de Nginx consulta la API local de CrowdSec antes de atender cada petición. ### Paso 1: Instalar CrowdSec CrowdSec publica sus paquetes en un repositorio propio. El script oficial solo añade ese repositorio y su clave; descárgalo y revísalo antes de ejecutarlo: ```bash curl -fsSL -o crowdsec-repo.sh https://install.crowdsec.net less crowdsec-repo.sh sudo sh crowdsec-repo.sh ``` Instala el motor: ```bash sudo apt update sudo apt install crowdsec ``` Durante la instalación, CrowdSec detecta los servicios presentes (Nginx, SSH) e instala sus colecciones y la configuración de lectura de logs. También registra la instancia en la API central de CrowdSec para recibir la lista comunitaria de IPs maliciosas. Comprueba que el servicio está activo y que la API local (LAPI) responde: ```bash sudo systemctl status crowdsec --no-pager sudo cscli lapi status ``` ```output ● crowdsec.service - Crowdsec agent Loaded: loaded (/usr/lib/systemd/system/crowdsec.service; enabled; preset: enabled) Active: active (running) since ... ... Loaded credentials from /etc/crowdsec/local_api_credentials.yaml Trying to authenticate with username ... on http://127.0.0.1:8080/ You can successfully interact with Local API (LAPI) ``` ### Paso 2: Revisar colecciones y fuentes de logs Una colección agrupa los parsers (cómo leer un log) y los escenarios (qué comportamiento es un ataque) de un servicio. Instala las de Nginx, los CVE HTTP más explotados y SSH. Si ya estaban instaladas, `cscli` lo indica y no hace nada: ```bash sudo cscli collections install crowdsecurity/nginx crowdsecurity/http-cve crowdsecurity/sshd ``` Comprueba que CrowdSec tiene configurada la lectura de los logs de Nginx: ```bash sudo grep -rn nginx /etc/crowdsec/acquis.yaml /etc/crowdsec/acquis.d/ 2>/dev/null ``` Si el comando no devuelve nada, crea un archivo de adquisición para Nginx: ```bash sudo nano /etc/crowdsec/acquis.d/nginx.yaml ``` ```yaml filenames: - /var/log/nginx/access.log - /var/log/nginx/error.log labels: type: nginx ``` Recarga CrowdSec para aplicar los cambios: ```bash sudo systemctl reload crowdsec ``` Haz unas peticiones al sitio y revisa las métricas para ver si CrowdSec procesa el log: ```bash curl -s -o /dev/null http://localhost/ sudo cscli metrics ``` En la salida, busca la tabla `Acquisition Metrics`: la fila `file:/var/log/nginx/access.log` debe tener valores en las columnas `Lines read` y `Lines parsed`, y la columna `Lines unparsed` debe estar vacía o ser muy baja. Puedes ver cómo interpreta CrowdSec una línea concreta con `cscli explain`: ```bash sudo cscli explain --log '203.0.113.5 - - [25/Sep/2026:10:20:30 +0000] "GET /wp-login.php HTTP/1.1" 404 162 "-" "curl/8.5.0"' --type nginx ``` La salida muestra cada parser por el que pasa la línea y los escenarios en los que acaba. ### Paso 3: Instalar el bouncer de Nginx Hasta ahora CrowdSec detecta, pero no bloquea nada. El bouncer de Nginx usa el módulo Lua de Nginx para consultar a la LAPI si la IP de cada petición tiene una decisión activa. Instálalo desde el mismo repositorio: ```bash sudo apt install crowdsec-nginx-bouncer ``` El paquete instala el módulo Lua de Nginx si falta, registra el bouncer en CrowdSec, guarda su clave de API en `/etc/crowdsec/bouncers/crowdsec-nginx-bouncer.conf` y añade `/etc/nginx/conf.d/crowdsec_nginx.conf`. Ese archivo se carga en el bloque `http` y aplica la comprobación a todos los sitios, así que no hace falta tocar cada `server`. Valida la configuración de Nginx y recárgala: ```bash sudo nginx -t sudo systemctl reload nginx ``` Comprueba que el bouncer está registrado: ```bash sudo cscli bouncers list ``` Debe aparecer un bouncer con un nombre que empieza por `crowdsec-nginx-bouncer`, la IP `127.0.0.1` y marcado como válido. ### Paso 4: Probar el bloqueo Desde tu equipo de pruebas, comprueba que el sitio responde con normalidad: ```bash curl -I http://your_server_ip/ ``` ```output HTTP/1.1 200 OK ... ``` En el servidor, crea una decisión de bloqueo de cinco minutos para la IP pública del equipo de pruebas (sustituye `your_test_ip`): ```bash sudo cscli decisions add --ip your_test_ip --duration 5m --reason "prueba del bouncer" ``` Repite la petición desde el equipo de pruebas. Ahora Nginx devuelve la página de bloqueo de CrowdSec: ```output HTTP/1.1 403 Forbidden ... ``` Elimina la decisión al terminar: ```bash sudo cscli decisions delete --ip your_test_ip ``` > Consejo: el bouncer de Nginx solo protege el tráfico HTTP. Para bloquear también SSH y el resto de puertos, instala el bouncer de firewall con `sudo apt install crowdsec-firewall-bouncer-nftables`, que aplica las mismas decisiones en nftables. ## Parte 2: CrowdSec con Traefik en Docker En esta parte todo se ejecuta con Docker Compose: Traefik v3 escribe su log de acceso en un volumen compartido, un contenedor de CrowdSec lo analiza y el plugin de CrowdSec para Traefik actúa como middleware que consulta la LAPI antes de pasar la petición al servicio. Como servicio de ejemplo se usa `traefik/whoami`. ### Paso 1: Preparar el proyecto Crea el directorio del proyecto: ```bash sudo mkdir -p /opt/traefik-crowdsec/crowdsec sudo chown -R "$USER": /opt/traefik-crowdsec cd /opt/traefik-crowdsec ``` El contenedor de CrowdSec puede registrar un bouncer al arrancar con una clave que tú le pasas, lo que evita tener que copiarla a mano después. Genera una clave aleatoria y guárdala en un archivo `.env`, que Docker Compose lee automáticamente: ```bash echo "CROWDSEC_BOUNCER_KEY=$(openssl rand -hex 32)" > .env chmod 600 .env ``` Crea el archivo de adquisición que indica a CrowdSec qué logs leer: ```bash nano crowdsec/acquis.yaml ``` ```yaml filenames: - /var/log/traefik/access.log labels: type: traefik ``` ### Paso 2: Escribir el archivo de Docker Compose Crea `docker-compose.yml`: ```bash nano docker-compose.yml ``` Sustituye `your_domain` y `admin@your_domain`. La versión del plugin (`v1.4.2` en el ejemplo) debe ser una publicada en el repositorio `maxlerebourg/crowdsec-bouncer-traefik-plugin`; consulta la última en su página de releases: ```yaml services: traefik: image: traefik:v3 restart: unless-stopped command: - --providers.docker=true - --providers.docker.exposedbydefault=false - --entrypoints.web.address=:80 - --entrypoints.web.http.redirections.entrypoint.to=websecure - --entrypoints.web.http.redirections.entrypoint.scheme=https - --entrypoints.websecure.address=:443 - --certificatesresolvers.le.acme.email=admin@your_domain - --certificatesresolvers.le.acme.storage=/letsencrypt/acme.json - --certificatesresolvers.le.acme.httpchallenge.entrypoint=web - --accesslog=true - --accesslog.filepath=/var/log/traefik/access.log - --experimental.plugins.bouncer.modulename=github.com/maxlerebourg/crowdsec-bouncer-traefik-plugin - --experimental.plugins.bouncer.version=v1.4.2 ports: - "80:80" - "443:443" volumes: - /var/run/docker.sock:/var/run/docker.sock:ro - ./letsencrypt:/letsencrypt - traefik-logs:/var/log/traefik labels: - traefik.enable=true - traefik.http.middlewares.crowdsec.plugin.bouncer.enabled=true - traefik.http.middlewares.crowdsec.plugin.bouncer.crowdsecLapiHost=crowdsec:8080 - traefik.http.middlewares.crowdsec.plugin.bouncer.crowdsecLapiKey=${CROWDSEC_BOUNCER_KEY} depends_on: - crowdsec crowdsec: image: crowdsecurity/crowdsec:latest restart: unless-stopped environment: COLLECTIONS: "crowdsecurity/traefik crowdsecurity/http-cve" BOUNCER_KEY_traefik: ${CROWDSEC_BOUNCER_KEY} volumes: - ./crowdsec/acquis.yaml:/etc/crowdsec/acquis.yaml:ro - crowdsec-config:/etc/crowdsec - crowdsec-data:/var/lib/crowdsec/data - traefik-logs:/var/log/traefik:ro whoami: image: traefik/whoami restart: unless-stopped labels: - traefik.enable=true - traefik.http.routers.whoami.rule=Host(`your_domain`) - traefik.http.routers.whoami.entrypoints=websecure - traefik.http.routers.whoami.tls.certresolver=le - traefik.http.routers.whoami.middlewares=crowdsec@docker volumes: traefik-logs: crowdsec-config: crowdsec-data: ``` Puntos clave del archivo: - Las opciones `experimental.plugins.bouncer.*` hacen que Traefik descargue el plugin al arrancar. - Las etiquetas del servicio `traefik` definen el middleware `crowdsec` con la dirección y la clave de la LAPI. - `BOUNCER_KEY_traefik` registra en CrowdSec un bouncer llamado `traefik` con la misma clave. - Cada router que quieras proteger debe incluir `crowdsec@docker` en sus middlewares, como hace `whoami`. ### Paso 3: Arrancar la pila y verificarla Levanta los servicios: ```bash docker compose up -d ``` Comprueba que Traefik ha cargado el plugin sin errores y que CrowdSec ha registrado el bouncer: ```bash docker compose logs traefik | grep -i plugin docker compose exec crowdsec cscli bouncers list ``` El bouncer `traefik` debe aparecer como válido. Desde el equipo de pruebas, abre el sitio: ```bash curl -I https://your_domain ``` ```output HTTP/2 200 ... ``` Tras unas cuantas peticiones, comprueba que CrowdSec lee el log de Traefik: ```bash docker compose exec crowdsec cscli metrics ``` La fuente `file:/var/log/traefik/access.log` debe mostrar líneas leídas y procesadas. ### Paso 4: Probar el bloqueo Crea una decisión para la IP del equipo de pruebas: ```bash docker compose exec crowdsec cscli decisions add --ip your_test_ip --duration 5m --reason "prueba del plugin" ``` Repite la petición desde ese equipo. En modo `live`, el plugin guarda en caché la respuesta de la LAPI durante un tiempo corto, así que el bloqueo puede tardar hasta un minuto en aplicarse: ```output HTTP/2 403 ... ``` Elimina la decisión: ```bash docker compose exec crowdsec cscli decisions delete --ip your_test_ip ``` ## Operación diaria Estos comandos sirven igual en la parte 1 (con `sudo cscli`) y en la parte 2 (con `docker compose exec crowdsec cscli`): ```bash sudo cscli decisions list sudo cscli alerts list --since 24h sudo cscli alerts inspect 12 ``` `decisions list` muestra las IPs bloqueadas ahora mismo por tus escenarios, y `alerts inspect` detalla qué escenario disparó una alerta concreta (sustituye `12` por el ID de la alerta). Para mantener parsers y escenarios al día, actualiza el índice del hub y los elementos instalados: ```bash sudo cscli hub update sudo cscli hub upgrade sudo systemctl reload crowdsec ``` ## Solución de problemas **Las líneas del log aparecen como `Lines unparsed`.** El tipo de la adquisición no coincide con el formato del log. Comprueba que `type` es `nginx` o `traefik` según el caso y que el log usa el formato por defecto; los formatos de log personalizados en Nginx no los reconocen los parsers estándar. **Nginx no arranca tras instalar el bouncer.** Revisa el error con `sudo nginx -t`. Si menciona Lua, comprueba que el módulo está instalado con `dpkg -l libnginx-mod-http-lua` y que no has compilado Nginx por tu cuenta ni usas un paquete de otro repositorio. **El bouncer está registrado pero no bloquea.** Verifica que la decisión existe con `cscli decisions list` y que la IP es la que llega realmente al servidor. Si Nginx o Traefik están detrás de otro proxy o de una CDN, verán la IP del proxy en lugar de la del cliente; en ese caso debes configurar la IP real del cliente (módulo `realip` en Nginx, `forwardedHeaders.trustedIPs` en Traefik) antes de que CrowdSec pueda funcionar. **Una IP legítima termina bloqueada.** Crea una lista blanca como parser de enriquecimiento: ```bash sudo nano /etc/crowdsec/parsers/s02-enrich/mis-ips.yaml ``` ```yaml name: local/mis-ips description: "IPs propias que nunca deben bloquearse" whitelist: reason: "Redes de la oficina" ip: - "198.51.100.20" cidr: - "10.0.0.0/8" ``` Recarga CrowdSec con `sudo systemctl reload crowdsec` y elimina la decisión existente con `sudo cscli decisions delete --ip` seguido de la IP. ## Conclusión Tienes CrowdSec analizando los logs de Nginx o de Traefik, recibiendo la lista comunitaria de IPs maliciosas y un bouncer que bloquea esas IPs antes de que las peticiones lleguen a tus aplicaciones. Como siguientes pasos, puedes añadir el bouncer de firewall para cubrir el resto de puertos, inscribir la instancia en la consola web de CrowdSec con `cscli console enroll` para ver alertas centralizadas y escribir escenarios propios para los endpoints de inicio de sesión de tus aplicaciones.