RETO 1 en parejas (vlb36): tu compañero entra en tu servidor de Internet

🏁 RETO 1 en parejas (vlb36): tu compañero entra en tu servidor de Internet

2º ASIR · Cliente SSH: tu MADLinuX · Servidor SSH: tu contenedor LXC en ValdeLAB36 (valdelab36.art) Guías: 1 servidor ssh · RETO 1 VirtualBox · RETO 1 vlb36 (este) · 2 scp y rsync (próximamente)

Objetivo: dar acceso a tu servidor a un compañero de verdad, con su clave, sin darle más poder del necesario, y después quitárselo. Todo en un servidor expuesto a Internet.

Requisito previo: tener hecha la práctica P0, con tu clave vlb36 en tu USB y el ritual de inicio de clase hecho (P0, apartado 2.1 «🎒 Tu clave va contigo»). Compruébalo:

PC_A$ ssh-add -l                                                           # debe aparecer tu clave
PC_A$ ssh -o PasswordAuthentication=no -p PUERTO_A apellidoA@valdelab36.art   # debe entrar SIN pedir contraseña

⛔ Si esto no funciona, no sigas: arregla primero tu clave (P0) o pide ayuda.


0. Escenario y convenciones

En esta ocasión, en vez de conectarnos a nuestra máquina virtual (VirtualBox) en MAX en local (en Pinto, en el aula vaya), nos conectamos al servidor aldebaran / Valdelab36.art , allá por Valdezarza (en Madrid). Para las mentes curiosas, dicho servidor usa la tecnología LinuX Containers (LXC), es decir, de alguna manera un entorno también aislado pero a la vez conectado a Internet.

Trabajáis en parejas: A pone su contenedor, B se conecta. Después, cambiáis los papeles.

  PC de B                aldebaran (valdelab36.art)              LXC de A
  ┌─────────────┐        ┌──────────────────────────┐            ┌───────────────────┐
  │ cliente ssh │ ─────► │ proxy de Incus  :PUERTO_A │ ─────────► │ sshd  127.0.0.1:22│
  │ (B)         │Internet│ (un puerto por alumno)    │            │ apellidoA, B, fenix│
  └─────────────┘        └──────────────────────────┘            └───────────────────┘
Símbolo Significa
PC_A$ / PC_B$ terminal del MADLinuX de A / de B
LXC_A$ terminal dentro del contenedor de A (entrando por SSH desde PC_A)
PUERTO_A el puerto SSH de A (tabla de clase: 22XX, donde XX es su número)
apellidoA / apellidoB vuestros usuarios (apellido en minúsculas, sin acentos)

🗺️ La puerta ya está abierta. Tu contenedor no tiene IP pública: aldebaran recibe la conexión en tu puerto y el proxy de Incus la entrega al sshd de tu contenedor. Por eso el puerto es la dirección: con el puerto de otro, llamas a su puerta.

⚠️ Estás en Internet. Bots de todo el mundo prueban estos puertos a diario. Todo lo que configures aquí es de verdad.


1. 🅱️ Enviar tu clave pública

Usa la clave de la práctica P0:

PC_B$ cat ~/.ssh/vlb36.pub
# ssh-ed25519 AAAAC3Nza...muy larga... b@madlinux

Envía esa línea completa a A por el chat o el correo de EducaMadrid. Es pública: no pasa nada si alguien más la ve.

⛔ Nunca envíes ~/.ssh/vlb36 (sin .pub): es tu clave privada. Quien la tenga, es tú.


2. 🅰️ Crear la cuenta de B (con lo mínimo)

LXC_A$ sudo adduser --disabled-password --comment "" apellidoB
  • --disabled-password: la cuenta no tiene contraseña. B solo podrá entrar con su clave.
  • No le damos sudo: B es un invitado, no un administrador. Es el principio de mínimo privilegio: a cada uno, solo el poder que necesita.

3. 🅰️ Instalar la clave de B

En tu sesión SSH (desde PC_A puedes pegar la línea que te envió B):

LXC_A$ sudo -u apellidoB mkdir -p -m 700 /home/apellidoB/.ssh
LXC_A$ echo 'ssh-ed25519 AAAAC3Nza...PEGA-AQUÍ... b@madlinux' | sudo -u apellidoB tee -a /home/apellidoB/.ssh/authorized_keys
LXC_A$ sudo -u apellidoB chmod 600 /home/apellidoB/.ssh/authorized_keys

💡 sudo -u apellidoB ejecuta el comando como B: la carpeta y el archivo ya son suyos, sin chown. La clave debe quedar en una sola línea.


4. 🅰️ Blindar el servidor

Primero, tu plan B: los PCs del aula se borran en cada reinicio, y algún día olvidarás el USB. Por eso tú (el dueño) conservarás la contraseña como plan B. Pero estás en Internet: cambia la contraseña que te dio el profesor por una robusta (larga, que no uses en ningún otro sitio):

LXC_A$ passwd

Ahora el blindaje:

LXC_A$ sudo nano /etc/ssh/sshd_config.d/10-aula.conf
PermitRootLogin no
PasswordAuthentication no
AllowUsers apellidoA apellidoB fenix

Match User apellidoA
    PasswordAuthentication yes
Directiva Para qué sirve
PasswordAuthentication no nadie entra con contraseña…
Match User apellidoA + PasswordAuthentication yes …excepto tú: tu plan B si olvidas el USB. B solo puede entrar con su clave

💡 El bloque Match va siempre al final del fichero: todo lo que escribas debajo solo se aplica a ese usuario.

⚠️ Tres usuarios en AllowUsers, obligatorio:

  • apellidoA: tú. Si te olvidas, te quedas fuera.
  • apellidoB: tu compañero.
  • fenix: el profesor, que administra todos los contenedores. Si falta, el profesor no puede entrar a ayudarte.

Aplicar, siempre en este orden y sin cerrar tu sesión:

LXC_A$ sudo sshd -t                         # 1) sintaxis (sin mensajes = OK)
LXC_A$ sudo systemctl reload ssh            # 2) recargar
PC_A$  ssh -p PUERTO_A apellidoA@valdelab36.art                   # 3) en OTRA terminal: ¿sigues entrando (con clave)?
PC_A$  ssh -o PubkeyAuthentication=no -p PUERTO_A apellidoA@valdelab36.art   # 4) ¿y tu plan B (contraseña)?

🆘 Si en las pruebas 3 o 4 no entras: no cierres la sesión que tienes abierta. Desde ella, corrige 10-aula.conf, sshd -t y reload. Si ya la cerraste, solo el profesor puede rescatarte.


5. 🅱️ Primera conexión: ¿es la puerta correcta?

PC_B$ ssh -i ~/.ssh/vlb36 -p PUERTO_A apellidoB@valdelab36.art
# The authenticity of host '[valdelab36.art]:PUERTO_A' can't be established.
# ED25519 key fingerprint is SHA256:xxxxxxxx...

Antes de escribir yes, A lee en voz alta la huella de su servidor:

LXC_A$ ssh-keygen -lf /etc/ssh/ssh_host_ed25519_key.pub

Si coincide carácter a carácter, yes. Cada servidor tiene su propia huella (su «DNI»): si coincide, estás en la puerta de A.


6. ✅ Pruebas (desde el PC de B)

Prueba Resultado esperado
ssh -i ~/.ssh/vlb36 -p PUERTO_A apellidoB@valdelab36.art 'hostname' ✅ entra sin contraseña y responde el apellido de A (el nombre del contenedor)
Dentro: groups ✅ no aparece sudo
Dentro: cat /etc/shadow ❌ Permission denied: B no es administrador
ssh -p PUERTO_A root@valdelab36.art ❌ Permission denied
ssh -p PUERTO_A intruso@valdelab36.art ❌ Permission denied
ssh -o PubkeyAuthentication=no -p PUERTO_A apellidoB@valdelab36.art ❌ Permission denied (publickey): B sin clave no tiene forma de entrar
(desde el PC de A) ssh -o PubkeyAuthentication=no -p PUERTO_A apellidoA@valdelab36.art ✅ pide contraseña: el plan B del dueño funciona

Y desde el contenedor de A, mirad quién ha entrado:

LXC_A$ who
LXC_A$ sudo journalctl -u ssh | grep apellidoB     # busca: Accepted publickey for apellidoB from ...

7. 🔒 Revocar el acceso

La visita ha terminado. Un buen administrador retira los accesos que ya no hacen falta:

LXC_A$ sudo nano /etc/ssh/sshd_config.d/10-aula.conf     # AllowUsers apellidoA fenix   (quita a B)
LXC_A$ sudo sshd -t && sudo systemctl reload ssh
LXC_A$ sudo deluser --remove-home apellidoB              # borra la cuenta y su clave

B lo comprueba: ssh -i ~/.ssh/vlb36 -p PUERTO_A apellidoB@valdelab36.art → ❌ Permission denied.


8. 🔄 Cambiad los papeles

Ahora B pone su contenedor y A se conecta. Repetid los pasos 1 a 7.


🤔 Preguntas para reflexionar (en el cuaderno)

  1. En el journalctl del paso 6, ¿desde qué IP dice tu contenedor que entró B? ¿Por qué no es la IP real de B? (Pista: ¿quién abre la conexión hacia tu sshd?) Si quisieras bloquear a un atacante por su IP dentro de tu contenedor, ¿podrías?
  2. ¿Por qué no le dimos sudo a B? ¿Qué podría hacer B con sudo en tu contenedor?
  3. ¿Por qué es más seguro que B te envíe su clave pública que darle una contraseña?
  4. El dueño (A) se permite entrar con contraseña y el invitado (B) no. ¿Por qué esa excepción? ¿Qué riesgo asume A a cambio, y cómo lo reduce?

🕵️ Extra: análisis de logs de tu servidor

Tu contenedor lleva semanas en Internet. Mira quién ha llamado a tu puerta:

LXC_A$ sudo journalctl -u ssh --no-pager | grep -E "Invalid user|Failed|banner exchange|Unable to negotiate|Accepted"

Clasifica cada línea: ¿eres tú, un compañero que se equivocó de puerto, un bot probando usuarios o un escáner? (Pista: fíjate en la hora, en el ritmo entre intentos y en el nombre de usuario.)


⚠️ Errores frecuentes

Síntoma (en B) Causa probable Solución
Permission denied con usuario y clave correctos estás llamando a otra puerta (puerto equivocado) revisa PUERTO_A en la tabla; ssh … 'hostname' debe decir el apellido de A
Permission denied (publickey) clave mal pegada (partida en varias líneas), permisos, o B no está en AllowUsers pasos 3 y 4
REMOTE HOST IDENTIFICATION HAS CHANGED el profesor renovó las claves de host de todos los servidores (24-sep) si lo confirma el profesor: ssh-keygen -R "[valdelab36.art]:PUERTO"
Connection refused puerto que no existe, o sshd de A parado revisa el puerto; A: systemctl status ssh
UNPROTECTED PRIVATE KEY FILE! usas la clave directamente desde el USB (FAT/exFAT no guarda permisos) cópiala a ~/.ssh y chmod 600 ~/.ssh/vlb36 (P0, 2.1)
A se ha quedado fuera falta apellidoA en AllowUsers, o el bloque Match está mal plan B con contraseña; si tampoco: sesión abierta → corrige; si no, avisa al profesor

▶ Ver solución (resumen de comandos)
# 1) B: enviar la pública
PC_B$ cat ~/.ssh/vlb36.pub

# 2-3) A: cuenta sin contraseña ni sudo + clave de B
LXC_A$ sudo adduser --disabled-password --comment "" apellidoB
LXC_A$ sudo -u apellidoB mkdir -p -m 700 /home/apellidoB/.ssh
LXC_A$ echo 'ssh-ed25519 AAAA... b@madlinux' | sudo -u apellidoB tee -a /home/apellidoB/.ssh/authorized_keys
LXC_A$ sudo -u apellidoB chmod 600 /home/apellidoB/.ssh/authorized_keys

# 4) A: contraseña robusta (plan B) y blindar:
#    PermitRootLogin no / PasswordAuthentication no / AllowUsers apellidoA apellidoB fenix
#    + al final: Match User apellidoA → PasswordAuthentication yes
LXC_A$ passwd
LXC_A$ sudo nano /etc/ssh/sshd_config.d/10-aula.conf
LXC_A$ sudo sshd -t && sudo systemctl reload ssh

# 5-6) B: conectar verificando la huella, y probar
PC_B$ ssh -i ~/.ssh/vlb36 -p PUERTO_A apellidoB@valdelab36.art 'hostname'

# 7) A: revocar
LXC_A$ sudo nano /etc/ssh/sshd_config.d/10-aula.conf     # AllowUsers apellidoA fenix
LXC_A$ sudo sshd -t && sudo systemctl reload ssh
LXC_A$ sudo deluser --remove-home apellidoB

Pregunta 1: tu contenedor ve 127.0.0.1. El proxy de Incus recibe la conexión en aldebaran y abre otra conexión, desde dentro de tu contenedor, hacia tu sshd. Todos (B, tú, los bots) parecéis venir de 127.0.0.1: bloquear esa IP te bloquearía a ti también.

Pregunta 2: cualquiera con sudo en su contenedor podía copiar la clave privada de host y hacerse pasar por el servidor de cualquier compañero (ataque man-in-the-middle) sin que saltara ningún aviso.

Pregunta 5: los PCs del aula se borran en cada reinicio: si A olvida el USB, sin contraseña se quedaría fuera de su propio servidor. A cambio, los bots pueden probar contraseñas contra el usuario de A. Se reduce con una contraseña robusta (passwd). (¿Serviría fail2ban dentro del contenedor? Recuerda la pregunta 1.)


➡️ Siguiente: Guía 2: scp y rsync (próximamente) enso.png