Monta tu propio laboratorio de Active Directory con Ludus y GOAD
Tabla de contenido
Los Pro Labs de Hack The Box están muy bien, pero cuestan 49 €/mes y, sobre todo, no puedes publicar nada de lo que haces en ellos. Si lo que quieres es un dominio de Active Directory entero para romperlo, revertirlo y volver a empezar, y encima escribir sobre ello sin pedirle permiso a nadie, la respuesta es montártelo en casa.
En esta entrada monto un laboratorio de AD desde cero con Ludus , que automatiza todo el ciclo sobre Proxmox, y despliego encima GOAD (Game of Active Directory), el laboratorio vulnerable de Orange Cyberdefense. El resultado es un dominio completo que enciendes cuando quieres, rompes a gusto y devuelves a su estado original en veinte segundos con un snapshot.
Escribo esto también como nota para mí mismo: monté el mío hace meses y, cuando volví a él, ya no me acordaba ni de la mitad de los pasos.
🗺️ Qué vamos a montar
Tu equipo (Kali)
│
│ WireGuard (198.51.100.0/24)
▼
┌──────────────────────────────┐
│ Servidor físico "ludus" │ Debian 12 + Proxmox VE
│ ──────────────────────── │
│ Ludus ──► Packer │ construye las plantillas
│ ──► Ansible │ despliega y provisiona
│ │
│ ┌────────────────────────┐ │
│ │ Range 10.2.0.0/16 │ │
│ │ router ─ DC01 ─ SRV01 │ │
│ │ └─ LX01 │ │
│ └────────────────────────┘ │
└──────────────────────────────┘
Ludus es la pieza que lo hace llevadero. Instala Proxmox por ti, construye las plantillas de Windows y Linux con Packer, levanta las máquinas, las mete en VLANs, monta un router, te da un WireGuard para entrar desde tu Kali y gestiona los snapshots. Todo con una API y un cliente de línea de comandos.
GOAD pone el contenido: un dominio con usuarios, relaciones de confianza, ACLs mal puestas, delegaciones y servicios vulnerables. Trae varios laboratorios en el mismo repositorio, así que con la infraestructura montada una vez puedes ir cambiando de escenario.
🧰 Requisitos
Estas son las especificaciones de mi servidor, que es un equipo reciclado, para que veas que no hace falta nada del otro mundo:
| Placa | MSI Z97 GAMING 5 |
| CPU | Intel i7-4790K (8 hilos) con VT-x |
| RAM | 19 GB |
| Disco | 218 GB SSD |
Sobre eso corren ahora mismo 13 máquinas virtuales: 9 plantillas y 4 del laboratorio. Como referencia, mi laboratorio actual consume 12 GB de RAM con tres VMs encendidas.
⚠️ El disco se sufre más que la RAM. Cada plantilla de Windows reserva unos 250 GB de disco provisionado (aunque en la práctica gaste mucho menos) y yo voy al 74% de ocupación. Si andas justo, construye solo las plantillas que vayas a usar de verdad.
Necesitas además hardware dedicado: Ludus instala Proxmox, así que el equipo se convierte en un hipervisor y no vas a poder usarlo para otra cosa.
🔧 Fase 1: la BIOS
Este paso se olvida y luego las máquinas no arrancan o van a rastras. Los nombres son de una placa MSI, pero el equivalente está en cualquiera:
| Opción | Valor | Dónde |
|---|---|---|
| Intel Virtualization Tech | Enabled | OC → CPU Features |
| Intel VT-D Tech | Enabled | OC → CPU Features |
| Boot Mode Select | UEFI | Settings → Boot |
| Fast Boot / MSI Fast Boot | Disable | Settings → Boot |
| Secure Boot | Disable | Advanced → Windows 8/8.1 |
| SATA Mode | AHCI | Advanced → Integrated Peripherals |
| Intel C-State | Disable | Advanced → Power Management |
Las dos primeras son obligatorias: sin VT-x no hay virtualización. El resto evita sorpresas al arrancar.
🐧 Fase 2: Debian 12
Ludus se instala sobre Debian 12 limpio. Ni Ubuntu ni Debian 13: el instalador espera Bookworm.
Graba la ISO, instala el sistema base sin entorno gráfico y añade tu usuario al grupo sudo:
su -
apt update && apt install sudo -y
usermod -aG sudo TU_USUARIO
Aprovecha para fijar la IP del servidor en el router por MAC (DHCP binding), porque vas a apuntar ahí muchas cosas y no te interesa que cambie.
🚀 Fase 3: instalar Ludus
Ya desde SSH, con las dependencias mínimas:
su -
apt update && apt install curl sudo git ca-certificates python3-debian -y
curl -s https://ludus.cloud/install | bash
⚠️ No hagas esta fase desde MobaXterm. Su terminal interfiere con el instalador. Usa un SSH normal y, a poder ser, dentro de
tmux, porque el proceso reinicia el servidor un par de veces mientras instala Proxmox.
Cuando termine, comprueba el estado y apunta la clave de API de root, que es la que permite crear usuarios:
ludus-install-status
# Root API key: ROOT.xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
A partir de aquí ya tienes Proxmox escuchando en https://IP_DEL_SERVIDOR:8006.
👤 Fase 4: tu usuario y las credenciales de Proxmox
Ludus es multiusuario: cada usuario tiene su propio range, su red y su WireGuard. Crea el tuyo con la clave de root:
export LUDUS_API_KEY='ROOT.xxxxxxxxxxxxxxxxxxxx'
ludus users add --name "Tu Nombre" --userid JO --admin --url https://127.0.0.1:8081
# te devuelve la API key del usuario: JO.xxxxxxxxxxxxxxxx
El --userid es importante: es la etiqueta que va a llevar todo lo tuyo (la red, las VMs, el peer de WireGuard). Yo uso JO, y por eso mi router se llama JO-router-debian11-x64.
Ahora cambia a la clave de tu usuario, que es la que vas a usar siempre:
export LUDUS_API_KEY='JO.xxxxxxxxxxxxxxxx'
ludus users list
Y saca las credenciales para entrar por web a Proxmox:
ludus users creds get
💡 Mete el
export LUDUS_API_KEYen tu.bashrc. Sin esa variable el cliente responde[FATAL] No API keyy no funciona ni un comando.
📦 Fase 5: las plantillas
Aquí es donde se va el tiempo. Ludus usa Packer para construir sus propias plantillas: descarga la ISO, hace una instalación desatendida, instala los guest tools y deja la imagen lista para clonar.
ludus templates list
La primera vez las verás todas a FALSE. Para construirlas:
ludus templates build # todas
ludus templates build -n win2019-server-x64-template # solo una
ludus templates logs -f # seguir el proceso
⏱️ Esto tarda horas, y es normal. Déjalo por la noche. Si algo se atasca,
ludus templates abortcorta el proceso, y si hay que ir a lo bruto,pkill packercomo root.
Estas son las que tengo construidas:
+------------------------------------+-------+
| TEMPLATE | BUILT |
+------------------------------------+-------+
| debian-11-x64-server-template | TRUE |
| debian-12-x64-server-template | TRUE |
| kali-x64-desktop-template | TRUE |
| win11-22h2-x64-enterprise-template | TRUE |
| win2022-server-x64-template | TRUE |
| ubuntu-24.04-x64-server-template | TRUE |
| win2019-server-x64-template | TRUE |
| win2025-server-x64-template | TRUE |
| win2025-server-x64-tpm-template | TRUE |
+------------------------------------+-------+
Añadir una plantilla propia
Las plantillas viven en el repositorio de Ludus y se pueden modificar. El caso que me tocó a mí: Windows Server 2025 sin TPM. Ludus trae la versión con TPM, pero para un laboratorio de AD el TPM sobra y complica los snapshots.
git clone https://gitlab.com/badsectorlabs/ludus.git
cd ludus/templates
cp -r win2025-server-x64-tpm win2025-server-x64
cd win2025-server-x64
mv win2025-server-x64-tpm.pkr.hcl win2025-server-x64.pkr.hcl
# renombrar la plantilla y la fuente dentro del .pkr.hcl
sed -i 's/win2025-server-x64-tpm-template/win2025-server-x64-template/' win2025-server-x64.pkr.hcl
sed -i 's/win2025-server-x64-tpm/win2025-server-x64/' win2025-server-x64.pkr.hcl
Al quitar el TPM hay que tocar también el Autounattend.xml, porque la instalación desatendida está preparada para un disco GPT con partición EFI. Sin TPM el esquema cambia: se deja una partición de sistema y otra de OS, y hay que corregir el PartitionID de destino, que pasa de la 3 a la 2.
Y se registra y se construye:
ludus templates add -d ~/ludus/templates/win2025-server-x64 --force
ludus templates build -n win2025-server-x64-template
ludus templates logs -f
🌐 Fase 6: WireGuard para tu máquina atacante
El laboratorio vive en una red aislada. Para atacarlo desde tu Kali, Ludus te da un túnel de WireGuard:
ludus users wireguard --user JO
Devuelve una configuración completa. Cópiala tal cual en tu Kali:
sudo nano /etc/wireguard/ludus.conf
[Interface]
PrivateKey = <la_tuya>
Address = 198.51.100.2/32
[Peer]
PublicKey = <la_del_servidor>
Endpoint = IP_DEL_SERVIDOR:51820
AllowedIPs = 10.2.0.0/16, 198.51.100.1/32
PersistentKeepalive = 25
sudo wg-quick up ludus # conectar
sudo wg-quick down ludus # desconectar
El fallo que me tuvo meses parcheando a mano
El túnel levantaba y yo llegaba al laboratorio sin problema, pero las máquinas del laboratorio no podían responderme: nada de reverse shells. El motivo está en el servidor, en /etc/wireguard/wg0.conf, donde tu peer queda así:
[Peer]
PublicKey = AD0s36X1DXCA...
AllowedIPs = 198.51.100.2/32
Solo con tu IP del túnel. Sin la red del laboratorio en esa línea, el servidor no sabe enrutar hacia ti el tráfico que sale de las VMs. Yo lo arreglaba en cada arranque con un wg set ... allowed-ips 198.51.100.2/32,10.2.0.0/16, sin caer en que ese comando no escribe en el fichero y se pierde al reiniciar.
La solución definitiva es editar el fichero y dejarlo así:
AllowedIPs = 198.51.100.2/32, 10.2.0.0/16
y aplicarlo en caliente, sin tirar el túnel:
sudo wg syncconf wg0 <(sudo wg-quick strip wg0)
⚠️ Ese bloque está marcado como
# Ansible managed, así que si vuelves a ejecutar el instalador o recreas el usuario, te lo va a pisar. Anótalo.
🏗️ Fase 7: desplegar el laboratorio
Un range de Ludus se define con un YAML. Podrías escribirlo tú, pero lo interesante es que GOAD ya trae la configuración hecha para Ludus.
git clone https://github.com/Orange-Cyberdefense/GOAD.git
cd GOAD
./goad.sh # la primera ejecución crea ~/.goad/
Configura GOAD para que hable con Ludus editando ~/.goad/goad.ini:
ludus_api_key = JO.xxxxxxxxxxxxxxxx
use_impersonation = no
⚠️ Si tu clave de API contiene un
%, tienes que duplicarlo (%%) en este fichero. Es unConfigParserde Python y el%es su carácter de interpolación. Si no lo haces, GOAD falla con un error que no dice absolutamente nada de la causa real.
Ahora coge la configuración del laboratorio que quieras. Yo uso DRACARYS:
cp ~/GOAD/ad/DRACARYS/providers/ludus/config.yml .
cp ~/GOAD/ad/DRACARYS/providers/ludus/inventory .
# quitar el prefijo de range_id de los nombres de VM
sed -i 's/{{ range_id }}-//g' config.yml
Ese config.yml es directamente el range de Ludus. Este es el mío:
network:
external_default: ACCEPT # internet para las VMs
wireguard_vlan_default: ACCEPT # tu Kali puede alcanzar las VMs
ludus:
- vm_name: "DC01"
hostname: "DC01"
template: win2025-server-x64-template
vlan: 10
ip_last_octet: 10
ram_gb: 4
cpus: 2
windows:
sysprep: true
- vm_name: "SRV01"
hostname: "SRV01"
template: win2025-server-x64-template
vlan: 10
ip_last_octet: 11
ram_gb: 4
cpus: 2
windows:
sysprep: true
- vm_name: "LX01"
hostname: "LX01"
template: ubuntu-24.04-x64-server-template
vlan: 10
ip_last_octet: 12
ram_gb: 4
cpus: 2
linux: true
Fíjate en cómo se forma la IP: el vlan: 10 y el ip_last_octet se combinan dentro de tu red 10.2.0.0/16, así que DC01 acaba siendo 10.2.10.10. Ludus levanta además un router propio en 10.2.10.254.
Y se despliega:
ludus range config set -f config.yml
ludus range deploy
ludus range logs -f # seguir el aprovisionamiento
ludus range status # hasta que ponga SUCCESS
Ludus crea las VMs y después Ansible las provisiona: promueve el dominio, crea los usuarios y mete las vulnerabilidades. Es largo. Si algo peta:
ludus range errors # solo los errores relevantes de los logs
ludus range abort # cortar el ansible en curso
Cuando termine deberías ver esto:
+------------+------------------------+-------+-------------+
| PROXMOX ID | VM NAME | POWER | IP |
+------------+------------------------+-------+-------------+
| 105 | JO-router-debian11-x64 | On | 10.2.10.254 |
| 106 | DC01 | On | 10.2.10.10 |
| 107 | SRV01 | On | 10.2.10.11 |
| 108 | LX01 | On | 10.2.10.12 |
+------------+------------------------+-------+-------------+
📸 Fase 8: los snapshots
No empieces a jugar sin hacer un snapshot. Es lo que separa un laboratorio de un dolor de cabeza: puedes reventar el dominio entero y volver al estado inicial en segundos.
ludus power off -n all
ludus snapshots create dracarys-ok -d "DRACARYS OK" --noRAM
ludus power on -n all
Consultar y revertir:
ludus snapshots list
ludus snapshots revert dracarys-ok
VM 106 (DC01)
└── dracarys-ok 2026-03-13 16:20:47 (DRACARYS OK)
└── current (You are here!)
Yo hago siempre dos: uno antes de que GOAD provisione, por si el aprovisionamiento se tuerce y no quiero reconstruir las VMs desde cero, y otro después, con el laboratorio ya montado y funcionando.
🎮 El día a día
Una vez montado, la rutina se queda en esto:
export LUDUS_API_KEY='JO.xxxxxxxxxxxx'
ludus power on -n all # encender
sudo wg-quick up ludus # (en la Kali) levantar el túnel
# ... a jugar ...
ludus snapshots revert dracarys-ok # dejarlo como estaba
ludus power off -n all # apagar
Y hay tres comandos que no salen en ningún tutorial y que ahorran mucho tiempo:
ludus range etc-hosts # genera el /etc/hosts con todos los hosts del range
ludus range rdp # zip con los .rdp de todas las máquinas Windows
ludus range inventory # el inventario de Ansible del range
El primero es oro puro: lo pegas en el /etc/hosts de tu Kali y ya te refieres a las máquinas por su nombre.
🧪 Comprobar que está vivo
Un barrido rápido te dice si el dominio está en pie de verdad:
nmap -Pn -p 88,135,389,445,3389,5985 10.2.10.10-12
Un controlador de dominio sano responde en 88 (Kerberos), 389 (LDAP), 445 (SMB) y 5985 (WinRM). Y el DNS del dominio tiene que resolver:
dig +short @10.2.10.10 dracarys.lab
10.2.10.10
🧯 Problemas con los que me he encontrado
- Las VMs no salen a internet. El router del range hace de NAT, pero según cómo quede la red se puede quedar corto. Se arregla en el propio router (
ssh debian@10.2.10.254, contraseñadebian) con unMASQUERADEpara tu red y, si el DNS no tira, unDNATdel puerto 53 hacia8.8.8.8. - El
%de la API key engoad.ini. Ya lo he dicho arriba, pero es que con esto se pierde media tarde. - MobaXterm durante la instalación. Rompe el instalador de Ludus. Y como bonus, luego se te olvida que la contraseña del servidor la tienes guardada solo ahí.
- Las plantillas de Windows con TPM complican los snapshots. Si no vas a probar cosas de TPM o Credential Guard, hazte la plantilla sin él.
- Ojo con
ludus range rm. Destruye todas las VMs del range sin preguntar. Las plantillas se conservan, que es lo que cuesta horas, pero el laboratorio hay que volver a desplegarlo entero.
🎯 Qué más puedes montar
Con la infraestructura hecha, cambiar de laboratorio es cambiar un fichero de configuración. En el repositorio de GOAD tienes:
| Laboratorio | Qué es |
|---|---|
| GOAD | El completo: 5 máquinas, dos bosques y tres dominios |
| GOAD-Light | La versión reducida, 3 máquinas |
| GOAD-Mini | Aún más pequeño, para ir justo de recursos |
| MINILAB | Un dominio sencillo, ideal para empezar |
| NHA | Ninja Hacker Academy |
| SCCM | Enfocado a atacar SCCM/MECM |
| DRACARYS | El que uso en esta entrada |
Y como todo esto corre en tu hardware, no hay reglas de publicación, ni suscripción, ni máquinas que se retiran. Puedes documentar hasta el último paso.
📝 Resumen
| Fase | Qué haces | Tiempo |
|---|---|---|
| 1 | BIOS: VT-x y VT-D | 5 min |
| 2 | Debian 12 limpio + sudo | 20 min |
| 3 | Instalar Ludus | 30 min |
| 4 | Crear usuario y sacar credenciales | 5 min |
| 5 | Construir plantillas | horas |
| 6 | WireGuard en la Kali | 10 min |
| 7 | ludus range config set y deploy | 1-2 h |
| 8 | Snapshot | 2 min |
La parte cara es la fase 5, y solo se paga una vez. A partir de ahí, montar un laboratorio nuevo son diez minutos de configuración y un deploy.
