- Un VPS Ubuntu 24.04 LTS con 8 vCPU, 16 GB RAM, 100 GB SSD (mínimo)
- Acceso SSH root y un FQDN apuntando al VPS (ej: soc.example.com)
- Conocimientos básicos de Docker Compose y Linux
- Tiempo: 4 horas reales (no incluye descarga de imágenes)
Esta guía monta un SOC casero completo sobre un único VPS: detección con Wazuh, gestión de casos con TheHive, threat intelligence con MISP y enriquecimiento automático con Cortex. Es la combinación open source más adoptada del ecosistema y suficiente para cubrir el SOC de una pyme, un homelab o un blue team de competición CTF.
Al final tendrás un pipeline funcional: una alerta de Wazuh dispara un caso en TheHive, Cortex enriquece los observables contra MISP + VirusTotal, y un analyzer de tu elección puede ejecutar respuesta automática (bloquear IP, aislar endpoint).
El despliegue está pensado para laboratorio o pyme — para producción enterprise hace falta separar componentes en máquinas dedicadas y endurecer HTTPS, RBAC y backups.
Pasos a seguir
Provisiona y endurece el VPS
Provisiona un Ubuntu 24.04 LTS con las especificaciones mínimas:
# Actualiza y reinicia con kernel nuevo
sudo apt update && sudo apt -y full-upgrade && sudo reboot
# Crea usuario no-root con sudo y bloquea login root SSH
sudo adduser soc && sudo usermod -aG sudo soc
sudo sed -i 's/^#\?PermitRootLogin.*/PermitRootLogin no/' /etc/ssh/sshd_config
sudo systemctl reload ssh
# Firewall: solo SSH + HTTPS + puertos de agentes Wazuh
sudo ufw default deny incoming
sudo ufw allow OpenSSH
sudo ufw allow 443/tcp comment 'HTTPS reverse proxy'
sudo ufw allow 1514/udp comment 'Wazuh agents'
sudo ufw allow 1515/tcp comment 'Wazuh enrollment'
sudo ufw enable
Verifica que el FQDN resuelve correctamente:
dig +short soc.example.com
# Debe devolver la IP pública del VPS
Instala Docker y prepara la red
Wazuh, TheHive, MISP y Cortex se ejecutarán como contenedores Docker conectados por una red interna compartida.
# Docker Engine oficial
curl -fsSL https://get.docker.com | sudo sh
sudo usermod -aG docker soc
newgrp docker
# Verifica versión
docker --version # >= 26.x
docker compose version # >= v2.30
Crea una red Docker para que los servicios se comuniquen por nombre:
docker network create --driver bridge soc-net
mkdir -p ~/soc/{wazuh,thehive,cortex,misp,traefik}
cd ~/soc
También subimos los límites del sistema que Wazuh y Elasticsearch necesitan:
echo 'vm.max_map_count=262144' | sudo tee /etc/sysctl.d/wazuh.conf
sudo sysctl --system
Despliega Wazuh all-in-one con Docker Compose
Clona el repo oficial y despliega la versión single-node (válida para laboratorio y pymes pequeñas):
cd ~/soc/wazuh
git clone https://github.com/wazuh/wazuh-docker.git -b v4.9.0 .
cd single-node
# Genera certificados internos
docker compose -f generate-indexer-certs.yml run --rm generator
# Cambia las contraseñas por defecto
sed -i 's/SecretPassword/Soc-Wazuh-2026!/' docker-compose.yml
# Arranca
docker compose up -d
Tras 3-5 minutos el dashboard estará en https://<vps>:443 (puerto interno mapeado a 5601). Lo expondrás con Traefik más adelante, en el paso 6.
Despliega MISP con su Docker Compose oficial
MISP gestiona threat intelligence — feeds, IOCs y sharing entre organizaciones.
cd ~/soc/misp
git clone https://github.com/MISP/misp-docker.git .
cp template.env .env
# Edita .env con tu dominio y contraseñas
sed -i 's/^BASE_URL=.*/BASE_URL=https:\/\/misp.soc.example.com/' .env
sed -i 's/^MYSQL_PASSWORD=.*/MYSQL_PASSWORD=Soc-Misp-2026!/' .env
sed -i 's/^MYSQL_ROOT_PASSWORD=.*/MYSQL_ROOT_PASSWORD=Soc-MispRoot-2026!/' .env
# Conecta a la red común
echo 'networks:' >> docker-compose.override.yml
echo ' default:' >> docker-compose.override.yml
echo ' name: soc-net' >> docker-compose.override.yml
echo ' external: true' >> docker-compose.override.yml
docker compose up -d
Usuario inicial admin: admin@admin.test / admin — cámbialo de inmediato tras el primer login.
Despliega TheHive 5 + Cortex
TheHive gestiona casos; Cortex ejecuta analyzers (VirusTotal, MISP lookup, AbuseIPDB, etc.).
cd ~/soc/thehive
cat > docker-compose.yml <<'EOF'
services:
cassandra:
image: cassandra:4
environment:
- CASSANDRA_CLUSTER_NAME=thp
volumes: ["cassandra-data:/var/lib/cassandra"]
networks: [soc-net]
elasticsearch:
image: elasticsearch:7.17.27
environment:
- discovery.type=single-node
- xpack.security.enabled=false
volumes: ["es-data:/usr/share/elasticsearch/data"]
networks: [soc-net]
cortex:
image: thehiveproject/cortex:3.1.7
depends_on: [elasticsearch]
networks: [soc-net]
thehive:
image: strangebee/thehive:5
depends_on: [cassandra, elasticsearch]
command: --no-config
networks: [soc-net]
volumes:
cassandra-data:
es-data:
networks:
soc-net:
external: true
EOF
docker compose up -d
Configura Traefik como reverse proxy con HTTPS
Traefik enruta wazuh.soc.example.com, misp.soc.example.com y thehive.soc.example.com con certificados Let's Encrypt automáticos.
# ~/soc/traefik/docker-compose.yml
services:
traefik:
image: traefik:v3.2
command:
- --providers.docker=true
- --providers.docker.network=soc-net
- --entrypoints.web.address=:80
- --entrypoints.web.http.redirections.entrypoint.to=websecure
- --entrypoints.websecure.address=:443
- --certificatesresolvers.le.acme.email=admin@example.com
- --certificatesresolvers.le.acme.storage=/letsencrypt/acme.json
- --certificatesresolvers.le.acme.httpchallenge.entrypoint=web
ports: ["80:80", "443:443"]
volumes:
- /var/run/docker.sock:/var/run/docker.sock:ro
- ./letsencrypt:/letsencrypt
networks: [soc-net]
networks:
soc-net:
external: true
Añade labels a cada servicio para que Traefik los enrute (ejemplo TheHive):
thehive:
labels:
- traefik.enable=true
- traefik.http.routers.thehive.rule=Host(`thehive.soc.example.com`)
- traefik.http.routers.thehive.entrypoints=websecure
- traefik.http.routers.thehive.tls.certresolver=le
- traefik.http.services.thehive.loadbalancer.server.port=9000
Integra Wazuh con TheHive y MISP
Esta es la pieza que convierte tres herramientas independientes en un SOC real.
Wazuh → TheHive (creación automática de casos)
En el manager de Wazuh, añade el integrator de TheHive editando /var/ossec/etc/ossec.conf:
<integration>
<name>custom-thehive</name>
<hook_url>https://thehive.soc.example.com/api/alert</hook_url>
<api_key>{{API_KEY_THEHIVE}}</api_key>
<alert_format>json</alert_format>
<level>10</level>
</integration>
Crea el script /var/ossec/integrations/custom-thehive.py (ejemplo en la doc de Wazuh-TheHive) que transforma la alerta JSON de Wazuh en un Alert de TheHive vía REST.
Cortex → MISP (enriquecimiento)
En Cortex (https://cortex.soc.example.com), añade el analyzer MISP_2_0, configura url=https://misp.soc.example.com, key=<API_KEY_MISP> y cert_check=true. A partir de aquí, cada observable de TheHive se enriquece con búsquedas en tu instancia MISP.
Despliega tu primer agente Wazuh y dispara una alerta de prueba
Para ver el pipeline completo en acción, despliega un agente en tu laptop o en otra VM:
curl -so wazuh-agent.deb https://packages.wazuh.com/4.x/apt/pool/main/w/wazuh-agent/wazuh-agent_4.9.0-1_amd64.deb
sudo WAZUH_MANAGER='soc.example.com' dpkg -i wazuh-agent.deb
sudo systemctl enable --now wazuh-agent
Genera una alerta artificial intentando un login SSH fallido 6 veces seguidas desde otra IP. La regla 5712 de Wazuh disparará una alerta de severidad 10, el integrator creará un Alert en TheHive y el analyzer MISP buscará la IP en feeds.
Tiempo total esperado de la cadena: menos de 30 segundos.
Tips y mejores prácticas
- Haz **snapshots del VPS** después de cada paso. Si rompes algo, vuelves en 1 minuto.
- Usa una **contraseña fuerte por servicio** y guárdalas en un password manager. Nunca reutilices.
- Configura **MFA TOTP** en TheHive y MISP desde el primer día — los dos lo soportan nativo.
- Para producción, mueve **Cassandra y Elasticsearch a discos NVMe dedicados**. Son la principal fuente de latencia.
- Suscríbete a feeds MISP **gratuitos** (CIRCL OSINT, abuse.ch, ThreatFox) antes de pagar por uno comercial — cubren mucho.
- Configura **backups automáticos** del directorio Docker (`/var/lib/docker/volumes`) y de los `.env` con secretos.
Solución de problemas comunes
El integrator Wazuh → TheHive no crea Alerts
Verifica logs de Wazuh en /var/ossec/logs/integrations.log. Causas habituales: API key incorrecta, certificado autofirmado de TheHive (añade verify=False al request en el script Python para laboratorio, nunca en producción), o regla de Wazuh sin level >= 10.
MISP devuelve 502 tras unos minutos
MISP es PHP/Apache y a veces tarda en inicializar. Espera 5 minutos tras docker compose up y revisa docker logs misp-misp-core-1. Si persiste, sube RAM disponible — MISP necesita ~3 GB libres bajo carga.
Cortex no puede ejecutar el analyzer MISP
El error más común es SSL: CERTIFICATE_VERIFY_FAILED si MISP usa cert autofirmado. Importa el CA de MISP al contenedor de Cortex (/etc/ssl/certs) o desactiva cert_check solo en laboratorio.
Preguntas frecuentes
¿Cuánto cuesta operar esto al mes?
Un VPS adecuado (Hetzner, Contabo, OVH) con las especificaciones recomendadas cuesta 15-30 USD/mes. Suma 12 USD/año del dominio y 0 USD de software open source. Total: 200-400 USD/año.
¿Sirve para producción enterprise?
Para PYMEs sí. Para enterprises grandes necesitas separar componentes en máquinas dedicadas, cluster Wazuh, Cassandra HA y backups cifrados off-site. La arquitectura es la misma, escala lo que cambia.
¿Hace falta saber programar?
Para esta guía, no. Para customizar el integrator Wazuh→TheHive sí ayuda saber Python básico (es el único script propio que tocas). El resto es Docker Compose + UI web.
¿Por qué no usar Elastic Security en vez de Wazuh?
Elastic Security es válido y técnicamente más maduro en ML/UEBA, pero su tier free es más limitado en compliance y FIM. Para un SOC casero, Wazuh es más completo gratis.