Cuestión 1 — Usuarios, grupos y permisos con sticky bit
Objetivo: el grupo alumnos puede crear y leer archivos en /srv/taller/entregas, pero solo el propietario de cada archivo puede borrarlo. Esto se consigue con permiso de escritura para el grupo en el directorio más el sticky bit, que restringe el borrado al propietario del fichero (o del directorio, o root).
# 1. Crear el grupo alumnos
sudo groupadd alumnos
# 2. Crear el directorio (toda la ruta) y asignar propietario:grupo
sudo mkdir -p /srv/taller/entregas
sudo chown profesor:alumnos /srv/taller/entregas
# 3. Fijar permisos: rwx propietario, rws grupo (setgid), sticky bit
# 2 = setgid, 1 = sticky -> modo 3770
sudo chmod 3770 /srv/taller/entregas
# Equivalente simbólico:
sudo chmod u=rwx,g=rwx,o=,g+s,+t /srv/taller/entregas
Resultado de ls -ld /srv/taller/entregas:
drwxrws--T 2 profesor alumnos 4096 ... /srv/taller/entregas
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 760 250" font-family="ui-sans-serif, system-ui, Arial, sans-serif">
<text x="380" y="26" text-anchor="middle" font-size="12" fill="#64748b">Descomposición de la cadena de permisos (ls -ld)</text>
<!-- Grupo tipo -->
<rect x="115" y="48" width="44" height="46" rx="6" fill="#eef2ff" stroke="#6366f1" stroke-width="1.6"/>
<text x="137" y="79" text-anchor="middle" font-size="22" font-weight="bold" fill="#0f172a">d</text>
<!-- Grupo propietario -->
<rect x="181" y="48" width="44" height="46" rx="6" fill="#eff6ff" stroke="#2563eb" stroke-width="1.6"/>
<text x="203" y="79" text-anchor="middle" font-size="22" font-weight="bold" fill="#0f172a">r</text>
<rect x="229" y="48" width="44" height="46" rx="6" fill="#eff6ff" stroke="#2563eb" stroke-width="1.6"/>
<text x="251" y="79" text-anchor="middle" font-size="22" font-weight="bold" fill="#0f172a">w</text>
<rect x="277" y="48" width="44" height="46" rx="6" fill="#eff6ff" stroke="#2563eb" stroke-width="1.6"/>
<text x="299" y="79" text-anchor="middle" font-size="22" font-weight="bold" fill="#0f172a">x</text>
<!-- Grupo grupo -->
<rect x="343" y="48" width="44" height="46" rx="6" fill="#ecfdf5" stroke="#059669" stroke-width="1.6"/>
<text x="365" y="79" text-anchor="middle" font-size="22" font-weight="bold" fill="#0f172a">r</text>
<rect x="391" y="48" width="44" height="46" rx="6" fill="#ecfdf5" stroke="#059669" stroke-width="1.6"/>
<text x="413" y="79" text-anchor="middle" font-size="22" font-weight="bold" fill="#0f172a">w</text>
<rect x="439" y="48" width="44" height="46" rx="6" fill="#059669" stroke="#059669" stroke-width="1.6"/>
<text x="461" y="79" text-anchor="middle" font-size="22" font-weight="bold" fill="#ffffff">s</text>
<!-- Grupo otros -->
<rect x="505" y="48" width="44" height="46" rx="6" fill="#e2e8f0" stroke="#64748b" stroke-width="1.6"/>
<text x="527" y="79" text-anchor="middle" font-size="22" font-weight="bold" fill="#0f172a">-</text>
<rect x="553" y="48" width="44" height="46" rx="6" fill="#e2e8f0" stroke="#64748b" stroke-width="1.6"/>
<text x="575" y="79" text-anchor="middle" font-size="22" font-weight="bold" fill="#0f172a">-</text>
<rect x="601" y="48" width="44" height="46" rx="6" fill="#d97706" stroke="#d97706" stroke-width="1.6"/>
<text x="623" y="79" text-anchor="middle" font-size="22" font-weight="bold" fill="#ffffff">T</text>
<!-- Etiquetas de grupo -->
<text x="137" y="112" text-anchor="middle" font-size="11" font-weight="bold" fill="#6366f1">tipo</text>
<text x="137" y="127" text-anchor="middle" font-size="10" fill="#6366f1">directorio</text>
<text x="251" y="112" text-anchor="middle" font-size="11" font-weight="bold" fill="#2563eb">propietario</text>
<text x="251" y="127" text-anchor="middle" font-size="10" fill="#2563eb">rwx</text>
<text x="413" y="112" text-anchor="middle" font-size="11" font-weight="bold" fill="#059669">grupo alumnos</text>
<text x="413" y="127" text-anchor="middle" font-size="10" fill="#059669">s = setgid</text>
<text x="575" y="112" text-anchor="middle" font-size="11" font-weight="bold" fill="#d97706">otros</text>
<text x="575" y="127" text-anchor="middle" font-size="10" fill="#d97706">T = sticky</text>
<!-- Notas -->
<rect x="40" y="152" width="680" height="40" rx="8" fill="#ecfdf5" stroke="#059669" stroke-width="1.4"/>
<text x="56" y="177" font-size="12" fill="#0f172a"><tspan font-weight="bold">s</tspan> (setgid): los archivos nuevos heredan el grupo «alumnos», no el grupo primario del alumno.</text>
<rect x="40" y="200" width="680" height="40" rx="8" fill="#fffbeb" stroke="#d97706" stroke-width="1.4"/>
<text x="56" y="225" font-size="12" fill="#0f172a"><tspan font-weight="bold">T</tspan> (sticky): cada alumno solo puede borrar o renombrar SUS propios archivos.</text>
</svg>
Figura 1. Anatomía de los permisos drwxrws--T: los diez caracteres desglosados en tipo, propietario, grupo (setgid) y otros (sticky).
Interpretación de la terna drwxrws--T:
d → es un directorio.
rwx (propietario profesor) → el profesor puede leer el contenido, modificarlo (crear/borrar) y entrar (x).
rws (grupo alumnos) → el grupo puede leer (r), escribir/crear (w) y entrar (x); la s indica el setgid activo: todo archivo nuevo creado dentro heredará el grupo alumnos (que las entregas pertenezcan al grupo común, no al grupo primario del alumno). Como hay x debajo, aparece s minúscula.
--T (otros) → los demás usuarios no tienen ningún permiso (---); la T mayúscula es el sticky bit activo sin permiso de ejecución para «otros» (si lo tuvieran sería t minúscula). El sticky bit es lo que garantiza que un alumno solo pueda borrar o renombrar sus propios archivos, aunque tenga permiso w sobre el directorio.
Convención de las letras especiales: minúscula (s/t) = bit especial activo y además permiso de ejecución; mayúscula (S/T) = bit especial activo sin permiso de ejecución debajo.
Para que el setgid actúe también sobre los permisos heredados conviene fijar el umask o usar ACL por defecto:
# Opción con ACL por defecto: archivos nuevos legibles/escribibles por el grupo
sudo setfacl -d -m g:alumnos:rw /srv/taller/entregas
Cuestión 2 — Cortafuegos con iptables
Guion iptables ordenado (las reglas se evalúan de arriba abajo; las políticas restrictivas se aplican al final una vez añadidas las excepciones):
#!/bin/bash
# ------- Limpieza inicial -------
iptables -F # vacía todas las reglas
iptables -X # borra cadenas de usuario
# ------- Políticas por defecto -------
iptables -P INPUT DROP # todo lo que entra se descarta salvo excepción
iptables -P FORWARD DROP # no enrutamos
iptables -P OUTPUT ACCEPT # permitimos la salida (respuestas del servidor)
# ------- 1) Tráfico de loopback (servicios locales) -------
iptables -A INPUT -i lo -j ACCEPT
# ------- 2) Conexiones ya establecidas / relacionadas -------
# Permite las respuestas a conexiones que el servidor inició o aceptó
iptables -A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
# ------- 3) SSH (22) solo desde la subred de administración -------
iptables -A INPUT -p tcp -s 172.16.0.160/28 --dport 22 -j ACCEPT
# ------- 4) HTTP (80) y HTTPS (443) desde cualquier origen -------
iptables -A INPUT -p tcp --dport 80 -j ACCEPT
iptables -A INPUT -p tcp --dport 443 -j ACCEPT
# (opcional) registrar lo descartado antes del DROP por defecto
iptables -A INPUT -j LOG --log-prefix "IPTABLES-DROP: " --log-level 4
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 760 430" font-family="ui-sans-serif, system-ui, Arial, sans-serif">
<!-- Entrada -->
<rect x="120" y="16" width="520" height="40" rx="8" fill="#e2e8f0" stroke="#64748b" stroke-width="1.5"/>
<text x="380" y="41" text-anchor="middle" font-size="13" font-weight="bold" fill="#0f172a">Paquete entrante — cadena INPUT</text>
<line x1="380" y1="56" x2="380" y2="74" stroke="#334155" stroke-width="2"/>
<polygon points="380,74 374,64 386,64" fill="#334155"/>
<!-- Regla 1 -->
<rect x="120" y="74" width="520" height="46" rx="8" fill="#ecfdf5" stroke="#059669" stroke-width="1.4"/>
<text x="138" y="103" font-size="12" fill="#0f172a">Interfaz loopback ( -i lo )</text>
<rect x="525" y="82" width="100" height="30" rx="6" fill="#059669"/>
<text x="575" y="102" text-anchor="middle" font-size="11" font-weight="bold" fill="#ffffff">ACCEPT</text>
<line x1="380" y1="120" x2="380" y2="140" stroke="#334155" stroke-width="2"/>
<polygon points="380,140 374,130 386,130" fill="#334155"/>
<!-- Regla 2 -->
<rect x="120" y="140" width="520" height="46" rx="8" fill="#ecfdf5" stroke="#059669" stroke-width="1.4"/>
<text x="138" y="169" font-size="12" fill="#0f172a">Estado ESTABLISHED / RELATED</text>
<rect x="525" y="148" width="100" height="30" rx="6" fill="#059669"/>
<text x="575" y="168" text-anchor="middle" font-size="11" font-weight="bold" fill="#ffffff">ACCEPT</text>
<line x1="380" y1="186" x2="380" y2="206" stroke="#334155" stroke-width="2"/>
<polygon points="380,206 374,196 386,196" fill="#334155"/>
<!-- Regla 3 -->
<rect x="120" y="206" width="520" height="46" rx="8" fill="#ecfdf5" stroke="#059669" stroke-width="1.4"/>
<text x="138" y="235" font-size="12" fill="#0f172a">SSH 22 · origen 172.16.0.160/28</text>
<rect x="525" y="214" width="100" height="30" rx="6" fill="#059669"/>
<text x="575" y="234" text-anchor="middle" font-size="11" font-weight="bold" fill="#ffffff">ACCEPT</text>
<line x1="380" y1="252" x2="380" y2="272" stroke="#334155" stroke-width="2"/>
<polygon points="380,272 374,262 386,262" fill="#334155"/>
<!-- Regla 4 -->
<rect x="120" y="272" width="520" height="46" rx="8" fill="#ecfdf5" stroke="#059669" stroke-width="1.4"/>
<text x="138" y="301" font-size="12" fill="#0f172a">HTTP 80 / HTTPS 443 · cualquier origen</text>
<rect x="525" y="280" width="100" height="30" rx="6" fill="#059669"/>
<text x="575" y="300" text-anchor="middle" font-size="11" font-weight="bold" fill="#ffffff">ACCEPT</text>
<line x1="380" y1="318" x2="380" y2="338" stroke="#334155" stroke-width="2"/>
<polygon points="380,338 374,328 386,328" fill="#334155"/>
<!-- Regla final: politica -->
<rect x="120" y="338" width="520" height="46" rx="8" fill="#fef2f2" stroke="#dc2626" stroke-width="1.4"/>
<text x="138" y="367" font-size="12" fill="#0f172a">Cualquier otro paquete (política por defecto)</text>
<rect x="525" y="346" width="100" height="30" rx="6" fill="#dc2626"/>
<text x="575" y="366" text-anchor="middle" font-size="11" font-weight="bold" fill="#ffffff">DROP</text>
<!-- Nota -->
<text x="380" y="404" text-anchor="middle" font-size="11" fill="#64748b">Evaluación de arriba abajo: a la primera coincidencia se aplica la acción.</text>
<text x="380" y="420" text-anchor="middle" font-size="11" fill="#64748b">Si ninguna regla acepta, la política por defecto DROP descarta el paquete.</text>
</svg>
Figura 2. Orden de evaluación de la cadena INPUT: excepciones ACCEPT primero y política DROP al final.
Comentario por bloques:
- Limpieza (
-F, -X): se parte de un estado limpio para evitar reglas residuales de arranques anteriores.
- Políticas por defecto:
INPUT DROP materializa el principio de lista blanca (denegar todo y permitir solo lo necesario). OUTPUT ACCEPT deja salir las respuestas del servidor.
- Loopback (
-i lo): imprescindible; muchos servicios (Apache↔BD, sockets internos) hablan por 127.0.0.1. Sin esta regla, con política DROP, se romperían.
- ESTABLISHED,RELATED (módulo
conntrack): permite los paquetes de conexiones ya válidas. Sin ella, aunque admitiéramos el SYN inicial, las respuestas posteriores se bloquearían.
- SSH restringido (
-s 172.16.0.160/28): la /28 da 2^{32-28} = 16 direcciones (172.16.0.160–172.16.0.175); solo desde esa subred de administración se acepta el puerto 22, reduciendo la superficie de ataque al servicio de gestión.
- HTTP/HTTPS: la intranet (Apache) debe ser accesible por todo el centro, así que 80 y 443 se abren sin restricción de origen.
- LOG: opcional, registra en el syslog lo que cae al DROP por defecto, útil para diagnóstico.
Persistencia (Debian/Ubuntu/Lliurex):
sudo apt install iptables-persistent
sudo netfilter-persistent save # guarda en /etc/iptables/rules.v4
Cuestión 3 — Acceso remoto seguro por par de claves SSH
Paso 1 — Generar el par de claves en el equipo del administrador (cliente):
ssh-keygen -t ed25519 -a 100 -C "admin@taller.local"
# (alternativa clásica: ssh-keygen -t rsa -b 4096)
Genera ~/.ssh/id_ed25519 (clave privada, nunca se comparte) y ~/.ssh/id_ed25519.pub (clave pública). Conviene proteger la privada con passphrase.
Paso 2 — Copiar la clave pública al servidor:
ssh-copy-id -i ~/.ssh/id_ed25519.pub admin@172.16.0.161
Esto añade la clave pública al fichero ~/.ssh/authorized_keys del usuario admin en el servidor, con los permisos correctos (700 en ~/.ssh, 600 en authorized_keys). Manualmente sería:
ssh admin@172.16.0.161 "mkdir -p ~/.ssh && chmod 700 ~/.ssh"
cat ~/.ssh/id_ed25519.pub | ssh admin@172.16.0.161 "cat >> ~/.ssh/authorized_keys && chmod 600 ~/.ssh/authorized_keys"
Paso 3 — Verificar que la clave funciona ANTES de endurecer (crítico para no quedarse fuera):
ssh admin@172.16.0.161 # debe entrar sin pedir la contraseña del sistema
Paso 4 — Endurecer /etc/ssh/sshd_config en el servidor:
# Solo autenticación por clave pública
PubkeyAuthentication yes
# Prohibir login directo de root
PermitRootLogin no
# Deshabilitar autenticación por contraseña (y métodos relacionados)
PasswordAuthentication no
ChallengeResponseAuthentication no
KbdInteractiveAuthentication no
UsePAM yes
# Endurecimiento adicional recomendado
Protocol 2
MaxAuthTries 3
AllowUsers admin
Paso 5 — Comprobar la sintaxis y recargar el servicio:
sudo sshd -t # valida sshd_config (sin errores = OK)
sudo systemctl reload ssh # (o 'sshd' según distro)
Recomendación: mantén una sesión SSH abierta mientras compruebas, por si hay que revertir. Con PermitRootLogin no y PasswordAuthentication no se elimina el ataque por fuerza bruta de contraseñas y el acceso directo a root.
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 760 330" font-family="ui-sans-serif, system-ui, Arial, sans-serif">
<!-- Caja Cliente -->
<rect x="30" y="40" width="320" height="180" rx="10" fill="#eff6ff" stroke="#2563eb" stroke-width="1.8"/>
<rect x="46" y="52" width="170" height="22" rx="6" fill="#2563eb"/>
<text x="131" y="67" text-anchor="middle" font-size="11" font-weight="bold" fill="#ffffff">Cliente (equipo admin)</text>
<rect x="48" y="88" width="284" height="32" rx="6" fill="#f8fafc" stroke="#64748b" stroke-width="1.3"/>
<text x="190" y="108" text-anchor="middle" font-size="12" fill="#0f172a">ssh-keygen -t ed25519</text>
<rect x="48" y="134" width="138" height="58" rx="6" fill="#fef2f2" stroke="#dc2626" stroke-width="1.4"/>
<text x="117" y="160" text-anchor="middle" font-size="11" font-weight="bold" fill="#0f172a">id_ed25519</text>
<text x="117" y="178" text-anchor="middle" font-size="10" fill="#dc2626">privada · secreta</text>
<rect x="194" y="134" width="138" height="58" rx="6" fill="#eff6ff" stroke="#2563eb" stroke-width="1.4"/>
<text x="263" y="160" text-anchor="middle" font-size="11" font-weight="bold" fill="#0f172a">id_ed25519.pub</text>
<text x="263" y="178" text-anchor="middle" font-size="10" fill="#2563eb">pública</text>
<!-- Caja Servidor -->
<rect x="410" y="40" width="320" height="180" rx="10" fill="#ecfdf5" stroke="#059669" stroke-width="1.8"/>
<rect x="426" y="52" width="190" height="22" rx="6" fill="#059669"/>
<text x="521" y="67" text-anchor="middle" font-size="11" font-weight="bold" fill="#ffffff">Servidor taller.local</text>
<rect x="430" y="120" width="284" height="48" rx="6" fill="#f8fafc" stroke="#64748b" stroke-width="1.3"/>
<text x="572" y="142" text-anchor="middle" font-size="12" font-weight="bold" fill="#0f172a">~/.ssh/authorized_keys</text>
<text x="572" y="160" text-anchor="middle" font-size="10" fill="#059669">claves públicas autorizadas</text>
<!-- Flecha ssh-copy-id -->
<line x1="332" y1="163" x2="428" y2="144" stroke="#334155" stroke-width="1.8"/>
<polygon points="428,144 416,143 419,153" fill="#334155"/>
<text x="380" y="136" text-anchor="middle" font-size="10" font-weight="bold" fill="#2563eb">ssh-copy-id</text>
<!-- Handshake -->
<rect x="30" y="246" width="700" height="74" rx="10" fill="#eef2ff" stroke="#6366f1" stroke-width="1.6"/>
<text x="380" y="268" text-anchor="middle" font-size="12" font-weight="bold" fill="#6366f1">Handshake de autenticación</text>
<text x="380" y="288" text-anchor="middle" font-size="11" fill="#0f172a">El servidor envía un reto aleatorio; el cliente lo firma con su clave privada.</text>
<text x="380" y="306" text-anchor="middle" font-size="11" fill="#0f172a">El servidor lo verifica con la pública → acceso sin contraseña.</text>
</svg>
Figura 3. Acceso SSH sin contraseña por par de claves: el cliente genera el par, ssh-copy-id sube la pública y el handshake firma con la privada.
Cuestión 4 — Zona directa DNS para taller.local
Fichero de zona BIND (/etc/bind/db.taller.local):
$TTL 86400
$ORIGIN taller.local.
; ----- Registro SOA -----
@ IN SOA ns1.taller.local. admin.taller.local. (
2026062101 ; Serial (AAAAMMDDnn)
3600 ; Refresh (1 h)
1800 ; Retry (30 min)
1209600 ; Expire (2 semanas)
86400 ) ; Negative TTL / Minimum (1 día)
; ----- Servidores de nombres (NS) -----
@ IN NS ns1.taller.local.
@ IN NS ns2.taller.local.
; ----- Registros A (IPv4) -----
servidor IN A 172.16.0.161
ns1 IN A 172.16.0.161
ns2 IN A 172.16.0.162
; ----- Registro AAAA (IPv6) -----
servidor IN AAAA 2001:db8::161
; ----- Registro MX (correo) -----
@ IN MX 10 servidor.taller.local.
; ----- Alias CNAME -----
intranet IN CNAME servidor.taller.local.
Justificación de cada elemento:
$TTL 86400: tiempo de vida por defecto de los registros (1 día) para las cachés resolutoras.
SOA: declara el servidor maestro (ns1), el correo del responsable (admin.taller.local., donde la primera . sustituye a la @) y los temporizadores. El Serial debe incrementarse en cada cambio (formato fecha 2026062101) para que los esclavos detecten la actualización.
- Dos
NS: ns1 y ns2, redundancia del servicio de nombres.
A: mapea el nombre servidor a la IPv4 172.16.0.161 (IP de servidores del diseño de red).
AAAA: mapea el mismo host a su dirección IPv6.
MX 10: indica el servidor de correo de la zona, con prioridad 10 (menor número = mayor preferencia).
CNAME intranet: alias que apunta a servidor.taller.local.; así http://intranet.taller.local resuelve al servidor Apache. Importante: un nombre con CNAME no puede tener otros registros (regla DNS).
Detalle clave: los FQDN terminan en punto (.) para indicar nombre absoluto; sin él, BIND añade el $ORIGIN.
Cuestión 5 — Diagnóstico: «la intranet no carga» pero el ping responde
El ping correcto indica que la capa de red (L3) y el host funcionan; el problema está en una capa superior (servicio, puerto, cortafuegos o resolución de nombres). Diagnóstico por capas:
(a) ¿Apache está activo y en qué puerto escucha?
# Estado del servicio
sudo systemctl status apache2
# Esperado: "active (running)". Si aparece "inactive/failed",
# arrancarlo: sudo systemctl start apache2 (y 'enable' para el arranque)
# Puertos en escucha (ss, moderno)
sudo ss -tlnp | grep -E ':80|:443'
# Esperado: LISTEN 0 511 *:80 ... users:(("apache2",...))
# LISTEN 0 511 *:443 ...
# Alternativa con netstat
sudo netstat -tlnp | grep apache2
# Qué proceso tiene abierto el puerto 80
sudo lsof -i :80
# Esperado: procesos 'apache2' en estado LISTEN
Si Apache no escucha en 80/443, revisar /etc/apache2/ports.conf y los VirtualHost, y los logs:
sudo journalctl -u apache2 --since "10 min ago"
sudo tail -n 50 /var/log/apache2/error.log
sudo apache2ctl configtest # valida la configuración (Syntax OK)
(b) ¿El cortafuegos bloquea el puerto?
# Listar reglas con números y sin resolver nombres
sudo iptables -L INPUT -n -v --line-numbers
# Esperado: reglas ACCEPT para tcp dpt:80 y dpt:443 ANTES del DROP
# Prueba de conectividad al puerto desde un cliente del aula
nc -zv 172.16.0.161 80
# Esperado: "Connection to 172.16.0.161 80 port [tcp/http] succeeded!"
Tras un reinicio, un fallo típico es que las reglas no se hayan persistido (DROP por defecto sin las excepciones de 80/443). Solución: recargar el script o netfilter-persistent reload, y comprobar que iptables-persistent guardó las reglas.
(c) ¿Es problema de resolución de nombres?
El usuario accede por http://intranet.taller.local. Si el ping por IP funciona pero por nombre no, el fallo es de DNS.
# Resolver el nombre contra el DNS interno
dig intranet.taller.local @172.16.0.161
# o: nslookup intranet.taller.local 172.16.0.161
# Esperado: el CNAME a servidor.taller.local y el A 172.16.0.161
# ¿Responde el servicio DNS (bind9)?
sudo systemctl status bind9 # Esperado: active (running)
sudo ss -ulnp | grep :53 # puerto 53 UDP en escucha
# Comprobar el resolutor del cliente
cat /etc/resolv.conf # nameserver debe apuntar al DNS interno
# Descartar el problema probando directamente por IP
ping -c1 intranet.taller.local # si falla por nombre pero la IP responde -> DNS
Si dig no devuelve la dirección, revisar la zona (cuestión 4): serial incrementado, recarga con sudo rndc reload taller.local, sintaxis con named-checkzone taller.local /etc/bind/db.taller.local, y que el cliente tenga el DNS interno en resolv.conf.
Resumen del flujo de diagnóstico: host vivo (ping OK) → servicio Apache active → puerto 80/443 en LISTEN (ss/lsof) → cortafuegos con ACCEPT en esos puertos (iptables -L) → nombre que resuelve a la IP correcta (dig/resolv.conf). El primer eslabón que falle señala la causa.
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 760 430" font-family="ui-sans-serif, system-ui, Arial, sans-serif">
<!-- Paso 1 -->
<rect x="90" y="20" width="580" height="54" rx="9" fill="#f8fafc" stroke="#64748b" stroke-width="1.4"/>
<rect x="104" y="31" width="32" height="32" rx="6" fill="#2563eb"/>
<text x="120" y="53" text-anchor="middle" font-size="16" font-weight="bold" fill="#ffffff">1</text>
<text x="150" y="45" font-size="12.5" font-weight="bold" fill="#0f172a">Host vivo — el ping responde</text>
<text x="150" y="64" font-size="11" fill="#2563eb">ping -c1 172.16.0.161</text>
<line x1="380" y1="74" x2="380" y2="92" stroke="#334155" stroke-width="2"/>
<polygon points="380,92 374,82 386,82" fill="#334155"/>
<!-- Paso 2 -->
<rect x="90" y="92" width="580" height="54" rx="9" fill="#f8fafc" stroke="#64748b" stroke-width="1.4"/>
<rect x="104" y="103" width="32" height="32" rx="6" fill="#059669"/>
<text x="120" y="125" text-anchor="middle" font-size="16" font-weight="bold" fill="#ffffff">2</text>
<text x="150" y="117" font-size="12.5" font-weight="bold" fill="#0f172a">¿Apache activo?</text>
<text x="150" y="136" font-size="11" fill="#059669">systemctl status apache2</text>
<line x1="380" y1="146" x2="380" y2="164" stroke="#334155" stroke-width="2"/>
<polygon points="380,164 374,154 386,154" fill="#334155"/>
<!-- Paso 3 -->
<rect x="90" y="164" width="580" height="54" rx="9" fill="#f8fafc" stroke="#64748b" stroke-width="1.4"/>
<rect x="104" y="175" width="32" height="32" rx="6" fill="#6366f1"/>
<text x="120" y="197" text-anchor="middle" font-size="16" font-weight="bold" fill="#ffffff">3</text>
<text x="150" y="189" font-size="12.5" font-weight="bold" fill="#0f172a">¿Escucha en 80 / 443? (LISTEN)</text>
<text x="150" y="208" font-size="11" fill="#6366f1">ss -tlnp | grep -E ':80|:443'</text>
<line x1="380" y1="218" x2="380" y2="236" stroke="#334155" stroke-width="2"/>
<polygon points="380,236 374,226 386,226" fill="#334155"/>
<!-- Paso 4 -->
<rect x="90" y="236" width="580" height="54" rx="9" fill="#f8fafc" stroke="#64748b" stroke-width="1.4"/>
<rect x="104" y="247" width="32" height="32" rx="6" fill="#d97706"/>
<text x="120" y="269" text-anchor="middle" font-size="16" font-weight="bold" fill="#ffffff">4</text>
<text x="150" y="261" font-size="12.5" font-weight="bold" fill="#0f172a">¿Cortafuegos con ACCEPT?</text>
<text x="150" y="280" font-size="11" fill="#d97706">iptables -L INPUT -n -v</text>
<line x1="380" y1="290" x2="380" y2="308" stroke="#334155" stroke-width="2"/>
<polygon points="380,308 374,298 386,298" fill="#334155"/>
<!-- Paso 5 -->
<rect x="90" y="308" width="580" height="54" rx="9" fill="#f8fafc" stroke="#64748b" stroke-width="1.4"/>
<rect x="104" y="319" width="32" height="32" rx="6" fill="#dc2626"/>
<text x="120" y="341" text-anchor="middle" font-size="16" font-weight="bold" fill="#ffffff">5</text>
<text x="150" y="333" font-size="12.5" font-weight="bold" fill="#0f172a">¿DNS resuelve el nombre?</text>
<text x="150" y="352" font-size="11" fill="#dc2626">dig intranet.taller.local</text>
<!-- Nota -->
<rect x="90" y="378" width="580" height="40" rx="8" fill="#fffbeb" stroke="#d97706" stroke-width="1.4"/>
<text x="380" y="403" text-anchor="middle" font-size="12" fill="#0f172a">El primer eslabón que falle señala la causa de la incidencia.</text>
</svg>
Figura 4. Diagnóstico por capas: se comprueba host, servicio, puerto, cortafuegos y DNS en orden hasta hallar el eslabón que falla.