El límite de Fail2ban#
En un artículo anterior configuré Fail2ban para bloquear IPs con demasiados intentos fallidos. Es una medida eficaz contra ataques de fuerza bruta, pero no cubre un escenario diferente: que alguien obtenga la clave privada SSH.
Puede ocurrir de distintas formas: un equipo comprometido donde reside la clave, un backup con permisos incorrectos, o una sesión compartida donde el archivo quedó expuesto. Una vez que un atacante tiene el archivo id_rsa, Fail2ban no interviene — la autenticación se resuelve al primer intento, sin intentos fallidos que banear.
El segundo factor convierte el dispositivo móvil en un requisito físico. Aunque el atacante disponga de la clave privada, sin el código generado en el móvil no puede autenticarse.
Qué es TOTP#
TOTP (Time-based One-Time Password) genera códigos de 6 dígitos que se renuevan cada 30 segundos. El servidor y el dispositivo móvil comparten un secreto inicial y derivan el mismo código a partir de la hora actual. No requiere conexión a internet ni depende de SMS. Funciona completamente offline.
Cualquier app compatible con el estándar TOTP es válida: Google Authenticator, Aegis, andOTP, entre otras.
Instalación#
sudo apt update
sudo apt install libpam-google-authenticatorGenerar el secreto y el código QR#
Ejecutar como el usuario que utilizará SSH (nunca como root):
google-authenticator -t -d -f -r 3 -R 30 -w 3Opciones:
-t— basado en tiempo (TOTP)-d— impide reutilizar el mismo código-f— escribe la configuración sin solicitar confirmación-r 3 -R 30— máximo 3 intentos por cada 30 segundos-w 3— ventana de 3 intervalos (±90 segundos de tolerancia de reloj)
El comando genera un código QR en la terminal. Escanearlo con la app de autenticación. Si no es posible escanearlo, el secreto también se muestra en texto plano para introducirlo manualmente.
Conservar los códigos de emergencia. Son cinco códigos de un solo uso que permiten acceder cuando el dispositivo móvil no está disponible. Deben guardarse offline, fuera del servidor.
Configurar PAM#
PAM es el módulo que conecta OpenSSH con Google Authenticator. Editar /etc/pam.d/sshd:
sudo nano /etc/pam.d/sshdComentar la línea @include common-auth para evitar que el sistema solicite también la contraseña del sistema operativo:
#@include common-authAñadir al final del archivo:
auth required pam_google_authenticator.so nullokLa opción nullok permite que usuarios sin el archivo .google_authenticator configurado accedan sin código TOTP. Es útil durante una migración gradual o para cuentas de servicio. Una vez que todos los usuarios relevantes tengan el segundo factor activo, conviene eliminarla.
Configurar sshd_config#
Dos cambios en /etc/ssh/sshd_config:
sudo nano /etc/ssh/sshd_configHabilitar la autenticación interactiva por teclado, necesaria para que PAM pueda presentar el prompt del código:
KbdInteractiveAuthentication yesExigir ambos factores en orden secuencial: primero la clave SSH, después el código TOTP:
AuthenticationMethods publickey,keyboard-interactiveReiniciar el servicio:
sudo systemctl restart sshVerificar el acceso#
Antes de cerrar la sesión activa, abrir una segunda terminal y probar la conexión. Si algo falla, la sesión abierta permite corregirlo sin perder el acceso.
$ ssh usuario@servidor
(usuario@servidor) Verification code:La clave SSH se valida de forma silenciosa. A continuación aparece el prompt del código. Introducir los 6 dígitos de la app y confirmar con Enter.
Desde la sesión activa, verificar el estado del servicio y la sintaxis de configuración:
sudo systemctl status ssh
sudo sshd -tsshd -t valida la configuración sin reiniciar el servicio. Cualquier salida indica un error que debe resolverse antes de cerrar la sesión.
Resultado#
Con esta configuración, un atacante necesita dos elementos independientes para autenticarse: la clave privada SSH y el dispositivo móvil con la app. Comprometer uno solo no es suficiente.
El artículo siguiente aborda cómo eximir la red VPN de este requisito — cuando la conexión proviene de una red de confianza, el segundo factor añade fricción sin incrementar la seguridad real.