--- title: "Reglas y decodificadores personalizados en Wazuh 4" description: "Crea decodificadores y reglas propias en Wazuh 4, pruébalos con wazuh-logtest, correlaciona eventos, bloquea IPs con respuesta activa y reduce falsos positivos." category: "Herramientas de Seguridad" language: es source: https://cubepath.com/es/docs/herramientas-de-seguridad/configuracion-avanzada-de-reglas-wazuh-siem updated: 2026-09-25 --- # Reglas y decodificadores personalizados en Wazuh 4 Wazuh analiza los logs que envían sus agentes en dos fases: los **decodificadores** extraen campos (usuario, IP de origen, acción) y las **reglas** deciden si ese evento genera una alerta y con qué nivel. Las reglas incluidas cubren SSH, sudo, servidores web y mucho más, pero tus aplicaciones internas necesitan las suyas. En este tutorial crearás un decodificador y varias reglas para una aplicación propia, las probarás con `wazuh-logtest`, correlacionarás intentos repetidos, bloquearás la IP atacante con respuesta activa y aprenderás a silenciar falsos positivos sin tocar las reglas originales. ## Requisitos previos - Un servidor Wazuh 4.x (manager, indexer y dashboard) funcionando. Los comandos usan las rutas estándar de `/var/ossec`. - Al menos un agente Linux (por ejemplo Ubuntu 24.04 en un VPS de CubePath) registrado y conectado al manager. - Acceso `sudo` en el manager y en el agente. - Nociones básicas de XML. Comprueba la versión del manager y que el agente está activo: ```bash sudo /var/ossec/bin/wazuh-control info sudo /var/ossec/bin/agent_control -l ``` ```output WAZUH_VERSION="v4.x.x" WAZUH_REVISION="..." WAZUH_TYPE="server" Wazuh agent_control. List of available agents: ID: 000, Name: wazuh-manager (server), IP: 127.0.0.1, Active/Local ID: 001, Name: web01, IP: any, Active ``` ## Dónde van tus reglas y decodificadores Nunca edites los ficheros de `/var/ossec/ruleset/`: las actualizaciones de Wazuh los sobrescriben. Lo tuyo va en: | Fichero | Contenido | |---|---| | `/var/ossec/etc/decoders/local_decoder.xml` | Decodificadores propios | | `/var/ossec/etc/rules/local_rules.xml` | Reglas propias | | `/var/ossec/etc/lists/` | Listas CDB (IPs, usuarios) | Usa identificadores de regla entre **100000 y 120000**, el rango reservado para reglas de usuario. El ejemplo de esta guía es una aplicación llamada `miapp` que escribe líneas como esta en `/var/log/miapp/app.log`: ```text Sep 25 10:30:45 web01 miapp[2154]: login failed user=admin src=203.0.113.10 ``` ## Paso 1: Crear el decodificador El predecodificador de Wazuh ya separa la fecha, el host y el nombre del programa (`miapp`) de las líneas con formato syslog. Tu decodificador solo tiene que reconocer el programa y extraer el usuario y la IP. En el **manager**, abre el fichero de decodificadores locales: ```bash sudo nano /var/ossec/etc/decoders/local_decoder.xml ``` Añade al final: ```xml ^miapp$ miapp ^login (\w+) user=(\S+) src=(\S+)$ action, srcuser, srcip ``` El decodificador padre selecciona los eventos de `miapp`; el hijo extrae tres campos. `srcip` y `srcuser` son nombres estándar de Wazuh, lo que permite usarlos luego en correlación y en respuesta activa. Las expresiones de `` usan la sintaxis propia de Wazuh (OS_Regex), que admite `\w`, `\S`, `\d`, `+` y `*`, pero no cuantificadores como `{4}`. ## Paso 2: Crear las reglas Abre el fichero de reglas locales: ```bash sudo nano /var/ossec/etc/rules/local_rules.xml ``` Añade un grupo nuevo con tres reglas encadenadas: ```xml miapp miapp: evento 100100 ^failed$ miapp: login fallido de $(srcuser) desde $(srcip) authentication_failed, 100101 miapp: posible fuerza bruta desde $(srcip) T1110 authentication_failures, ``` - `decoded_as` enlaza con el nombre del decodificador padre. - `if_sid` hace que la regla 100101 solo se evalúe si antes coincidió la 100100. - `frequency`, `timeframe`, `if_matched_sid` y `same_srcip` convierten eventos sueltos en una alerta de correlación. - `$(srcip)` inserta el valor del campo en la descripción de la alerta. Comprueba que la configuración carga sin errores: ```bash sudo /var/ossec/bin/wazuh-analysisd -t ``` Si termina sin mensajes de `ERROR` ni `CRITICAL`, la configuración es correcta. Un error de XML indicará el fichero y la línea. ## Paso 3: Probar con wazuh-logtest `wazuh-logtest` pasa una línea de log por el mismo motor que usa el manager y muestra cada fase, sin necesidad de generar eventos reales: ```bash sudo /var/ossec/bin/wazuh-logtest ``` Pega la línea de ejemplo y pulsa Intro: ```text Sep 25 10:30:45 web01 miapp[2154]: login failed user=admin src=203.0.113.10 ``` ```output **Phase 1: Completed pre-decoding. full event: 'Sep 25 10:30:45 web01 miapp[2154]: login failed user=admin src=203.0.113.10' timestamp: 'Sep 25 10:30:45' hostname: 'web01' program_name: 'miapp' **Phase 2: Completed decoding. name: 'miapp' action: 'failed' srcip: '203.0.113.10' srcuser: 'admin' **Phase 3: Completed filtering (rules). id: '100101' level: '5' description: 'miapp: login fallido de admin desde 203.0.113.10' groups: '['miapp', 'authentication_failed']' firedtimes: '1' mail: 'False' **Alert to be generated. ``` Pega la misma línea seis veces seguidas: la última debe disparar la regla `100102` con nivel 10. Sal con `Ctrl+C`. Si la fase 2 no muestra tus campos, el problema está en el decodificador; si la fase 3 muestra otra regla, revisa `if_sid` y `field`. Cuando todo cuadre, reinicia el manager para cargar las reglas: ```bash sudo systemctl restart wazuh-manager ``` ## Paso 4: Recoger el log en el agente En el **agente**, indica a Wazuh qué fichero debe leer. Edita su configuración: ```bash sudo nano /var/ossec/etc/ossec.conf ``` Añade este bloque dentro de ``: ```xml syslog /var/log/miapp/app.log ``` ```bash sudo systemctl restart wazuh-agent ``` Genera un evento de prueba en el agente: ```bash sudo mkdir -p /var/log/miapp echo "$(date '+%b %e %H:%M:%S') $(hostname) miapp[2154]: login failed user=admin src=203.0.113.10" | sudo tee -a /var/log/miapp/app.log ``` En el **manager**, busca la alerta: ```bash sudo grep '"id":"100101"' /var/ossec/logs/alerts/alerts.json | tail -n 1 ``` La alerta también aparece en el dashboard, en **Threat Hunting**, filtrando por `rule.id: 100101`. ## Paso 5: Bloquear la IP con respuesta activa La respuesta activa ejecuta un script en el agente cuando salta una regla. Wazuh incluye `firewall-drop`, que bloquea la IP de origen con iptables durante el tiempo indicado. El comando ya está definido en el `ossec.conf` del manager; solo falta asociarlo a tu regla. En el **manager**: ```bash sudo nano /var/ossec/etc/ossec.conf ``` Añade dentro de ``: ```xml firewall-drop local 100102 600 ``` `location` en `local` ejecuta la acción en el agente que generó el evento y `timeout` deshace el bloqueo a los 10 minutos. La regla necesita un campo `srcip`, por eso era importante extraerlo en el decodificador. Protege las IPs de administración para que nunca se bloqueen. En el mismo fichero, dentro del bloque `` que ya existe, añade una línea por IP: ```xml 198.51.100.20 ``` ```bash sudo /var/ossec/bin/wazuh-analysisd -t && sudo systemctl restart wazuh-manager ``` Prueba el bloqueo escribiendo seis fallos seguidos en el agente (usa una IP de documentación, no la tuya): ```bash for i in 1 2 3 4 5 6; do echo "$(date '+%b %e %H:%M:%S') $(hostname) miapp[2154]: login failed user=admin src=203.0.113.10" | sudo tee -a /var/log/miapp/app.log > /dev/null done ``` En el agente, comprueba el registro de respuesta activa y la regla del firewall: ```bash sudo tail -n 3 /var/ossec/logs/active-responses.log sudo iptables -S INPUT | grep 203.0.113.10 ``` ```output -A INPUT -s 203.0.113.10/32 -j DROP ``` ## Paso 6: Reducir falsos positivos con listas CDB Una regla hija de nivel 0 anula la alerta de su regla padre cuando se cumple una condición. Combinada con una lista CDB, permite silenciar, por ejemplo, los fallos de SSH que vienen del servidor de monitorización sin modificar el ruleset. En el **manager**, crea la lista con una IP por línea en formato `clave:valor`: ```bash sudo nano /var/ossec/etc/lists/ips-confianza ``` ```text 198.51.100.20:monitorizacion 198.51.100.21:bastion ``` Asigna la propiedad correcta y declara la lista en el bloque `` de `/var/ossec/etc/ossec.conf`: ```bash sudo chown wazuh:wazuh /var/ossec/etc/lists/ips-confianza sudo nano /var/ossec/etc/ossec.conf ``` ```xml etc/lists/ips-confianza ``` Añade la regla que silencia los intentos de usuario inexistente por SSH (regla 5710) desde esas IPs en `local_rules.xml`, dentro de un grupo: ```xml 5710 etc/lists/ips-confianza sshd: usuario inexistente desde IP de confianza (silenciado) ``` El manager compila las listas al reiniciarse: ```bash sudo /var/ossec/bin/wazuh-analysisd -t && sudo systemctl restart wazuh-manager ``` Verifícalo en `wazuh-logtest` con una línea de sshd: ```text Sep 25 11:02:10 web01 sshd[3321]: Invalid user test from 198.51.100.20 port 52144 ``` La fase 3 debe mostrar `id: '100200'` y `level: '0'`, sin `Alert to be generated`. Con otra IP de origen seguirá saltando la regla 5710. ## Paso 7: Vigilar ficheros críticos en tiempo real El módulo de integridad de ficheros (FIM, `syscheck`) compara hashes y permisos. Por defecto escanea cada 12 horas; con `realtime` avisa en segundos. En el **agente**, dentro del bloque `` de `/var/ossec/etc/ossec.conf`, añade: ```xml /etc/ssh /var/www/html ``` `report_changes` guarda un diff del contenido en la alerta; úsalo solo en ficheros de texto pequeños, nunca en directorios con secretos. Reinicia y provoca un cambio: ```bash sudo systemctl restart wazuh-agent echo "" | sudo tee -a /var/www/html/index.html ``` En el manager, las modificaciones generan la regla 550 (checksum cambiado) y los ficheros nuevos la 554: ```bash sudo grep '"id":"550"' /var/ossec/logs/alerts/alerts.json | tail -n 1 ``` ## Solución de problemas **`wazuh-analysisd -t` falla con un error de XML.** Suele ser un `<` o `&` sin escapar dentro de `` o ``. Escríbelos como `<` y `&`. **La regla funciona en wazuh-logtest pero no llega ninguna alerta.** Revisa que el agente lee el fichero (`sudo grep miapp /var/ossec/logs/ossec.log` en el agente debe mostrar `Analyzing file: '/var/log/miapp/app.log'`) y que las líneas tienen el mismo formato que la de prueba. **La respuesta activa no bloquea.** Comprueba que la alerta contiene `srcip`, que la IP no está en `` y revisa `/var/ossec/logs/active-responses.log` en el agente. **Demasiadas alertas de FIM.** Excluye rutas ruidosas con `/ruta` dentro de `` o crea una regla hija de nivel 0 sobre la 550 para esa ruta. ## Conclusión Has creado un decodificador y reglas propias, las has validado con `wazuh-logtest`, has convertido fallos sueltos en una alerta de fuerza bruta con bloqueo automático y has silenciado ruido con una lista CDB. El siguiente paso lógico es escribir reglas para el resto de tus aplicaciones, revisar cada semana las reglas que más alertas generan para ajustarlas y enviar las alertas de nivel alto a tu canal de incidentes con las integraciones de Wazuh.