Ir al contenido

Proteger SSH con Google Authenticator: segundo factor en Ubuntu

·3 mins
Rogelio Guerra Riverón
Autor
Rogelio Guerra Riverón
Construyendo mi propia infraestructura web desde cero. Aquí documento cada paso: servidores, redes, contenedores y lo que vaya surgiendo.

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-authenticator

Generar 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 3

Opciones:

  • -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/sshd

Comentar la línea @include common-auth para evitar que el sistema solicite también la contraseña del sistema operativo:

#@include common-auth

Añadir al final del archivo:

auth required pam_google_authenticator.so nullok

La 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_config

Habilitar la autenticación interactiva por teclado, necesaria para que PAM pueda presentar el prompt del código:

KbdInteractiveAuthentication yes

Exigir ambos factores en orden secuencial: primero la clave SSH, después el código TOTP:

AuthenticationMethods publickey,keyboard-interactive

Reiniciar el servicio:

sudo systemctl restart ssh

Verificar 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 -t

sshd -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.