En Linux, cada archivo tiene un dueño (usuario), un grupo, y un conjunto de permisos. Modificar todo eso es fácil… demasiado fácil si usas root sin cabeza.
Vamos a verlos uno por uno.
1. chown → Cambiar el dueño del archivo
La sintaxis es:
chown usuario archivo
Ejemplo simple:
sudo chown juan /var/www/html/index.html
Ahora Juan es el dueño de ese archivo.
Si quieres cambiar usuario y grupo:
sudo chown juan:profesores documento.txt
Cambiar solo el grupo:
sudo chown :profesores documento.txt
Cambiar de forma recursiva (carpeta entera):
sudo chown -R juan:juangroup /home/juan
chown es “Change Owner”: cambia quién manda sobre el archivo.
2. chgrp → Cambiar solo el grupo
Es más específico que chown:
sudo chgrp alumnos proyecto.txt
La idea es sencilla: Cuando tienes un archivo, pueden mandar sobre él:
tú como usuario
o cualquiera de tu grupo asociado
chgrp te deja decidir ese segundo nivel.
3. chmod → Cambiar los permisos
Aquí empieza el festival de números y letras. Tus alumnos suelen entenderlo mejor si usas una metáfora de puertas.
Cada archivo tiene permisos divididos en tres bloques:
u g o user group others
Y cada uno tiene:
r → read (leer)
w → write (escribir)
x → execute (ejecutar)
Dos formas de usar chmod:
A) Modo numérico (octal)
Es el clásico:
chmod 755 archivo
Por qué 7, 5 y 5? Porque cada permiso suma:
r = 4
w = 2
x = 1
Ejemplos:
7 = rwx (4+2+1)
6 = rw- (4+2)
5 = r-x (4+1)
4 = r– (4)
Ejemplos prácticos:
Permiso para que usuario pueda todo, grupo y otros solo leer:
Un usuario normal solo puede cambiar permisos y dueños de lo que le pertenece. Root puede cambiar todo, lo que lo convierte en una herramienta poderosa… o en un desastre en manos torpes.
Acabas de expulsar a alumno1 de su propia casa. Es un experimento divertido para enseñar responsabilidad… o para que entiendan por qué root no es una buena costumbre.
Resumen
chown → cambia el dueño del archivo y su grupo
chgrp → cambia solo el grupo
chmod → cambia los permisos (r, w, x) en user/group/others
root puede cambiarlo todo
usuarios normales solo pueden cambiar sus propios archivos
La estación espacial Andrómeda necesita organizar a su tripulación. Hay tres equipos principales:
pilotos
ingenieros
cientificos
Cada miembro de la tripulación tendrá acceso solo a determinadas carpetas según su grupo. Además, el comandante de la estación deberá poder reorganizar la tripulación, cambiar usuarios de grupo y ajustar propietarios y permisos de archivos.
Tu misión será convertirte en el administrador del sistema de la estación.
1. Objetivos de la práctica
Al finalizar esta práctica, el alumno será capaz de:
crear usuarios en Ubuntu,
crear grupos de usuarios,
añadir usuarios a grupos,
cambiar un usuario de grupo,
comprobar a qué grupos pertenece un usuario,
crear carpetas para distintos equipos,
asignar propietario y grupo a carpetas y archivos,
modificar permisos con chmod,
utilizar chown para cambiar propietario y grupo,
verificar que los permisos funcionan correctamente.
2. Qué vas a aprender
En Linux, cada archivo y carpeta tiene asociado:
un propietario,
un grupo,
unos permisos.
Los permisos se pueden definir para:
u → usuario propietario,
g → grupo,
o → otros usuarios.
Y los permisos básicos son:
r → lectura,
w → escritura,
x → ejecución o acceso.
3. Preparación inicial
Antes de empezar, abre una terminal y asegúrate de trabajar con un usuario con permisos de administración.
Puedes comprobarlo con:
whoami
Y probar que tienes permisos de sudo con:
sudo -v
4. Crear los grupos de la estación
Vamos a crear los tres grupos principales de la tripulación.
La carpeta comun será accesible para todos, mientras que las otras estarán restringidas.
12. Comprobar los permisos
ls -ld /srv/andromeda/pilotos ls -ld /srv/andromeda/ingenieros ls -ld /srv/andromeda/cientificos ls -ld /srv/andromeda/comun
Fíjate en algo como esto:
drwxrwx--- 2 root pilotos ...
Eso significa:
d → es una carpeta,
rwx → permisos del propietario,
rwx → permisos del grupo,
--- → permisos del resto.
13. Probar acceso con distintos usuarios
Ahora toca comprobar si realmente funciona.
Entrar como un usuario concreto
Puedes cambiar de usuario con:
su - luke
O, si prefieres, ejecutar comandos como otro usuario:
sudo -u luke ls /srv/andromeda/pilotos sudo -u luke ls /srv/andromeda/ingenieros
Qué debería ocurrir
luke sí debería poder entrar en /srv/andromeda/pilotos
luke no debería poder entrar en /srv/andromeda/ingenieros
Prueba varios casos:
sudo -u luke ls /srv/andromeda/pilotos sudo -u luke ls /srv/andromeda/ingenieros sudo -u data ls /srv/andromeda/ingenieros sudo -u ripley ls /srv/andromeda/cientificos sudo -u spock ls /srv/andromeda/pilotos
¿Que hace? sudo -u luke ls
Ejecuta el comando ls como si lo estuviera lanzando el usuario luke. -u luke Le dice a sudo que el comando no se ejecute como tu usuario actual, sino como el usuario luke.
14. Crear archivos dentro de las carpetas
Vamos a crear documentos de misión dentro de cada zona.
echo "Ruta secreta al sector Omega" | sudo tee /srv/andromeda/pilotos/ruta_estelar.txt
echo "Estado del reactor principal" | sudo tee /srv/andromeda/ingenieros/reactor.txt
echo "Análisis de muestras alienígenas" | sudo tee /srv/andromeda/cientificos/informe_biologico.txt
echo "Reunión general a las 18:00" | sudo tee /srv/andromeda/comun/avisos_generales.txt
¿Que hace tee?
sirve para escribir un texto dentro de un archivo con permisos de administrador. El comando tee recoge lo que le llega por la entrada estándar y lo:
muestra por pantalla,
y además lo guarda en un archivo.
Como va precedido de sudo, tee se ejecuta con permisos de administrador, por lo que puede escribir en una ruta protegida.
Un usuario del grupo correcto debería poder trabajar dentro de su carpeta.
Un usuario de otro grupo debería recibir un error de permisos.
Los archivos deben respetar los permisos establecidos.
21. Ver propietarios y permisos de toda la estación
Para revisar toda la estructura:
ls -lR /srv/andromeda
Esto te mostrará:
carpetas,
archivos,
propietarios,
grupos,
permisos.
22. Recuerda
Diferencia entre propietario y grupo
El propietario es normalmente el usuario dueño del archivo.
El grupo permite que varios usuarios compartan acceso a archivos y carpetas.
Diferencia entre chown y chmod
chown cambia el propietario o grupo.
chmod cambia los permisos.
Comandos clave
Crear grupo
sudo groupadd nombre_grupo
Crear usuario
sudo useradd -m -s /bin/bash nombre_usuario
Asignar contraseña
sudo passwd nombre_usuario
Añadir usuario a grupo
sudo usermod -aG grupo usuario
Ver grupos de un usuario
groups usuario
Quitar usuario de un grupo
sudo gpasswd -d usuario grupo
Cambiar propietario y grupo
sudo chown propietario:grupo archivo_o_carpeta
Cambiar permisos
sudo chmod permisos archivo_o_carpeta
23. Actividad
Ahora que ya sabes manejar usuarios y permisos, realiza estas tareas:
Tarea 1
Crea un nuevo grupo llamado:
seguridad
Tarea 2
Crea dos usuarios nuevos:
trinity
morpheo
Tarea 3
Añade ambos al grupo seguridad.
Tarea 4
Crea la carpeta:
/srv/andromeda/seguridad
Tarea 5
Haz que:
el propietario sea root,
el grupo sea seguridad,
los permisos sean 770.
Tarea 6
Crea dentro un archivo llamado:
protocolo_defensa.txt
Tarea 7
Haz que el archivo pertenezca a trinity:seguridad.
Tarea 8
Pon permisos 640 al archivo.
Tarea 9
Comprueba que:
trinity puede leerlo,
morpheo puede leerlo,
luke no puede acceder.
25. Planteate las siguientes preguntas.
¿Qué diferencia hay entre un usuario y un grupo?
¿Qué hace el comando chown?
¿Qué hace el comando chmod?
¿Qué significa el permiso 770?
¿Qué significa el permiso 640?
¿Cómo se comprueba a qué grupos pertenece un usuario?
¿Qué comando se usa para eliminar a un usuario de un grupo?
¿Por qué es útil trabajar con grupos en lugar de dar permisos usuario por usuario?
La estación orbital Andrómeda ya está organizada. Cada tripulante pertenece a su equipo, cada carpeta está protegida y los documentos sensibles solo son accesibles por el personal autorizado. Has completado con éxito tu primera misión como administrador de sistemas espaciales.
Tabla de comandos y opciones principales
Comando
Opción / sintaxis
Explicación
groupadd
groupadd nombre_grupo
Crea un grupo nuevo en el sistema.
useradd
useradd nombre_usuario
Crea un usuario.
useradd
-m
Crea automáticamente la carpeta personal del usuario en /home.
useradd
-s /bin/bash
Asigna la shell Bash al usuario.
passwd
passwd nombre_usuario
Establece o cambia la contraseña de un usuario.
usermod
usermod usuario
Modifica la configuración de un usuario existente.
usermod
-aG grupo usuario
Añade el usuario a un grupo secundario sin quitarlo de los demás.
groups
groups usuario
Muestra los grupos a los que pertenece un usuario.
id
id usuario
Muestra UID, GID y grupos del usuario.
mkdir
mkdir carpeta
Crea una carpeta.
mkdir
-p
Crea la ruta completa aunque haya varios niveles de carpetas.
touch
touch archivo
Crea un archivo vacío si no existe.
ls
ls
Lista archivos y carpetas.
ls
-l
Muestra la lista en formato largo, con permisos, propietario, grupo, tamaño, etc.
ls
-d
Muestra información de la carpeta en sí, no de su contenido.
ls
-R
Lista el contenido de forma recursiva, incluyendo subcarpetas.
chown
chown propietario archivo
Cambia el propietario de un archivo o carpeta.
chown
chown propietario:grupo archivo
Cambia propietario y grupo a la vez.
chown
chown :grupo archivo
Cambia solo el grupo del archivo o carpeta.
chown
-R
Aplica el cambio de propietario/grupo de forma recursiva.
chmod
chmod permisos archivo
Cambia los permisos de un archivo o carpeta.
chmod
770
Propietario y grupo con todos los permisos; otros sin acceso.
chmod
750
Propietario con todos los permisos; grupo puede leer y entrar; otros sin acceso.
chmod
640
Propietario puede leer y escribir; grupo solo leer; otros sin acceso.
chmod
664
Propietario y grupo pueden leer y escribir; otros solo leer.
chmod
777
Todos pueden leer, escribir y ejecutar/entrar.
chmod
-R
Cambia permisos de forma recursiva.
gpasswd
gpasswd -d usuario grupo
Elimina un usuario de un grupo.
su
su - usuario
Cambia a otro usuario cargando su entorno.
sudo
sudo comando
Ejecuta un comando con privilegios de administrador.
sudo
sudo -u usuario comando
Ejecuta un comando como otro usuario.
getent
getent group nombre_grupo
Consulta información de un grupo en la base de datos del sistema.
whoami
whoami
Muestra el usuario actual.
tee
tee archivo
Escribe en un archivo a partir de la entrada estándar. Muy útil junto con echo.
El equivalente digital de mirarse al espejo. Muestra el usuario efectivo que está ejecutando el comando. Perfecto para explicar la diferencia entre:
usuario real (el que inicia sesión),
usuario efectivo (el que el sistema usa para permisos, especialmente tras un sudo).
id
Un pequeño radiotelescopio hacia tu identidad numérica. Muestra:
UID (identificador del usuario)
GID (grupo principal)
grupos secundarios Es una forma directa de ver permisos y roles dentro del sistema. Ideal para ejercicios de administración y forense.
who / w / users
El “quién está ahora mismo en la nave”. Sirve para ver sesiones activas y cómo han entrado:
tty
pts (sesiones remotas)
SSH
tiempo conectado
En ciberseguridad es una herramienta rápida para detectar conexiones sospechosas.
env
El baúl entero de variables de entorno. Aquí viven cosas como:
$USER
$HOME
$SHELL
$PATH
Además permite explicar a los alumnos por qué una aplicación “sabe” dónde buscar binarios o dónde está su carpeta de configuración.
echo $USER
Una forma simple de leer la variable que indica el nombre del usuario que ha iniciado sesión. Comparar whoami vs $USER es didáctico: $USER → quien inició sesión whoami → usuario efectivo (útil para mostrar cómo sudo cambia el contexto)
echo $HOME
Viene genial para scripts o explicaciones sobre la organización del sistema. Muestra la ruta al directorio personal, que siempre es sagrado en Linux.
echo $SHELL
Permite enseñar la diferencia entre bash, zsh, fish… Ideal para que entiendan por qué su terminal “se comporta raro” tras instalar algo.
hostname
La identidad pública del sistema en la red. Junto con hostname -I, sirve para explicar la distinción entre:
identidad del equipo,
interfaces,
direcciones IP que usa para comunicarse.
logname
La versión más purista de “quién inició esta sesión”, incluso si has hecho un su o un sudo. Muy útil en prácticas de forense porque te permite reconstruir acciones de usuarios.
tty
Muestra el dispositivo de terminal actual. En remoto se verá algo como /dev/pts/1. Perfecto para entender:
sesiones locales,
sesiones remotas,
multiplexación de terminales.
ps aux | grep $USER
Una puerta a ver “qué está ejecutando realmente tu identidad”. A los alumnos les ayuda a comprender procesos, permisos, señales y contextos.
finger (si lo instalas)
Pinta un pequeño perfil del usuario:
shell
home
nombre real
Antiguo pero didáctico como pocas cosas.
Actividad: “¿Quién eres en esta máquina?” – Identidad y sesiones en Linux
Imagina que el sistema es una estación espacial. Cada alumno entra por una compuerta distinta, a veces cambia de traje (sudo), y el objetivo es reconstruir quién hizo qué.
Todo ocurre en un Ubuntu normal.
FASE 1 — Identidad básica
Ejecuta:
whoami
echo $USER
id
logname
Descubrir que el sistema te reconoce por varias “capas”.
Explicación:
whoami → usuario efectivo.
$USER → usuario que inició sesión.
id → UID, GID, grupos.
logname → el user original aunque hayan hecho su.
Pequeño reto: Pídeles que intenten entender por qué sudo whoami devuelve root, pero echo $USER sigue mostrando su usuario normal.
FASE 2 — Dónde están realmente
Ejecutar
pwd
echo $HOME
echo $SHELL
tty
Esto muestra:
dónde están,
cuál es su shell,
qué terminal están usando (local, SSH, pts…).
Ejercicio: Compartir un terminal local (tty1) con una sesión SSH
FASE 3 — Quién más está en la nave
Ahora miramos el estado de la estación:
who
w
users
hostname
hostname -I
Objetivo: identificar todas las sesiones activas. Puedes entrar desde otra máquina para ver “un intruso”.
Mini-misión: Que usen who para averiguar:
quién está conectado,
desde qué terminal,
desde qué IP si es SSH,
desde cuándo.
Esto introduce sin ruido en análisis forense real.
FASE 4 — Cambio de identidad
sudo -i
whoami
echo $USER
id
logname
tty
Aquí ocurre la magia:
whoami → root
$USER → su usuario original
logname → quien realmente abrió la sesión
tty → la misma porque no abren una nueva
FASE 5 — Ver qué hace cada identidad
En otra terminal, que ejecuten:
ps aux | grep $USER
ps aux | grep root
Fijate que root suele llevar servicios, demonios, etc.
FASE 6 — Prueba forense
Prueba a ejecutar con un usuario un comando secreto en su sesión, por ejemplo:
En este pequeño universo, tu Linux hace de Máquina Central, un nodo que controla el flujo de información entre los humanos libres y las máquinas. Los alumnos son “operadores”, encargados de levantar accesos, crear identidades falsas, aislar directorios y conceder privilegios solo a quienes “existen dentro del sistema”.
El sistema está dividido en dos mundos:
La Superficie (usuarios sin privilegios)
El Backdoor (usuarios con acceso sudo)
La misión avanza en fases, y cada fase tiene su sentido dentro del lore.
FASE 1 — Generación de identidades (crear usuarios)
La Resistencia necesita identidades nuevas para infiltrarse en Matrix.
Cada alumno debe crear:
3 usuarios sin privilegios:
trinity
apoc
switch
1 usuario operador con privilegios sudo:
neo
“neo” deberá ser añadido al grupo sudoers.
Instrucciones sugeridas (los alumnos deben descubrir qué significan las opciones):
La carpeta backdoor representa la puerta por la que Neo accede al código subyacente de Matrix.
FASE 4 — Pruebas de acceso: El Oráculo y los obstáculos
Entrar con cada usuario y comprobar qué carpetas ven.
Crear un archivo dentro de /mission-data con usuarios que NO son del grupo → debe fallar.
Intentar listar /backdoor con un usuario que no sea neo → debe fallar.
Que /simulacion permita escribir a matrix, pero no a zion.
Esto entrena:
– su comprensión de permisos
– su uso de su, ls -l, id, touch, mkdir, groups, etc.
FASE 5 — Mini misión final: Neutralizar al Agente Smith
smith → representa al Agente Smith
Este usuario NO debe pertenecer a ningún grupo de la resistencia ni a matrix.
Debe tener una carpeta personal sin permisos para nadie más:
sudo adduser smith
sudo chmod 700 /home/smith
Debes demostrar que smith no puede interactuar con las carpetas del sistema (mission-data, simulacion, backdoor) y explicar por qué, usando ls -ld, permisos y grupos.
Docker Compose es un orquestador local. Permite definir varios contenedores y sus relaciones en un único archivo docker-compose.yml. Es como dirigir una pequeña obra de teatro donde cada servicio tiene su papel, y Compose levanta el escenario entero con un comando.
Puntos clave:
Escritura declarativa: defines lo que quieres, Compose lo monta.
Multi-servicio: web, base de datos, caches, workers… todo junto.
Entornos replicables: mismo resultado en cualquier máquina.
Paso 3: Crear la carpeta web con un HTML/PHP mínimo
mkdir web
nano web/index.php
Contenido:
<?php
$mysqli = new mysqli("db", "root", "curso2025", "tienda");
echo $mysqli->connect_error ? "Error de conexión" : "Conexión OK a la BD";
?>
<h1>Hola desde Apache en Docker Compose</h1>
Paso 4: Crear Dockerfile para Apache + PHP
Dentro de web/:
FROM php:8.2-apache
RUN docker-php-ext-install mysqli
Suele ser contraseña/usuario mal puestos. Revisa variables. Si ya creaste la base con datos erróneos, recuerda que MySQL guarda usuarios en el volumen: o corriges dentro, o borras volumen (Anexo 10).
Montando Wordpres usando DokerFile
los Dockerfiles listos para hacer docker build directamente (sin Compose) y luego docker run.
Te dejo estructura + archivos y los comandos exactos.
Este Dockerfile crea una imagen de MySQL “lista”, y el usuario/DB/contraseñas las seguirás pasando en el docker run (porque eso es configuración de despliegue, no de imagen).
FROM mysql:8.0
# Opcional: configuración extra (descomenta si la necesitas)
# COPY my.cnf /etc/mysql/conf.d/my.cnf
EXPOSE 3306
Nota: MySQL oficial ya trae su entrypoint; aquí no necesitas más si vas a usar variables en docker run.
wordpress/Dockerfile (build directo)
Imagen WordPress basada en la oficial. Si quieres meter ajustes PHP, te lo dejo ya incluido sin depender de un archivo externo (para que sea “build directo” de verdad).
un docker-compose.yml (WordPress + MySQL) bien comentado para alumnos, con red y volúmenes, y usando las imágenes oficiales (lo más limpio para clase).
docker-compose.yml
version: "3.9"
services:
db:
image: mysql:8.0
container_name: wp-mysql
restart: unless-stopped
# Variables de entorno que MySQL usa para inicializar la BD
environment:
MYSQL_DATABASE: wordpress
MYSQL_USER: wpuser
MYSQL_PASSWORD: wp-pass-123
MYSQL_ROOT_PASSWORD: root-pass-123
# Volumen para que la base de datos NO se pierda al borrar el contenedor
volumes:
- wp-db:/var/lib/mysql
# Conectamos el servicio a una red privada de Docker
networks:
- wp-net
wordpress:
image: wordpress:latest
container_name: wp-web
restart: unless-stopped
# Mapeo de puertos: HOST:CONTENEDOR
# En el navegador: http://localhost:8080
ports:
- "8080:80"
# Variables de entorno para que WordPress sepa cómo conectar con MySQL
environment:
WORDPRESS_DB_HOST: db:3306
WORDPRESS_DB_NAME: wordpress
WORDPRESS_DB_USER: wpuser
WORDPRESS_DB_PASSWORD: wp-pass-123
# Volumen para que WordPress (wp-content, plugins, uploads…) se mantenga
volumes:
- wp-html:/var/www/html
# Dependencia: arranca db antes (no garantiza “lista”, pero sí orden)
depends_on:
- db
networks:
- wp-net
# Definimos volúmenes "named" (persisten aunque pares/borras contenedores)
volumes:
wp-db:
wp-html:
# Red interna para que los contenedores se vean por nombre (db, wordpress)
networks:
wp-net:
driver: bridge
Ya hemos llegado, la democracia se ha convertido en un recuerdo, poco a poco los organismos oficiales han implementado diferentes sistemas de control a la población, primero en las calles, luego en la prensa y televisión y ahora le toca a internet.
Tú anque estas infiltrado en el Incibe, demomento tienes que hacerte pasar por un escoria-censurador.
Te han encargado hacerel prototipo. Como deberas instalar diferentes tipos de herramientas de control y vigilancia, te han pedido que utilices Docker para ir montando los diferentes servicios.
Lo primero, decidir que podra y que no ver los ciudadanos y asi poder adoctirnar a lo mas jovenes e identificar a los mas adultos para someterlos a una dura vigilancia.
Entregar el README con toda la documentación necesaria para su instalación en Raspberry y Ubuntu. Adjuntar comentarios, instrucciones de uso de las acciones mas comunes con el programa Hole y añadir biblioteca de direcciones.
Usar network_mode: host es muy recomendable en Raspberry, porque simplifica el uso de los puertos 53 y 80 (evitas conflictos con el firewall de Docker).
🌐 6. Configurar el router
Ahora tu Pi-hole está sirviendo DNS en la IP fija (ejemplo: 192.168.0.200).
Entra en tu router y en Configuración WAN o DNS manual, pon:
DNS primario: 192.168.0.200 (ojo las ips mostradas son las de este ejemplo)
DNS secundario: 1.1.1.1
7. Pruebas
Desde cualquier dispositivo en la red:
nslookup google.com
Debería mostrar como servidor DNS tu Pi-hole. Y desde el panel web (http://192.168.0.200/admin) verás todas las peticiones y bloqueos.
🧠 Preguntas de ejemplo para reflexionar (añadir al Readme.me)
¿Qué diferencia hay entre cambiar el DNS en un solo dispositivo y hacerlo en el router?
¿Por qué es importante que la Raspberry tenga una IP fija?
¿Qué ventajas de privacidad aporta Pi-hole frente a usar DNS públicos?
¿Qué limitaciones podría tener Pi-hole en una red grande?
LISTAS DE SERVIDORES
Estas se añaden desde la interfaz de Holi o Pi-hole en Group Management → Adlists.
EMPEZAREMOS TRABAJANDO EN NUESTRA MAQUINA VIRTUAL Kali (o Ubuntu) Primero vamos a Crear un entorno de red simple con servidores web para la busqueda de vulnerabilidades y monitorización.
Crea un directorio para tu proyecto:
Ejemplo mkdir red1
Dentro crea las carpetas httpd y firewall
Dentro de la carpeta httpd crea un archivo Dockerfile-httpd
y inserta el siguiente código:
# Dockerfile para httpd
FROM httpd:latest
COPY ./public-html/ /usr/local/apache2/htdocs/
NOTAS;
La instrucción COPY ./public-html/ /usr/local/apache2/htdocs/ en el Dockerfile realiza lo siguiente:
COPY: Es una instrucción de Dockerfile que copia archivos o directorios desde el sistema de archivos del host al sistema de archivos del contenedor. ./public-html/: Especifica el directorio en tu máquina local que contiene los archivos que deseas copiar. En este caso, se asume que tienes un directorio llamado public-html en el mismo nivel que tu Dockerfile.
/usr/local/apache2/htdocs/: Especifica el destino dentro del contenedor donde se copiarán los archivos. Este es el directorio predeterminado de documentos de Apache (httpd), donde se almacenan los archivos que se servirán como contenido web.
Crea otro Dockerfile-firewall en la carpeta del firewall y pon:
# Dockerfile para el firewall
FROM ubuntu:latest
RUN apt-get update && apt-get install -y iptables
COPY ./firewall-rules.sh /usr/local/bin/firewall-rules.sh
RUN chmod +x /usr/local/bin/firewall-rules.sh
ENTRYPOINT ["/usr/local/bin/firewall-rules.sh"]
NOTAS; RUN en un Dockerfile se utiliza para ejecutar comandos dentro de la imagen durante el proceso de construcción. Es una de las instrucciones más comunes y permite instalar paquetes, configurar el sistema, y realizar otras tareas necesarias para preparar la imagen. La carpeta public-html debes crearela en la de httpd
Crea un archivo llamado firewall-rules.sh dentro del subdirectorio firewall:
#!/bin/bash
# Limpiar reglas existentes
iptables -F
# Permitir tráfico desde el host
iptables -A INPUT -i eth0 -s 192.168.1.0/24 -j ACCEPT
# Bloquear todo el tráfico restante
iptables -A INPUT -j DROP
docker-compose up --build
* Realiza pruebas de conexion entre el host y los contenedores. * En cada servidor web modifica el index.html para que ponga server1, server2 o lo que quieras.
Posibles problemas Para ver las redes: sudo docker network ls Si necesitas borrar la red: sudo docker network rm nombreRed Si teneis problemas de permisos usar siempre sudo
Puede ser que tengas que cambiar el archivo de info del repositorio de parrot /etc/containers/registries.conf [registries.search]registries = [‘docker.io’,’quay.io’]
Paso 2
Configurar un entorno de laboratorio con Parrot
Crea una nueva carpeta para parrot y crea el dockerfile
Dockerfile para Parrot Security OS
# Usar la imagen oficial de Parrot Security OS
FROM parrotsec/security:latest
# Actualizar y instalar herramientas
RUN apt-get update && apt-get install -y \
metasploit-framework \
nmap \
burpsuite \
wireshark \
john \
hydra \
git \
vim \
wget &&
# Establecer el punto de entrada CMD ["/bin/bash"]
Además de las herramientas mencionadas anteriormente, aquí tienes algunas adicionales que podrías considerar:
Aircrack-ng: Suite de herramientas para evaluar la seguridad de redes Wi-Fi.
SQLmap: Herramienta para detectar y explotar vulnerabilidades de inyección SQL.
Nikto: Escáner de servidores web para detectar vulnerabilidades.
Gobuster: Herramienta para la enumeración de directorios y archivos en servidores web.
Ejecución del Contenedor
Para construir y ejecutar el contenedor:
# Construir la imagen
docker build -t parrot-pentest .
# Ejecutar el contenedor
docker run -it parrot-pentest
Paso 3
En los pasos anteriores has creado un docker-composer para montar 3 contenedores (dos de web y el firewall). Luego has creado un contenedor parrot con herramientas, pero si te fijas, este esta en una red diferente.
Ahora debes modificar el YML del paso 1 para que cree todo el proceso del paso 1 y 2. Es decir los dos de web, el firewall y el parrot con los dokerfiles ya creados.
Ayuda Si necesitas borrar la red: sudo docker network rm nombreRed Para eliminar un contenedor sudo docker rm nombre o id del contenedor Para parar un contenderor: sudo docker stop nombre o id del contenedor
Si quieres pararlos todos: sudo docker stop $(docker ps -q) Para borrar todos los de una red en concreto: sudo docker rm -f nombreDeLaRed
Como vamos a usar parrot para administrar la red, debemos indicarle tanot que sea interactivo como que es una maquina administradora.
Ejemplo:
version: '3.8'
services:
# Servicio web1
web1:
build:
context: ./httpd
dockerfile: Dockerfile-httpd
networks:
mynetwork:
ipv4_address: 172.20.0.2
# Servicio web2
web2:
build:
context: ./httpd
dockerfile: Dockerfile-httpd
networks:
mynetwork:
ipv4_address: 172.20.0.3
# Servicio de firewall
firewall:
build:
context: ./firewall
dockerfile: Dockerfile-firewall
cap_add:
- NET_ADMIN # Esto otorga privilegios para manipular la red
networks:
mynetwork:
ipv4_address: 172.20.0.4
# Nuevo contenedor Parrot Security OS
parrot:
build:
context: ./parrotsec # Ubicación del Dockerfile para Parrot Security OS
dockerfile: Dockerfile-parrot # Nombre del Dockerfile que contiene las instrucciones
networks:
mynetwork:
ipv4_address: 172.20.0.5
cap_add:
- SYS_ADMIN # Permite algunos privilegios elevados si es necesario para Parrot OS
stdin_open: true # Mantiene la terminal abierta para interacciones
tty: true # Habilita un terminal interactivo
# Definición de la red "mynetwork"
networks:
mynetwork:
driver: bridge
ipam:
config:
- subnet: 172.20.0.0/16 # Subred definida para la red interna
El dockerfile, tambien tenemos que prepararlo para el yml, cambiando o poniendo el nombre del archivo. Crea una carpeta llamada parrotsec en tu proyecto y dentro de ella coloca el Dockerfile-parrot
# Usar la imagen oficial de Parrot Security OS
FROM parrotsec/security:latest
# Actualizar y instalar herramientas
RUN apt-get update && apt-get install -y \
metasploit-framework \
nmap \
burpsuite \
wireshark \
john \
hydra \
git \
vim \
wget \
&& apt-get clean
# Establecer el directorio de trabajo
WORKDIR /root
# Ejecutar un comando para mantener el contenedor activo
CMD [ "bash" ]
docker-compose up en el directorio de tu proyecto. Docker Compose construirá y levantará todos los contenedores
Dentro del conetenedor de parrot ejecuta un nmap para rastrear todas las ips de la red en la que se encuentra.
Si necesitas borrar la red: sudo docker network rm nombreRed Para eliminar un contenedor sudo docker rm nombre o id del contened
Paso 4
Ahora vamos a realizar diferentes rastreos con nmap en la subred.
1. Escaneo básico de una dirección IP en la red:
Supongamos que quieres escanear la dirección IP 172.20.0.2 (que es la dirección IP de tu contenedor web1). Puedes ejecutar el siguiente comando en el contenedor de Parrot:
nmap 172.20.0.2
Este comando realiza un escaneo básico de los puertos más comunes del contenedor web1.
2. Escaneo de todos los puertos:
Si quieres hacer un escaneo de todos los puertos de una máquina en la red, puedes usar la opción -p- para escanear todos los puertos (del 1 al 65535):
nmap -p- 172.20.0.2
Este comando escaneará todos los puertos de la IP 172.20.0.2 (el contenedor web1) para verificar cuáles están abiertos.
3. Escaneo detallado con información de servicios:
Si quieres obtener más información acerca de los servicios que están corriendo en un contenedor (por ejemplo, versión del servicio), puedes usar la opción -sV que realiza un escaneo de versión de servicios:
nmap -sV 172.20.0.2
Esto no solo escaneará los puertos, sino que también intentará detectar la versión de los servicios que están corriendo en esos puertos.
4. Escaneo con detección de sistema operativo:
Puedes agregar la opción -O para intentar detectar el sistema operativo que está ejecutando el contenedor o la máquina objetivo:
nmap -O 172.20.0.2
Este comando intentará identificar el sistema operativo basado en el comportamiento de los puertos y las respuestas de red.
5. Escaneo en una subred completa:
Si deseas escanear toda la red para encontrar qué dispositivos están activos y qué puertos están abiertos, puedes especificar una subred completa. Por ejemplo, si quieres escanear la subred 172.20.0.0/24, puedes usar el siguiente comando:
nmap 172.20.0.0/24
Este comando escaneará todas las direcciones IP de 172.20.0.1 a 172.20.0.254 dentro de la subred 172.20.0.0/24 para ver qué máquinas están activas y qué puertos tienen abiertos.
6. Escaneo de puertos específicos:
Si solo te interesa escanear puertos específicos, puedes usar la opción -p para definir los puertos que quieres escanear. Por ejemplo, si solo te interesa saber si el puerto 80 (HTTP) y 443 (HTTPS) están abiertos en web1, puedes hacer lo siguiente:
nmap -p 80,443 172.20.0.2
Este comando solo escaneará los puertos 80 y 443 en la IP 172.20.0.2.
7. Escaneo silencioso (sin descubrimiento de hosts):
Si quieres escanear sin enviar demasiada información a la red (es decir, hacer un escaneo «silencioso»), puedes usar la opción -Pn que desactiva el descubrimiento de hosts (es decir, no verificará si la máquina está en línea antes de hacer el escaneo):
nmap -Pn 172.20.0.2
Esto puede ser útil si deseas realizar un escaneo sin alertar a sistemas de monitoreo de red, ya que nmap no enviará un paquete de «descubrimiento» al objetivo.
8. Escaneo de una máquina con múltiples servicios (ejemplo de escaneo en Parrot):
Si quisieras escanear tu red en busca de múltiples servicios o máquinas y visualizar la topología de red de manera más detallada, puedes usar el comando siguiente para hacer un escaneo más avanzado:
nmap -sS -sV -O -T4 172.20.0.0/24
Este comando hace lo siguiente:
-sS: Escaneo de tipo «SYN» (más sigiloso).
-sV: Detección de versiones de servicios.
-O: Detección del sistema operativo.
-T4: Ajusta la velocidad del escaneo para hacerlo más rápido.
Escaneará toda la subred 172.20.0.0/24 buscando máquinas activas y proporcionando información detallada sobre los servicios y sistemas operativos detectados.
9. Escaneo de vulnerabilidades con scripts Nmap (NSE):
Nmap incluye una gran cantidad de scripts de detección de vulnerabilidades que puedes ejecutar con el parámetro --script. Por ejemplo, para detectar posibles vulnerabilidades relacionadas con SMB, puedes ejecutar el siguiente comando:
nmap --script smb-vuln* 172.20.0.2
Esto ejecutará todos los scripts de vulnerabilidades SMB que están disponibles en Nmap y tratará de detectar cualquier posible problema en el puerto SMB (445).
Cómo ejecutar los comandos en tu contenedor Parrot:
Accede al contenedor Parrot desde tu máquina host con el siguiente comando:docker exec -it <nombre_o_id_del_contenedor_parrot> bashEl nombre del contenedor lo puedes obtener con docker ps.
Una vez dentro del contenedor, simplemente ejecuta los comandos de nmap como si estuvieras en cualquier otra máquina Linux.
Red interna de Docker: Todos estos escaneos solo serán visibles dentro de la red interna de Docker. Si estás ejecutando estos escaneos desde el contenedor Parrot, solo podrás escanear los contenedores que estén en la misma red (en este caso, mynetwork).
Paso 5 de 80
Vamos a ver ahora el trafico que se produce dentro de la red, para ello usremos wiresark desde la terminal del contenedor de parrot.
Primero verifica las interfaces de red dentro del contenedor:
ip a
Normalmente, la interfaz será eth0. Puedes verificar el tráfico de la subred capturando paquetes en esta interfaz.
3️⃣ Capturar tráfico con Wireshark
Dentro del contenedor Parrot, puedes iniciar Wireshark en modo terminal con tshark:
tshark -i eth0
4️⃣ Generar tráfico entre los contenedores
Desde otro terminal, puedes generar tráfico entre los servicios. Por ejemplo, desde web1 puedes hacer peticiones a web2:
docker exec -it web1 curl http://172.20.0.3
O puedes hacer un ping desde Parrot a web2:
ping -c 4 172.20.0.3
Si quieres capturar únicamente tráfico HTTP (puerto 80), puedes ejecutar:
tshark -i eth0 port 80
Para tráfico ICMP (pings):
tshark -i eth0 icmp
5️⃣ Filtrar tráfico en Wireshark
En la interfaz gráfica de Wireshark, puedes filtrar paquetes con:
ip.addr == 172.20.0.2 → Para ver solo tráfico de web1
ip.addr == 172.20.0.3 → Para ver tráfico de web2
http → Para capturar solo tráfico HTTP
icmp → Para capturar solo tráfico de ping
Paso 6 de 80
Ahora vamos a hacerlo, pero fuera de la subred
Identificar la interfaz de Docker en el host
Docker usa una interfaz virtual llamada bridge para manejar redes internas. Para encontrar la interfaz de la red mynetwork (172.20.0.0/16), ejecuta:
ip a | grep docker
Verás algo como esto:
3: docker0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP inet 172.17.0.1/16 brd 172.17.255.255 scope global docker0
Si la red mynetwork no usa la interfaz docker0, identifica su nombre con:
docker network inspect mynetwork | grep Gateway
El resultado te dará el Gateway y te ayudará a identificar la interfaz.
Capturar tráfico con Wireshark en el host
Abre Wireshark en tu sistema Parrot y selecciona la interfaz de red de Docker, por ejemplo:
docker0
br-xxxxxxxxxxxx (si Docker creó una interfaz bridge específica)
Puedes verificar qué interfaces están activas con:
ip link show
Filtrar tráfico de la subred Docker
Usa estos filtros en Wireshark para ver solo el tráfico de la subred 172.20.0.0/16:
Capturar todo el tráfico de Docker:ip.addr == 172.20.0.0/16
Capturar tráfico HTTP entre los contenedores:tcp.port == 80
Capturar pings (ICMP) entre contenedores:icmp
No olvides generar trafico entre los contenedores mientras haces el rastreo.
Paso 7
En el contenedor Web 1 vamos a instalar PHP para Apache, y vamos a poner una pagina que identifique la ubicación del usuario que hace la petición.
Para acceder desde el navegador del host a la página PHP alojada en uno de tus contenedores web1 o web2, sigue estos pasos:
Exponer el puerto del servidor web en Docker Compose
Actualmente, en tu docker-compose.yml, los servicios web1 y web2no tienen puertos expuestos al host. Para hacerlo, edita el archivo y agrega la sección ports:
services: web1: build: context: ./httpd dockerfile: Dockerfile-httpd networks: mynetwork: ipv4_address: 172.20.0.2 ports: – «8080:80» # Expone el puerto 80 del contenedor como 8080 en el host web2: build: context: ./httpd dockerfile: Dockerfile-httpd networks: mynetwork: ipv4_address: 172.20.0.3 ports: – «8081:80» # Expone el puerto 80 del contenedor como 8081 en el host
Con esta configuración:
web1 será accesible desde el host en http://localhost:8080
web2 será accesible desde el host en http://localhost:8081
Aplicar los cambios y reiniciar los contenedores
Después de editar docker-compose.yml, aplica los cambios reiniciando los contenedores:
docker-compose down
docker-compose up -d
Paso 8
Ahora vamos a subir un conjunto de contenedores a Docker Hub junto con su docker-compose.yml
(espera a que salga algo tipo “ready for connections”.)
1.4 Crear base/tablas (opción guiada en vivo)
Entrar a MySQL:
docker exec -it jee-mysql mysql -u jee -pjee1234 jee_app
Ejemplo de SQL (hazlo con tus tablas reales):
CREATE TABLE IF NOT EXISTS alumnos ( id INT AUTO_INCREMENT PRIMARY KEY, nombre VARCHAR(100) NOT NULL );INSERT INTO alumnos(nombre) VALUES ('Ada'), ('Alan'); SELECT * FROM alumnos;
Salir:
exit
1.5 Preparar Tomcat 10 con tu WAR (sin construir imagen)
Aquí hay dos formas. La más didáctica es montar el WAR como volumen.
FROM tomcat:10.1-jdk17-temurin
RUN rm -rf /usr/local/tomcat/webapps/*
COPY ROOT.war /usr/local/tomcat/webapps/ROOT.war
EXPOSE 8080
2.3 db/init.sql (carga automática al primer arranque)
CREATE TABLE IF NOT EXISTS alumnos ( id INT AUTO_INCREMENT PRIMARY KEY, nombre VARCHAR(100) NOT NULL );INSERT INTO alumnos(nombre) VALUES ('Ada'), ('Alan');