La autenticación SSH por contraseña es la mayor superficie expuesta de un servidor corriente. Contra ella no pueden ni Fail2ban ni ningún umbral: mil direcciones a un intento por hora no alcanzarán nunca un límite, y seguirán probando exactamente mientras probar siga siendo posible. Las claves eliminan esa posibilidad, y de toda la lista de fortificación este es el único ajuste que cambia la situación de forma cualitativa.
Solo una cosa asusta: cortar la contraseña y quedarse fuera. Este es el orden en el que eso no puede ocurrir.
La clave
Se genera en su máquina, no en el servidor:
ssh-keygen -t ed25519 -C "portátil de trabajo"
ed25519 en lugar de RSA: más corta, más rápida y sin preguntas sobre la longitud. RSA hace falta solo si debe llegar a algo muy antiguo; entonces -t rsa -b 4096.
Poner frase de paso a la clave merece la pena: el archivo de la clave puede robarse de un portátil, y sin frase de paso funciona de inmediato. No tendrá que escribirla cada vez, de eso se encarga ssh-agent, y en macOS y en la mayoría de escritorios Linux ya está en marcha.
La copia al servidor es un solo comando, mientras la contraseña aún funciona:
ssh-copy-id -i ~/.ssh/id_ed25519.pub user@203.0.113.25
Si ssh-copy-id no está disponible, el contenido del archivo .pub se añade como una línea a ~/.ssh/authorized_keys en el servidor. Los permisos importan: el directorio .ssh en 700, el archivo en 600, propiedad del propio usuario. Con otros permisos, sshd se niega en silencio a leer el archivo, y esa es la causa más frecuente de «la clave no funciona».
La comprobación que lo decide todo
Antes de cortar nada, abra una segunda conexión sin cerrar la primera:
ssh -o PasswordAuthentication=no user@203.0.113.25
La opción prohíbe al cliente recurrir a la contraseña; si el acceso funciona, funciona por la clave. Mientras ese comando no pase, no avance. Y mantenga la primera conexión abierta hasta el final: por ella se arregla todo lo que rompa.
El corte y una trampa poco evidente
Los ajustes van a un archivo aparte para que una actualización del paquete no los borre. Pero el nombre del archivo importa:
sudo tee /etc/ssh/sshd_config.d/10-hardening.conf <<'EOF'
PasswordAuthentication no
PermitRootLogin no
KbdInteractiveAuthentication no
PubkeyAuthentication yes
MaxAuthTries 3
LogLevel VERBOSE
EOF
La cuestión es que OpenSSH usa el primer valor obtenido para un parámetro, y no el último como en casi todo lo demás. Los archivos de sshd_config.d se leen por orden alfabético, y las imágenes de nube de Ubuntu dejan ahí 50-cloud-init.conf, donde con frecuencia figura PasswordAuthentication yes. Su archivo con el número 90 no hará nada en esa situación: el ajuste parece puesto y la contraseña sigue funcionando. De ahí el número 10, que se lee antes.
Lo que ha quedado realmente se ve sin adivinar:
sudo sshd -T | grep -Ei 'passwordauth|permitrootlogin|pubkeyauth'
Ese comando imprime la configuración efectiva después de todas las inclusiones. Créale a él, no al contenido de los archivos.
Después, comprobación de sintaxis y recarga suave del servicio:
sudo sshd -t && sudo systemctl reload ssh
sshd -t es obligatorio: una errata en la configuración dejará el servicio caído con restart y a usted fuera. reload, además, no corta las sesiones abiertas.
Ubuntu 24.04: el puerto no está donde cree
Una trampa propia de los Ubuntu recientes: allí sshd se lanza mediante un socket de systemd. En ese modo la línea Port de sshd_config no hace nada: escucha el socket, no el demonio. Si cambia el puerto, hay que editarlo a él:
sudo systemctl edit ssh.socket
y ListenStream= (un valor vacío reinicia el anterior) debe nombrar el puerto nuevo. El síntoma que lo delata: la configuración está cambiada, el servicio reiniciado, y el servidor sigue respondiendo en el 22.
A propósito del cambio de puerto: como protección no funciona, los escáneres encuentran un servicio en cualquier puerto en minutos. Su único efecto son registros más tranquilos, porque la búsqueda masiva va solo al 22. Es cómodo, pero no lo confunda con seguridad.
Quién puede entrar
Un complemento útil es una lista explícita:
AllowUsers deploy admin
Todo lo que no figure ahí se rechaza antes incluso de comprobar la clave. Eso cubre también el caso de que algún paquete cree un usuario del sistema con intérprete de comandos y directorio personal.
Una entrada de reserva
Una clave en un portátil es un punto único de fallo. El disco muere, el portátil se pierde y el servidor queda inaccesible para siempre. Un mínimo razonable:
- una segunda clave, desde otro dispositivo, en
authorized_keys; - una copia de la clave privada en un gestor de contraseñas o en una memoria cifrada;
- un acceso de consola probado en el proveedor: VNC o serie. Probado significa que ha entrado por él al menos una vez, no que «hay un botón en algún sitio del panel».
Aproveche para mirar qué hay ya en authorized_keys, tanto de su usuario como de root. Una clave ajena ahí sobrevive a cualquier cambio de contraseña y sigue siendo un acceso operativo.
Después
La búsqueda de contraseñas no desaparecerá, simplemente se vuelve inútil: en los registros quedarán miles de líneas Failed password, ninguna de las cuales puede terminar en éxito. Lo que ahora merece observarse son los accesos correctos: desde qué dirección, con qué usuario, a qué hora. Un acceso correcto por clave desde una dirección desconocida es un acontecimiento mucho más importante que un millón de fallos, y bastante más difícil de advertir en el flujo general. Ese es justamente el cuadro que muestra la página de demostración de abajo.