1. Objetivo y preparación

Esta demostración evidencia una confusión habitual en la administración de cuentas, la de creer que passwd -l bloquea una cuenta. En realidad solo invalida la autenticación por contraseña, de modo que un usuario con una clave SSH en ~/.ssh/authorized_keys sigue pudiendo entrar. El bloqueo real de la cuenta exige, además, expirarla.

Para que la diferencia sea visible, la práctica usa una conexión SSH real desde el anfitrión hacia una instancia de OpenStack, y distingue en todo momento dónde se ejecuta cada orden:

  • Anfitrión: su equipo, donde se genera la clave de prueba y desde donde se simulan las conexiones del usuario.

  • Instancia: la máquina virtual de OpenStack, donde reside la cuenta maria y donde se aplican los bloqueos.

Realice la demostración sobre una instancia de pruebas, nunca sobre un servidor en producción. Los pasos crean una cuenta con contraseña y clave SSH, y la eliminan al final.

Requisitos

  • Una instancia de OpenStack en ejecución con una imagen de Ubuntu y una IP flotante asignada.

  • Un grupo de seguridad que permita el tráfico entrante por el puerto 22/TCP desde su equipo.

  • Acceso SSH a la instancia como el usuario ubuntu, el que traen las imágenes cloud de Ubuntu, con el par de claves del proyecto que inyectó cloud-init al arrancar. En los ejemplos, ese par de claves es ~/.ssh/clave_openstack y la IP flotante se representa con IP_FLOTANTE.

  • El servicio ssh activo en la instancia, con UsePAM yes, que es el valor por defecto en Ubuntu. De él depende que el bloqueo completo surta efecto también sobre la clave SSH.

2. Preparación del entorno

2.1. Generar la clave de maria y copiarla a la instancia

En el anfitrión, genere una clave SSH de prueba sin frase de paso. Esta clave es la que usará maria, distinta de la clave con la que usted accede como ubuntu:

# Anfitrión

# Genera el par de claves de prueba de maria, sin frase de paso
ssh-keygen -t ed25519 -N '' -f ~/maria_demo

Copie la parte pública a la instancia con scp, autenticándose como ubuntu con el par de claves del proyecto:

# Anfitrión

# Copia la clave pública de maria a la instancia, autenticándote como ubuntu
scp -i ~/.ssh/clave_openstack ~/maria_demo.pub ubuntu@IP_FLOTANTE:/tmp/maria_demo.pub
Orden Función

ssh-keygen -t ed25519 -N '' -f ~/maria_demo

Crea el par de claves maria_demo y maria_demo.pub. La opción -N '' genera la clave privada sin frase de paso, para que la conexión sea desatendida

scp -i ~/.ssh/clave_openstack … ubuntu@IP_FLOTANTE:/tmp/…

Copia la clave pública al interior de la instancia, usando la clave del proyecto para autenticarse como ubuntu

2.2. Crear la cuenta maria e instalar su clave

Conéctese a la instancia como ubuntu y, dentro de la instancia, cree la cuenta e instale la clave pública como authorized_keys:

# Anfitrión: entrar en la instancia

# Abre una sesión en la instancia como el usuario ubuntu
ssh -i ~/.ssh/clave_openstack ubuntu@IP_FLOTANTE
# Instancia

# Crea la cuenta maria con directorio personal y shell bash
sudo useradd -m -s /bin/bash maria

# Asigna la contraseña a maria sin que se muestre por pantalla
echo 'maria:Bastionado2026' | sudo chpasswd

# Crea el directorio .ssh con permisos 700 y propietario maria
sudo install -d -m 700 -o maria -g maria /home/maria/.ssh

# Instala la clave pública de prueba como authorized_keys de maria
sudo cp /tmp/maria_demo.pub /home/maria/.ssh/authorized_keys

# Asigna el archivo a maria para que sshd lo acepte
sudo chown maria:maria /home/maria/.ssh/authorized_keys

# Restringe el archivo a lectura y escritura solo para su propietario
sudo chmod 600 /home/maria/.ssh/authorized_keys

sshd rechaza la autenticación por clave si los permisos del directorio ~/.ssh o del archivo authorized_keys son demasiado abiertos. Por eso el directorio se crea con 700 y el archivo con 600, ambos propiedad de maria.

3. Línea base: la clave SSH funciona

Desde el anfitrión, conéctese como maria usando su clave de prueba. Sustituya IP_FLOTANTE por la IP flotante de la instancia:

# Anfitrión

# Conéctate como maria con su clave y ejecuta id para comprobar el acceso
ssh -i ~/maria_demo maria@IP_FLOTANTE id

La conexión se establece y muestra la salida de id, con uid y gid de maria. Esta es la situación de partida. La cuenta es plenamente funcional.

4. Bloqueo parcial con passwd -l: la trampa

En la instancia, aplique el bloqueo de contraseña y consulte el estado de la cuenta:

# Instancia

# Bloquea la contraseña de maria anteponiendo ! a su hash
sudo passwd -l maria

# Muestra el estado de la contraseña: "maria L" confirma el bloqueo
sudo passwd -S maria

passwd -l antepone un carácter ! al hash de la contraseña en /etc/shadow, y passwd -S informa de la cuenta como L, bloqueada. Repita ahora la conexión desde el anfitrión:

# Anfitrión

# Reintenta el acceso de maria con su clave tras el bloqueo parcial
ssh -i ~/maria_demo maria@IP_FLOTANTE id

La conexión vuelve a tener éxito

Pese a que la cuenta figura como bloqueada, la clave SSH sigue dando acceso. passwd -l invalida únicamente la autenticación por contraseña y no afecta a ningún otro método. Si el usuario dispone de una clave en authorized_keys, entra sin impedimento. Esta es la trampa. passwd -l no bloquea la cuenta, solo su contraseña.

5. Bloqueo completo

El bloqueo efectivo requiere, además, expirar la cuenta. En la instancia:

# Instancia

# Bloquea la contraseña y expira la cuenta con una fecha en el pasado
sudo usermod -L -e 1 maria

# Comprueba la fecha de expiración de la cuenta: "Jan 02, 1970"
sudo chage -l maria | grep -i 'Account expires'
Opción Efecto

-L

Antepone ! al hash de la contraseña, igual que passwd -l

-e 1

Fija la fecha de expiración de la cuenta en el día 1 desde el 1 de enero de 1970, es decir, el 2 de enero de 1970. Al estar en el pasado, la cuenta aparece como caducada

Repita una última vez la conexión desde el anfitrión:

# Anfitrión

# Reintenta el acceso de maria con su clave tras el bloqueo completo
ssh -i ~/maria_demo maria@IP_FLOTANTE id

Ahora el acceso se deniega. La expiración de la cuenta la comprueba el módulo pam_unix en la fase account, con independencia del método de autenticación empleado, de modo que bloquea también la clave SSH. Este sí es un bloqueo real de la cuenta.

6. Reactivación y limpieza

Para reactivar la cuenta se revierten los dos efectos del bloqueo completo. En la instancia:

# Instancia

# Reactiva la cuenta: quita el ! del hash y elimina la expiración
sudo usermod -U -e '' maria

# Comprueba que la cuenta ya no expira: "never"
sudo chage -l maria | grep -i 'Account expires'

Cuando la demostración ha terminado, elimine la cuenta en la instancia y la clave de prueba en el anfitrión:

# Instancia

# Elimina la cuenta maria junto con su directorio personal
sudo userdel -r maria
# Anfitrión

# Elimina la clave de prueba del anfitrión
rm -f ~/maria_demo ~/maria_demo.pub

7. Resumen

Fase Orden en la instancia Conexión ssh maria@IP_FLOTANTE desde el anfitrión

Línea base

-

Entra

Bloqueo parcial

passwd -l maria

Entra (la trampa)

Bloqueo completo

usermod -L -e 1 maria

Bloqueada

El bloqueo real de una cuenta lo proporciona la expiración (-e 1), no el bloqueo de la contraseña (-l). Un bloqueo con passwd -l o usermod -L deja abiertas las vías de acceso que no usan la contraseña local, como las claves públicas de SSH, los tokens o la autenticación federada. Por ello, el CIS Benchmark recomienda combinar ambos efectos al dar de baja o suspender una cuenta.

8. Licencia

Licencia CC BY-NC-ND 4.0

Esta página forma parte del curso Bastionado de Redes y Sistemas © 2026 de José Juan Sánchez Hernández y su contenido se distribuye bajo una licencia Creative Commons Attribution-NonCommercial-NoDerivatives 4.0 International.

Esta licencia exige que quienes reutilicen el material otorguen el debido crédito al autor. Permite copiar y redistribuir el material en cualquier medio o formato, únicamente en su forma original, y solo para fines no comerciales.