¡Monta tu propio SIEM gratis! 🛡️ Wazuh en Docker paso a paso (Tutorial Homelab) | Cómo instalar Wazuh en Docker

Wazuh | SIEM | Detección de intrusiones | Docker Compose | Self-hosted | GPL-2.0

Wazuh en Docker Compose: tu SIEM autohospedado, paso a paso

Wazuh centraliza los registros de tus equipos, detecta intrusiones, vigila cambios en ficheros y localiza vulnerabilidades. Esta guía despliega la versión 4.14.7 con Docker Compose en un solo nodo, con certificados propios y contraseñas cambiadas desde el primer momento.

Vídeo tutorial en YouTube

Mira el vídeo completo sobre cómo instalar Wazuh en Docker en el canal GENBYTE:

¿Qué es Wazuh?

Wazuh es una plataforma de seguridad de código abierto que combina SIEM y detección de intrusiones. Tiene tres componentes: el manager, que recibe los datos de los agentes y genera alertas; el indexer, basado en OpenSearch, que guarda y busca los eventos; y el dashboard, la interfaz web.

Idea clave: el stack de Docker es el servidor. Los agentes se instalan en los equipos que quieres vigilar y se conectan a él por los puertos 1514 y 1515.

Características principales

Un solo compose

Manager, indexer y dashboard en un único docker-compose.yml, ideal para empezar.

Certificados propios

Un contenedor generador emite la CA y los certificados de cada componente.

Agentes en contenedor

El repositorio incluye un compose para el agente, además de la instalación con paquete.

Versiones fijadas

Las imágenes llevan la etiqueta 4.14.7, y el repositorio tiene esa versión como etiqueta Git.

Requisitos del sistema

  • RAM: el artículo en el que se basa esta guía recomienda 6 GB como mínimo para que el indexer funcione con holgura
  • CPU: 4 núcleos recomendados
  • Disco: 50 GB libres como mínimo, y SSD si puedes
  • Docker Engine y el plugin de Docker Compose, con Git instalado
  • Puertos libres en el host: 443 para el dashboard, 1514, 1515 y 514/udp para agentes, 55000 para la API y 9200 para el indexer
Puerto 9200: el compose oficial publica el indexer en el host. Si no necesitas acceder a él desde fuera, quita ese mapeo y déjalo solo en la red interna de Docker.

Instalación paso a paso

Paso 1: ajusta vm.max_map_count

El indexer no arranca con el valor por defecto de la mayoría de sistemas Linux. Aplícalo ahora y hazlo permanente, porque si solo lo cambias con sysctl -w, se pierde al reiniciar:

# Aplicar ahora sudo sysctl -w vm.max_map_count=262144 # Hacerlo permanente echo "vm.max_map_count=262144" | sudo tee -a /etc/sysctl.conf sudo sysctl -p

Paso 2: clona la etiqueta v4.14.7

Usa la etiqueta de la versión, no la rama principal, que es la de desarrollo de la 5.x:

git clone https://github.com/wazuh/wazuh-docker.git -b v4.14.7 cd wazuh-docker/single-node/

Paso 3: genera los certificados

El generador lee config/certs.yml, que ya viene en el repositorio, y escribe los certificados en config/wazuh_indexer_ssl_certs/:

docker compose -f generate-indexer-certs.yml run --rm generator ls -l config/wazuh_indexer_ssl_certs/

Debes ver los certificados del indexer, del manager, del dashboard y la autoridad. Si la carpeta está vacía, no sigas: el stack no arrancará con certificados ausentes.

Paso 4: cambia las contraseñas por defecto

Las contraseñas del compose son públicas. El fichero del repositorio trae SecretPassword, kibanaserver y MyS3cr37P450r.*-. Un SIEM con contraseñas de ejemplo concentra los registros de tus servidores en un punto que cualquiera puede abrir. Cámbialas antes de arrancar.

4a. Genera el hash de la contraseña de admin. El indexer guarda las contraseñas como hash bcrypt. La ruta viene del artículo original. El repositorio usa la misma carpeta de herramientas para securityadmin.sh, pero no he podido ejecutar la imagen para comprobar que hash.sh está ahí:

docker run --rm -ti wazuh/wazuh-indexer:4.14.7 \ bash /usr/share/wazuh-indexer/plugins/opensearch-security/tools/hash.sh \ -p 'TuContrasenaLargaYUnica'

4b. Pon el hash en config/wazuh_indexer/internal_users.yml. Hay que cambiarlo en dos usuarios, no solo en admin:

  • admin: el hash que acabas de generar con tu contraseña de INDEXER_PASSWORD.
  • kibanaserver: un hash generado con la contraseña que pondrás en DASHBOARD_PASSWORD. Es el usuario con el que el dashboard se conecta al indexer; si no coincide, el dashboard no puede entrar.

4c. Pon las mismas contraseñas en docker-compose.yml, en claro, en los servicios que las usan: INDEXER_PASSWORD aparece en el manager y en el dashboard, API_PASSWORD también en ambos, y DASHBOARD_PASSWORD en el dashboard.

Comprobación: el valor de API_PASSWORD lo usan el manager y el dashboard para el usuario wazuh-wui, que no aparece en internal_users.yml. El repositorio no documenta cómo se crea ese usuario, así que cuando arranques, comprueba que el dashboard conecta con la API.

Paso 5: levanta el stack

docker compose up -d docker compose ps docker compose logs -f wazuh.indexer

El primer arranque tarda varios minutos, porque el indexer crea sus índices. Ten paciencia antes de dar la instalación por fallida.

Si cambiaste las contraseñas después de un primer arranque: no lo he comprobado en esta versión. Los cambios en internal_users.yml pueden no aplicarse si el indexer ya inicializó su índice de seguridad. Si pasa, la forma segura de empezar de cero es parar el stack, borrar el volumen wazuh-indexer-data y volver a arrancar, porque perderás los datos indexados.

Paso 6: entra en el dashboard

Abre https://IP_DEL_SERVIDOR. El compose publica el dashboard en el 443 del host, aunque dentro del contenedor escuche en el 5601. El certificado es de tu propia CA, así que el navegador avisará:

# Usuario: admin # Contraseña: la que pusiste en INDEXER_PASSWORD

docker-compose.yml de single-node (v4.14.7)

Este es el fichero del repositorio en la etiqueta v4.14.7. Las contraseñas aparecen con marcadores CAMBIA_...; sustitúyelos por las tuyas como en el paso 4:

# Wazuh App Copyright (C) 2017, Wazuh Inc. (License GPLv2) services: wazuh.manager: image: wazuh/wazuh-manager:4.14.7 hostname: wazuh.manager restart: always ulimits: memlock: soft: -1 hard: -1 nofile: soft: 655360 hard: 655360 ports: - "1514:1514" - "1515:1515" - "514:514/udp" - "55000:55000" environment: - INDEXER_URL="https://wazuh.indexer:9200" - INDEXER_USERNAME=admin - INDEXER_PASSWORD=CAMBIA_INDEXER - FILEBEAT_SSL_VERIFICATION_MODE=full - SSL_CERTIFICATE_AUTHORITIES=/etc/ssl/root-ca.pem - SSL_CERTIFICATE=/etc/ssl/filebeat.pem - SSL_KEY=/etc/ssl/filebeat.key - API_USERNAME=wazuh-wui - API_PASSWORD=CAMBIA_API volumes: - wazuh_api_configuration:/var/ossec/api/configuration - wazuh_etc:/var/ossec/etc - wazuh_logs:/var/ossec/logs - wazuh_queue:/var/ossec/queue - wazuh_var_multigroups:/var/ossec/var/multigroups - wazuh_integrations:/var/ossec/integrations - wazuh_active_response:/var/ossec/active-response/bin - wazuh_agentless:/var/ossec/agentless - wazuh_wodles:/var/ossec/wodles - filebeat_etc:/etc/filebeat - filebeat_var:/var/lib/filebeat - ./config/wazuh_indexer_ssl_certs/root-ca-manager.pem:/etc/ssl/root-ca.pem - ./config/wazuh_indexer_ssl_certs/wazuh.manager.pem:/etc/ssl/filebeat.pem - ./config/wazuh_indexer_ssl_certs/wazuh.manager-key.pem:/etc/ssl/filebeat.key - ./config/wazuh_cluster/wazuh_manager.conf:/wazuh-config-mount/etc/ossec.conf wazuh.indexer: image: wazuh/wazuh-indexer:4.14.7 hostname: wazuh.indexer restart: always ports: - "9200:9200" environment: - OPENSEARCH_JAVA_OPTS=-Xms1g -Xmx1g ulimits: memlock: soft: -1 hard: -1 nofile: soft: 65536 hard: 65536 volumes: - wazuh-indexer-data:/var/lib/wazuh-indexer - ./config/wazuh_indexer_ssl_certs/root-ca.pem:/usr/share/wazuh-indexer/config/certs/root-ca.pem - ./config/wazuh_indexer_ssl_certs/wazuh.indexer-key.pem:/usr/share/wazuh-indexer/config/certs/wazuh.indexer.key - ./config/wazuh_indexer_ssl_certs/wazuh.indexer.pem:/usr/share/wazuh-indexer/config/certs/wazuh.indexer.pem - ./config/wazuh_indexer_ssl_certs/admin.pem:/usr/share/wazuh-indexer/config/certs/admin.pem - ./config/wazuh_indexer_ssl_certs/admin-key.pem:/usr/share/wazuh-indexer/config/certs/admin-key.pem - ./config/wazuh_indexer/wazuh.indexer.yml:/usr/share/wazuh-indexer/config/opensearch.yml - ./config/wazuh_indexer/internal_users.yml:/usr/share/wazuh-indexer/config/opensearch-security/internal_users.yml wazuh.dashboard: image: wazuh/wazuh-dashboard:4.14.7 hostname: wazuh.dashboard restart: always ports: - 443:5601 environment: - INDEXER_USERNAME=admin - INDEXER_PASSWORD=CAMBIA_INDEXER - WAZUH_API_URL=https://wazuh.manager - DASHBOARD_USERNAME=kibanaserver - DASHBOARD_PASSWORD=CAMBIA_DASHBOARD - API_USERNAME=wazuh-wui - API_PASSWORD=CAMBIA_API volumes: - ./config/wazuh_indexer_ssl_certs/wazuh.dashboard.pem:/usr/share/wazuh-dashboard/certs/wazuh-dashboard.pem - ./config/wazuh_indexer_ssl_certs/wazuh.dashboard-key.pem:/usr/share/wazuh-dashboard/certs/wazuh-dashboard-key.pem - ./config/wazuh_indexer_ssl_certs/root-ca.pem:/usr/share/wazuh-dashboard/certs/root-ca.pem - ./config/wazuh_dashboard/opensearch_dashboards.yml:/usr/share/wazuh-dashboard/config/opensearch_dashboards.yml - ./config/wazuh_dashboard/wazuh.yml:/usr/share/wazuh-dashboard/data/wazuh/config/wazuh.yml - wazuh-dashboard-config:/usr/share/wazuh-dashboard/data/wazuh/config - wazuh-dashboard-custom:/usr/share/wazuh-dashboard/plugins/wazuh/public/assets/custom depends_on: - wazuh.indexer links: - wazuh.indexer:wazuh.indexer - wazuh.manager:wazuh.manager volumes: wazuh_api_configuration: wazuh_etc: wazuh_logs: wazuh_queue: wazuh_var_multigroups: wazuh_integrations: wazuh_active_response: wazuh_agentless: wazuh_wodles: filebeat_etc: filebeat_var: wazuh-indexer-data: wazuh-dashboard-config: wazuh-dashboard-custom:
Sobre los volúmenes: el compose oficial usa volúmenes Docker para los datos de Wazuh, y lo dejamos así porque es lo que mantiene el proyecto. Los certificados y la configuración sí están en carpetas del host (./config).

Conectar un agente

El repositorio trae un compose para ejecutar el agente en contenedor. Está en wazuh-docker/wazuh-agent/, y solo necesitas indicarle la IP del manager:

# Dentro de wazuh-docker/wazuh-agent/docker-compose.yml, cambia el placeholder: WAZUH_MANAGER_SERVER=IP_DE_TU_MANAGER docker compose up -d

El agente en contenedor vigila lo que monte dentro. Para vigilar equipos reales, lo normal es instalar el agente como paquete en cada máquina. El artículo en el que se basa esta guía lo instala con el paquete .deb; esa ruta no la he podido verificar desde aquí, así que compruébala contra la documentación oficial de agentes antes de usarla.

Dirección del manager: la IP que pongas debe ser la del host de Docker, accesible desde el agente. Y los puertos 1514 y 1515 tienen que estar abiertos en el cortafuegos del servidor.

Gestión y mantenimiento

Ver estado y logs

docker compose ps docker compose logs -f wazuh.manager

Consultar la contraseña configurada

# Lee la contraseña en claro desde el fichero de variables que usa el compose grep INDEXER_PASSWORD docker-compose.yml

Detener el stack

docker compose down
Copias de seguridad: guarda la carpeta config/ (certificados, internal_users.yml y tu compose con las contraseñas) y los volúmenes de datos. Sin los certificados no puedes restaurar la instalación.

Stack técnico

  • Manager: wazuh/wazuh-manager:4.14.7, con Filebeat para enviar los eventos al indexer
  • Indexer: wazuh/wazuh-indexer:4.14.7, basado en OpenSearch
  • Dashboard: wazuh/wazuh-dashboard:4.14.7, en el 443 del host
  • Generador de certificados: wazuh/wazuh-certs-generator:0.0.4
  • Licencia: GPLv2

Comentarios

Entradas populares de este blog

Solución al error: «user is not in the sudoers file» en Debian

NAS SYNOLOGY DSM 7.1 en VMware ESXI - Guía instalación y configuración Synology DSM 7.1 en VMWARE

Multisesión RDP en Windows 10 Pro