Blog de Obi Madu
Volver a todos los artículos
SecurityTips & TricksInfrastructure

Añadiendo un WAF gratuito a mi Homebox: Tutorial de CrowdSec AppSec con Traefik y Dokploy

Una guía completa sobre cómo protejo mis aplicaciones de Homebox con el WAF AppSec de CrowdSec, un plugin de Traefik y Dokploy.

Añadiendo un WAF gratuito a mi Homebox: Tutorial de CrowdSec AppSec con Traefik y Dokploy

Mantengo una "Homebox", que en mi caso es un servidor en la nube donde alojo varias aplicaciones personales. Como algunas de estas aplicaciones están expuestas a internet público, y como uso este servidor a menudo como recipiente de despliegue rápido para nuevos proyectos, la seguridad es prioritaria.

Para proteger este setup, añadí recientemente un Web Application Firewall (WAF) usando CrowdSec. CrowdSec es un motor de seguridad open-source y colaborativo. Un WAF es esencial porque proporciona "virtual patching": detiene payloads maliciosos, detiene escáneres automáticos y protege las aplicaciones de CVEs conocidos aunque el código subyacente aún no se haya actualizado.

Mi Homebox se gestiona con Dokploy, una herramienta PaaS que usa Traefik como reverse proxy subyacente. En este tutorial, te guiaré exactamente por cómo integré las capacidades AppSec de CrowdSec directamente en Traefik usando un plugin, creando un WAF gratuito y robusto que protege todos mis despliegues.

(Nota: Aunque este tutorial usa Dokploy para gestionar las configuraciones, los mismos conceptos y archivos de Docker Compose se pueden usar para proteger cualquier entorno estándar de Traefik.)

Cómo funciona la inteligencia de CrowdSec

Un error común es pensar que CrowdSec envía tus logs de tráfico a la nube para analizarlos. Esto es completamente falso.

  1. Local First: CrowdSec construye su inteligencia localmente. El motor corre en tu servidor, detecta ataques localmente y banea localmente. Funciona incluso sin conexión a internet.
  2. Comunidad que preserva la privacidad (Opt-in): Compartir inteligencia con la Comunidad CrowdSec es estrictamente opcional. Si te registras a través de la Consola de CrowdSec, solo comparte señales anonimizadas (como "la IP X intentó un exploit conocido"), nunca logs en bruto, payloads de peticiones o datos sensibles. Te beneficia de las blocklists de la comunidad sin comprometer tu privacidad de datos.

CrowdSec estándar (Capa 4) vs. AppSec (Capa 7)

Antes de entrar en la configuración, es importante entender la diferencia entre el comportamiento estándar de CrowdSec y la nueva función AppSec. Operan en capas completamente distintas del modelo OSI:

  • CrowdSec estándar (Capa 4): Actúa a nivel de red. Analiza logs (como fallos de SSH o inundaciones de HTTP 404) y bloquea malas direcciones IP hablando con un firewall (como iptables). Si una IP está baneada, ni siquiera puede abrir una conexión TCP a tu servidor.
  • CrowdSec AppSec (Capa 7): Actúa como un verdadero WAF a nivel de aplicación. En lugar de solo mirar IPs, inspecciona activamente los payloads HTTP reales, los headers y los parámetros de consulta (como buscar multipart/form-data malicioso específico) para capturar zero-days y exploits de CVE a nivel de aplicación en tiempo real.

Aquí hay una visualización simple de cómo difiere la arquitectura:

┌────────────────────────────────────────────────────────┐
│ STANDARD CROWDSEC (Layer 4 - Network IP Blocking)      │
└────────────────────────────────────────────────────────┘
  Attacker IP ──> [ Firewall / iptables ] ──X (Blocked instantly)

                          │ (Updates ban list)
                    [ CrowdSec Engine ] <── (Reads background logs)
-
-
┌────────────────────────────────────────────────────────┐
│ CROWDSEC APPSEC (Layer 7 - Payload Inspection WAF)     │
└────────────────────────────────────────────────────────┘
  Attacker HTTP Request ──> [ Traefik + Bouncer Plugin ]
                                  │   ▲
                  (Sends payload) │   │ (Returns Allow/Block)
                                  ▼   │
                        [ CrowdSec AppSec Engine ] 
                           (Inspects HTTP body)

Plugins de Traefik y el CrowdSec Bouncer

Traefik es un reverse proxy moderno que enruta el tráfico a mis contenedores Docker. Una de sus mejores características son los Plugins, que te permiten extender la funcionalidad base de Traefik sin necesidad de recompilar el binario.

Para este setup, usamos el plugin CrowdSec Traefik Bouncer. Actúa como puente entre Traefik y el motor AppSec de CrowdSec. Intercepta el tráfico en el edge y pregunta a CrowdSec si un payload de petición es seguro o malicioso antes de permitir que llegue a la aplicación.

iWhat is a CrowdSec bouncer?+

Un bouncer es el componente de enforcement de CrowdSec. El motor de CrowdSec detecta amenazas y crea decisiones; el bouncer aplica esas decisiones donde el tráfico realmente fluye. En este caso, el plugin de Traefik es el bouncer porque vive dentro de Traefik y puede bloquear o permitir peticiones HTTP antes de que lleguen a mis apps.

Guía de implementación paso a paso

Aquí está exactamente cómo configuré esto en mi entorno Dokploy/Traefik.

1. Desplegar el contenedor de CrowdSec

Primero, desplegué el motor de CrowdSec. Usé la imagen oficial de Docker y usé la variable de entorno COLLECTIONS para instalar automáticamente las reglas de AppSec al iniciar.

services:
  crowdsec:
    image: crowdsecurity/crowdsec:latest
    environment:
      GID: "${GID-1000}"
      BOUNCER_KEY_TRAEFIK: "${BOUNCER_KEY_TRAEFIK}"
      COLLECTIONS: "crowdsecurity/linux crowdsecurity/traefik crowdsecurity/http-cve crowdsecurity/appsec-virtual-patching crowdsecurity/appsec-generic-rules"
    volumes:
      - ../files/acquis.yaml:/etc/crowdsec/acquis.yaml
      - crowdsec-db:/var/lib/crowdsec/data/
      - crowdsec-config:/etc/crowdsec/
    security_opt:
      - no-new-privileges:true
    labels:
      - traefik.enable=false
    restart: always
    networks: 
      - dokploy-network

2. La clave LAPI crítica

Nótese la variable BOUNCER_KEY_TRAEFIK arriba. Esta es la clave LAPI (Local API Key), que autentica de forma segura el plugin de Traefik con tu motor de CrowdSec. Sin ella, Traefik no puede comunicarse con CrowdSec.

Cuando se configura a través de esta variable de entorno, el contenedor de CrowdSec no impone un formato estricto de clave. Cualquier cadena que establezcas se convierte en la clave válida. Puedes simplemente generar una cadena aleatoria fuerte de 32 caracteres, asignarla a BOUNCER_KEY_TRAEFIK en tu archivo .env de Docker Compose, y luego introducir esa misma cadena en tu configuración de middleware de Traefik más adelante.

3. Configurar la adquisición (acquis.yaml)

Instalar las colecciones de AppSec no es suficiente; debes decirle explícitamente a CrowdSec que empiece a escuchar tráfico AppSec. Monté este archivo acquis.yaml en el contenedor:

---
source: appsec
listen_addr: 0.0.0.0:7422
path: /
appsec_configs:
  - crowdsecurity/appsec-default
labels:
  type: appsec
iWhat is happening in this file?+

Si eres nuevo en CrowdSec, puedes preguntarte qué hace realmente este archivo acquis.yaml (Adquisición). Por defecto, CrowdSec busca amenazas leyendo archivos de log (como tus logs de Nginx o SSH) después de que ocurran.

Pero un WAF necesita capturar cosas en vivo, antes de que lleguen a tu aplicación. Este archivo le dice a CrowdSec que deje de mirar archivos estáticos y en su lugar lance un listener HTTP activo:

  • source: appsec: Le dice al motor que esperamos tráfico HTTP entrante en vivo.
  • listen_addr: 0.0.0.0:7422: Abre el puerto 7422. Aquí es exactamente donde nuestro plugin de Traefik enviará cada petición HTTP para inspección.
  • appsec_configs: Carga las reglas específicas de AppSec que le dijimos al contenedor que instalara antes.

Sin este archivo, el listener no se iniciará, Traefik no tendrá a dónde enviar las peticiones, ¡y las reglas del WAF nunca se ejecutarán!

4. El middleware de Traefik (middlewares.yaml)

A continuación, configuré el middleware de Traefik usando el editor de sistema de archivos integrado de Dokploy. Esto le dice a Traefik que use el plugin Bouncer y reenvíe las peticiones al motor AppSec de CrowdSec.

http:
  middlewares:
    redirect-to-https:
      redirectScheme:
        scheme: https
        permanent: true
    crowdsec:
      plugin:
        bouncer:
          enabled: true
          logLevel: DEBUG
          crowdsecMode: appsec
          crowdsecLapiKey: keystring # Replace with your LAPI key
          crowdsecLapiScheme: http
          crowdsecLapiHost: crowdsec:8080
          crowdsecAppsecEnabled: true
          crowdsecAppsecHost: crowdsec:7422
          crowdsecAppsecFailureBlock: true
          crowdsecAppsecUnreachableBlock: true

Protección fail-closed

Presta especial atención a crowdsecAppsecFailureBlock: true y crowdsecAppsecUnreachableBlock: true. Estos son críticos para la seguridad. Aseguran una arquitectura "fail-closed". Si el contenedor de CrowdSec cae, o si el motor AppSec devuelve un error 500, Traefik bloqueará la petición entrante por completo en lugar de dejar que rodee el WAF y llegue a tu aplicación.

5. Aplicación global

Finalmente, para asegurar que cada petición que llega a mi servidor sea inspeccionada, enganché el middleware crowdsec directamente a los entrypoints principales de Traefik (web y websecure):

entryPoints:
  web:
    address: :80
    http:
      middlewares:
        - crowdsec@file
  websecure:
    address: :443
    http3:
      advertisedPort: 443
    http:
      tls:
        certResolver: letsencrypt
      middlewares:
        - crowdsec@file

Mantener el WAF actualizado (Automatización)

Instalar un WAF es solo la mitad de la batalla. Las vulnerabilidades se descubren a diario, así que tus reglas necesitan actualizarse constantemente para capturar nuevos CVEs.

Para actualizar CrowdSec, necesitas dos comandos:

  1. cscli hub update (Descarga el último índice de reglas disponibles)
  2. cscli hub upgrade (Aplica las actualizaciones a tus colecciones instaladas)

Automaticé este proceso usando Dokploy Schedules, configurándolo para que se ejecute una vez al día. Las actualizaciones diarias son el punto óptimo: te mantienen protegido de los CVE recién publicados sin causar un uso de recursos excesivo y demasiado granular.

Cómo manejo el reinicio requerido

Una advertencia importante: después de actualizar las reglas, el motor de CrowdSec requiere un reinicio para que las nuevas reglas de AppSec surtan efecto.

En mi setup, mis copias de seguridad rutinarias de contenedores de Dokploy se ejecutan poco después del horario de actualización. Como el proceso de backup detiene el contenedor para respaldar la configuración y luego lo inicia de nuevo, eso se convierte de forma natural en el paso de reinicio que aplica las reglas actualizadas.

Pruebas en el mundo real: Bloqueando CVE-2025-55182

Para verificar el setup, decidí probarlo contra un exploit muy real y muy peligroso: CVE-2025-55182 (una vulnerabilidad de Prototype Pollution de Next.js que conduce a Remote Code Execution).

Usé una herramienta open-source de exploit (rix4uni/CVE-2025-55182) y la disparé directamente contra un dominio alojado en mi Homebox protegida.

1. El intento de exploit falló

Al ejecutar la herramienta de línea de comandos, cada intento de payload falló al ejecutarse contra el servidor. La herramienta no pudo rodear el edge.

2. Los logs de CrowdSec

Mirando los logs del contenedor de CrowdSec, pude ver exactamente qué pasó. CrowdSec denegó activamente el intento de exploit, reconociendo el payload malicioso en tiempo real.

3. Análisis de logs

Para confirmar, pasé los logs en bruto por un resumen con IA, que verificó que las reglas AppSec de CrowdSec capturaron y descartaron con éxito el payload RCE de Next.js antes de que tocara el contenedor de mi aplicación.

Conclusión

Combinando Traefik, Dokploy y CrowdSec AppSec, pude desplegar un Web Application Firewall capaz y gratuito en mi Homebox en la nube. Mis aplicaciones personales y mis despliegues rápidos ahora están protegidos de exploits automáticos y activos desde el momento en que tocan el edge.

Si haces self-hosting o mantienes un servidor personal, recomiendo adoptar una arquitectura WAF similar a nivel de edge.