-
Notifications
You must be signed in to change notification settings - Fork 108
Expand file tree
/
Copy pathdeploy.sh
More file actions
247 lines (221 loc) · 10.1 KB
/
Copy pathdeploy.sh
File metadata and controls
247 lines (221 loc) · 10.1 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
#!/usr/bin/env bash
# ─────────────────────────────────────────────────────────────────
# HackLabs – Despliegue Docker al estilo DockerLabs
# Uso: sudo bash deploy.sh
# ─────────────────────────────────────────────────────────────────
# ── Colores (usando $'…' para que los escapes se resuelvan al asignar) ──
RED=$'\033[0;31m'; GREEN=$'\033[0;32m'; YELLOW=$'\033[1;33m'
CYAN=$'\033[0;36m'; BOLD=$'\033[1m'; DIM=$'\033[2m'; NC=$'\033[0m'
CONTAINER_NAME="hacklabs"
IMAGE_NAME="hacklabs:latest"
NET_NAME="hacklabs_net"
SHIM="macvlan0"
log() { echo "${GREEN}[+]${NC} $1"; }
warn() { echo "${YELLOW}[!]${NC} $1"; }
err() { echo "${RED}[✗] $1${NC}"; exit 1; }
# ── Banner ──
clear
echo ""
echo "${RED} __ __ __ __ __ ${NC}"
echo "${RED} / / / /____ _ _____ / /__ / / ____ _ / /_ _____${NC}"
echo "${RED} / /_/ // __ \`// ___// //_// / / __ \`// __ \\ / ___/${NC}"
echo "${RED} / __ // /_/ // /__ / ,< / /___/ /_/ // /_/ /(__ ) ${NC}"
echo "${RED}/_/ /_/ \\__,_/ \\___//_/|_|/_____/\\__,_//_.___//____/ ${NC}"
echo ""
echo " ${DIM}Intentionally Vulnerable Labs · by afsh4ck${NC}"
echo " ${RED}[!] ADVERTENCIA: Solo usar en entornos aislados y controlados${NC}"
echo ""
# ── Verificar root ──
[[ $EUID -ne 0 ]] && err "Ejecuta con privilegios root: ${YELLOW}sudo bash deploy.sh${NC}"
# ── Verificar Docker ──
if ! command -v docker &>/dev/null; then
echo "${YELLOW}[!]${NC} Docker no está instalado en el sistema."
read -rp " ¿Deseas instalar Docker ahora? (y/n): " INSTALL_DOCKER
if [[ "$INSTALL_DOCKER" =~ ^[yYsS]$ ]]; then
log "Instalando Docker..."
apt-get update -qq
apt-get install -y -qq docker.io > /dev/null 2>&1 || err "Error al instalar Docker."
systemctl enable --now docker > /dev/null 2>&1
log "Docker instalado correctamente."
else
err "Docker es necesario para desplegar HackLabs."
fi
fi
if ! docker info &>/dev/null; then
echo "${YELLOW}[!]${NC} El servicio Docker no está activo."
read -rp " ¿Deseas iniciar Docker ahora? (y/n): " START_DOCKER
if [[ "$START_DOCKER" =~ ^[yYsS]$ ]]; then
systemctl start docker
sleep 2
docker info &>/dev/null || err "No se pudo iniciar Docker."
log "Docker iniciado correctamente."
else
err "Docker debe estar activo para desplegar HackLabs."
fi
fi
# ── Detectar interfaz de red ──
IFACE="eth0"
if ! ip link show "$IFACE" &>/dev/null; then
IFACE=$(ip route | awk '/default/{print $5; exit}')
[[ -z "$IFACE" ]] && err "No se detectó ninguna interfaz de red activa."
warn "eth0 no disponible — usando ${BOLD}$IFACE${NC}"
fi
HOST_IP_CIDR=$(ip -4 addr show "$IFACE" | grep -oP '(?<=inet\s)\d+\.\d+\.\d+\.\d+/\d+' | head -1)
[[ -z "$HOST_IP_CIDR" ]] && err "No se pudo detectar la IP de $IFACE."
# Extraer componentes
HOST_IP=$(echo "$HOST_IP_CIDR" | cut -d/ -f1)
CIDR_MASK=$(echo "$HOST_IP_CIDR" | cut -d/ -f2)
NET_BASE=$(echo "$HOST_IP" | grep -oP '^\d+\.\d+\.\d+')
# Calcular la dirección de red correcta (para Docker macvlan)
IFS='.' read -r O1 O2 O3 O4 <<< "$HOST_IP"
if [[ "$CIDR_MASK" -eq 24 ]]; then
NETWORK_ADDR="${O1}.${O2}.${O3}.0"
elif [[ "$CIDR_MASK" -eq 16 ]]; then
NETWORK_ADDR="${O1}.${O2}.0.0"
elif [[ "$CIDR_MASK" -eq 8 ]]; then
NETWORK_ADDR="${O1}.0.0.0"
else
NETWORK_ADDR="${O1}.${O2}.${O3}.0"
fi
SUBNET="${NETWORK_ADDR}/${CIDR_MASK}"
GATEWAY=$(ip route | awk "/default.*$IFACE/{print \$3; exit}")
[[ -z "$GATEWAY" ]] && GATEWAY=$(ip route | awk '/default/{print $3; exit}')
[[ -z "$GATEWAY" ]] && err "No se pudo detectar la puerta de enlace."
log "Red detectada: ${BOLD}$SUBNET${NC} en ${BOLD}$IFACE${NC} (gateway ${BOLD}$GATEWAY${NC})"
# ── Seleccionar IP libre en rango .100–.199 ──
CONTAINER_IP=""
while read -r OCTET; do
CANDIDATE="${NET_BASE}.${OCTET}"
ping -c1 -W1 "$CANDIDATE" &>/dev/null 2>&1 || { CONTAINER_IP="$CANDIDATE"; break; }
done < <(shuf -i 100-199)
[[ -z "$CONTAINER_IP" ]] && err "No se encontró ninguna IP libre en ${NET_BASE}.100-199."
log "IP asignada al laboratorio: ${BOLD}${CONTAINER_IP}${NC}"
# ── Limpiar instancias previas ──
warn "Limpiando instancias previas si existen..."
docker stop "$CONTAINER_NAME" &>/dev/null || true
docker rm "$CONTAINER_NAME" &>/dev/null || true
docker network rm "$NET_NAME" &>/dev/null || true
ip link del "$SHIM" &>/dev/null || true
# ── Función de limpieza (Ctrl+C) ──
cleanup() {
echo ""
warn "Deteniendo el laboratorio..."
docker stop "$CONTAINER_NAME" &>/dev/null || true
docker rm "$CONTAINER_NAME" &>/dev/null || true
docker network rm "$NET_NAME" &>/dev/null || true
ip link del "$SHIM" &>/dev/null || true
echo "${GREEN}[+] Laboratorio eliminado correctamente. ¡Hasta pronto!${NC}"
echo ""
exit 0
}
trap cleanup SIGINT SIGTERM
# ── Construir imagen Docker ──
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
GIT_HASH=$(git -C "$SCRIPT_DIR" rev-parse --short HEAD 2>/dev/null || date +%s)
log "Construyendo imagen Docker..."
docker build -t "$IMAGE_NAME" --build-arg CACHEBUST="$GIT_HASH" "$SCRIPT_DIR" --quiet \
|| err "Error al construir la imagen Docker."
# ── Crear red macvlan ──
log "Creando red macvlan '${BOLD}$NET_NAME${NC}'..."
docker network create \
--driver macvlan \
--subnet="$SUBNET" \
--gateway="$GATEWAY" \
--opt parent="$IFACE" \
"$NET_NAME" > /dev/null \
|| err "No se pudo crear la red macvlan."
# ── Crear shim macvlan para que el host pueda alcanzar el contenedor ──
ip link add "$SHIM" link "$IFACE" type macvlan mode bridge 2>/dev/null || true
ip addr add "${NET_BASE}.200/32" dev "$SHIM" 2>/dev/null || true
ip link set "$SHIM" up
ip route add "${CONTAINER_IP}/32" dev "$SHIM" 2>/dev/null || true
# ── Iniciar contenedor ──
log "Iniciando contenedor HackLabs..."
docker run -d \
--name "$CONTAINER_NAME" \
--network "$NET_NAME" \
--ip "$CONTAINER_IP" \
--hostname hacklabs \
--cap-add NET_ADMIN \
-v hacklabs_db:/app/data \
-v hacklabs_uploads:/app/uploads \
-v hacklabs_logs:/app/logs \
"$IMAGE_NAME" > /dev/null \
|| err "No se pudo iniciar el contenedor."
# ── Esperar que el servicio HTTP esté listo ──
echo -n "${GREEN}[+]${NC} Esperando que el servicio arranque"
sleep 5
for _ in $(seq 1 30); do
curl -sf --connect-timeout 1 "http://${CONTAINER_IP}" &>/dev/null && break
echo -n "."
sleep 1
done
echo ""
# ── Panel de información ──
echo ""
echo " ${GREEN}════════════════════════════════════════════════════${NC}"
echo " ${BOLD}${GREEN} ✓ Laboratorio desplegado correctamente${NC}"
echo " ${GREEN}════════════════════════════════════════════════════${NC}"
echo ""
echo " ${CYAN}${BOLD} IP del objetivo: ${CONTAINER_IP}${NC}"
echo ""
echo " ${DIM} HTTP → http://${CONTAINER_IP}${NC}"
echo " ${DIM} FTP → ftp://${CONTAINER_IP} (puerto 21)${NC}"
echo " ${DIM} SSH → ssh user@${CONTAINER_IP} (puerto 22)${NC}"
echo " ${DIM} SMB → //${CONTAINER_IP}/ (puerto 445)${NC}"
echo ""
echo " ${DIM} nmap -sV -p 21,22,80,445 ${CONTAINER_IP}${NC}"
echo ""
echo " ${GREEN}════════════════════════════════════════════════════${NC}"
echo ""
echo " ${YELLOW} Presiona Ctrl+C para detener el laboratorio${NC}"
echo ""
# ── Abrir Firefox ──
# Si Firefox ya está abierto en la sesión del usuario, abrir nueva pestaña
# en ESA sesión (mismo perfil logueado, extensiones, etc.).
_BROWSER_USER="${SUDO_USER:-}"
if [[ -n "$_BROWSER_USER" ]]; then
_FF=$(command -v firefox-esr 2>/dev/null || command -v firefox 2>/dev/null)
if [[ -n "$_FF" ]]; then
_URL="http://${CONTAINER_IP}"
_FF_PID=$(pgrep -u "$_BROWSER_USER" -x firefox | head -1)
[[ -z "$_FF_PID" ]] && _FF_PID=$(pgrep -u "$_BROWSER_USER" -x firefox-esr | head -1)
# Intenta heredar entorno gráfico de la sesión real del usuario.
_DISPLAY=":0"
_DBUS=""
if [[ -n "$_FF_PID" ]] && [[ -r "/proc/${_FF_PID}/environ" ]]; then
_ENV_DUMP=$(tr '\0' '\n' < "/proc/${_FF_PID}/environ" 2>/dev/null || true)
_DISPLAY=$(printf '%s\n' "$_ENV_DUMP" | awk -F= '/^DISPLAY=/{print $2; exit}')
_DBUS=$(printf '%s\n' "$_ENV_DUMP" | awk -F= '/^DBUS_SESSION_BUS_ADDRESS=/{print substr($0,index($0,$2)); exit}')
[[ -z "$_DISPLAY" ]] && _DISPLAY=":0"
fi
if [[ -n "$_FF_PID" ]]; then
# Firefox ya abierto: fuerza nueva pestaña en la sesión existente.
if [[ -n "$_DBUS" ]]; then
sudo -u "$_BROWSER_USER" env DISPLAY="$_DISPLAY" \
DBUS_SESSION_BUS_ADDRESS="$_DBUS" \
HOME="/home/${_BROWSER_USER}" \
"$_FF" --new-tab "$_URL" &>/dev/null &
else
sudo -u "$_BROWSER_USER" env DISPLAY="$_DISPLAY" \
HOME="/home/${_BROWSER_USER}" \
"$_FF" --new-tab "$_URL" &>/dev/null &
fi
else
# No hay Firefox abierto: abrir con perfil normal del usuario.
sudo -u "$_BROWSER_USER" env DISPLAY="$_DISPLAY" \
HOME="/home/${_BROWSER_USER}" \
"$_FF" "$_URL" &>/dev/null &
fi
fi
fi
# ── Mantener el script activo hasta Ctrl+C ──
while true; do
# Verificar que el contenedor sigue corriendo
if ! docker inspect -f '{{.State.Running}}' "$CONTAINER_NAME" &>/dev/null 2>&1; then
echo ""
warn "El contenedor se ha detenido inesperadamente."
break
fi
sleep 5
done