Seguridad

Protege tu SSH: Configura 2FA con Google Authenticator, Guía Definitiva para Sysadmins

TL;DR — Lo que vas a tener al final

  • Tiempo de setup: 1-2 horas para un server nuevo.
  • Requisitos: Acceso root, 2 sesiones SSH abiertas durante cambios.
  • Resultado: Login por clave ed25519, fail2ban activo, 99% de ataques bloqueados.
  • Troubleshooting: Consola del proveedor, journalctl -u sshd, fail2ban-client status.

Por qué necesitas 2FA en SSH en 2026

Si tienes un servidor expuesto a internet, la pregunta no es si van a intentar entrar, sino cuántas veces al día. Los datos de Shodan y los reportes de Shadowserver muestran que un puerto 22 abierto recibe entre 200 y 2.000 intentos de login por día, incluso en servidores hogareños con IP dinámica. En el momento en que un atacante tiene tu contraseña (reutilizada de otro servicio, filtrada en un dump, capturada por un keylogger), tu servidor queda expuesto. La autenticación de dos factores (2FA) cierra esa ventana agregando un segundo factor que solo tú tienes en tu teléfono.

En esta guía vas a configurar TOTP (Time-based One-Time Password) usando Google Authenticator — técnicamente el módulo libpam-google-authenticator — sobre un servidor SSH Linux. El flujo es: el usuario ingresa su clave SSH (o contraseña), y después un código de 6 dígitos rotativo de 30 segundos que aparece en una app del teléfono. Si alguien roba tu clave privada, todavía necesita el código. Si alguien te roba el teléfono, todavía necesita la clave privada.

Este no es el método más moderno (FIDO2 con llaves físicas es estrictamente más fuerte contra phishing), pero sigue siendo el equilibrio correcto entre seguridad y fricción operativa para la mayoría de sysadmins que manejan uno o varios servidores Linux. Al final de la guía te dejo cuándo vale la pena saltar a FIDO2 y cuándo quedarse en TOTP.

Cómo funciona Google Authenticator con PAM

El módulo libpam-google-authenticator se enchufa en la pila PAM (Pluggable Authentication Modules) del sistema. Cuando configuras sshd para requerir este módulo, el flujo de login queda así:

  1. El cliente SSH se conecta al servidor y propone métodos de autenticación.
  2. Si sshd tiene AuthenticationMethods publickey,keyboard-interactive, primero valida tu clave pública contra ~/.ssh/authorized_keys.
  3. Si la clave pasa, sshd invoca el módulo PAM, que muestra un prompt Verification code:.
  4. Tú abres la app en el teléfono y lees el código de 6 dígitos vigente.
  5. El servidor valida el código contra la semilla TOTP almacenada en ~/.google_authenticator del usuario.

El código rota cada 30 segundos basado en el reloj del sistema. El módulo acepta por defecto un window de 3 slots (el anterior, el actual y el siguiente), así que tolera un desfase de hasta ±30 segundos entre cliente y servidor. Si el desfase es mayor, los códigos no coinciden. Por eso es crítico tener NTP funcionando antes de empezar — si no, vas a quedarte afuera.

Pre-requisitos antes de instalar

Antes de tocar nada, asegúrate de tener:

  • Acceso al servidor por consola o panel de hosting (no solo SSH). Si algo sale mal con PAM, te puedes quedar sin acceso y necesitas un recovery path físico.
  • NTP activo y sincronizado. Verifica con timedatectl status que System clock synchronized: yes. Sin esto, los códigos TOTP no van a coincidir con el servidor.
  • Una app TOTP en el teléfono. Google Authenticator funciona, pero si quieres evitar el ecosistema de Google, Aegis (Android, open source) o Raivo OTP (iOS, open source) son mejores — soportan backups cifrados y exports.
  • Una sesión SSH abierta en otra ventana mientras configuras. Vas a editar archivos de sshd y PAM; cualquier cambio mal aplicado rompe el login. Mantén una segunda conexión viva para revertir si es necesario.

Instalar el módulo PAM

En Debian, Ubuntu y derivados:

sudo apt update
sudo apt install libpam-google-authenticator -y
google-authenticator

En Fedora, RHEL, Rocky, AlmaLinux y derivados:

sudo dnf install epel-release -y
sudo dnf install google-authenticator qrencode-libs -y
google-authenticator

El binario google-authenticator es interactivo. Te va a preguntar:

  • Do you want authentication tokens to be time-based? → Responde y (time-based es el estándar TOTP).
  • Do you want me to update your ~/.google_authenticator file? → y.
  • Do you want to disallow multiple uses of the same authentication token? → y. Impide reuso del mismo código en la misma ventana de 30s.
  • By default, tokens are good for 30 seconds… → y para aceptar el default (30s + ventana de drift).
  • Do you want to enable rate-limiting? → y. Limita a 3 intentos cada 30s — protege contra fuerza bruta local.

Al final, el comando imprime un QR code en la terminal y un URL. Escanealo con tu app TOTP. También te imprime 5 códigos de respaldo (scratch codes) — guárdalos en un lugar seguro fuera del teléfono. Si pierdes el teléfono, estos son tu única entrada al servidor.

Configurar sshd para requerir 2FA

Edita el archivo principal /etc/ssh/sshd_config directamente. Si tu distribución trae OpenSSH 9.5 o superior (Debian 12+, Ubuntu 24.04+, Fedora 41+), también puedes usar un drop-in en /etc/ssh/sshd_config.d/. Si estás en RHEL 9, Rocky Linux 9 o AlmaLinux 9 edita /etc/ssh/sshd_config directo — esas distribuciones todavía traen OpenSSH 8.7 y no soportan la directiva Include:

sudo cp /etc/ssh/sshd_config /etc/ssh/sshd_config.bak.$(date +%Y%m%d)
sudo tee /etc/ssh/sshd_config.d/99-2fa.conf > /dev/null <<'EOF'
# Requerir clave pública + TOTP (AuthenticationMethods permite encadenar factores)
PubkeyAuthentication yes
PasswordAuthentication no
AuthenticationMethods publickey,keyboard-interactive
# Habilitar el desafío interactivo para PAM
KbdInteractiveAuthentication yes
UsePAM yes
EOF

Los cuatro cambios clave: AuthenticationMethods publickey,keyboard-interactive exige ambos factores en orden; PubkeyAuthentication yes garantiza que tu clave SSH sea el primer factor (sin esto, sshd podría ofrecer solo password y saltarse el TOTP); PasswordAuthentication no cierra el camino de ataque por contraseña a nivel de sshd; KbdInteractiveAuthentication yes activa el prompt donde PAM pregunta el código TOTP.

Ahora hay que indicarle a PAM que use el módulo de Google Authenticator. El contenido del archivo /etc/pam.d/sshd varía entre familias:

Debian / Ubuntu:

sudo cp /etc/pam.d/sshd /etc/pam.d/sshd.bak.$(date +%Y%m%d)
sudo tee /etc/pam.d/sshd > /dev/null <<'EOF'
# PAM configuration for the Secure Shell service
@include common-auth
# Google Authenticator 2FA — segundo factor después de la clave pública
auth required pam_google_authenticator.so nullok
@include common-account
@include common-session
EOF

RHEL / Fedora / Rocky / AlmaLinux:

sudo cp /etc/pam.d/sshd /etc/pam.d/sshd.bak.$(date +%Y%m%d)
sudo tee /etc/pam.d/sshd > /dev/null <<'EOF'
# PAM configuration for the Secure Shell service
auth include system-auth
# Google Authenticator 2FA — segundo factor después de la clave pública
auth required pam_google_authenticator.so nullok
account include system-auth
session include system-auth
EOF

El parámetro nullok permite que usuarios sin ~/.google_authenticator todavía puedan entrar — útil durante la transición cuando aún no corriste google-authenticator para todos los usuarios. Quítalo cuando termines la rollout, así nadie se loguea sin 2FA configurado.

Valida la configuración y recarga sshd sin tumbar la sesión actual:

sudo sshd -t && echo "config válida"
sudo systemctl reload sshd

sshd -t hace dry-run del config y devuelve errores sin iniciar nada. systemctl reload sshd aplica cambios sin matar sesiones existentes — distinto de restart que sí las corta.

Verificación paso a paso

Abre una nueva ventana de terminal (no cierres la sesión actual hasta confirmar). Conéctate normalmente:

ssh usuario@servidor

Si la clave pública es válida, sshd te va a pedir:

Verification code:

Abre la app TOTP, lee el código, ingrésalo. Si todo está bien, entras. Si te marca Invalid verification code tres veces seguidas, el rate-limiting te bloquea por 30 segundos — espera, revisa NTP, y reintenta.

Problema Causa probable Fix
Código siempre inválido Reloj del servidor desincronizado sudo systemctl restart systemd-timesyncd y verificar timedatectl
No aparece prompt de código KbdInteractiveAuthentication no en sshd_config Cambiar a yes y systemctl reload sshd
Login funciona sin pedir código nullok en PAM y usuario sin ~/.google_authenticator Correr google-authenticator para ese usuario y quitar nullok
Prompt pide contraseña en vez de código AuthenticationMethods mal configurado o PasswordAuthentication yes Verificar cadena: publickey,keyboard-interactive y PasswordAuthentication no
Rate-limit te bloquea inmediato Muchos intentos fallidos previos Esperar 30s; si persiste, revisar /var/log/auth.log

Códigos de respaldo y recuperación

Los 5 scratch codes que imprimió google-authenticator al inicio son tu red de seguridad si pierdes el teléfono. Cada uno sirve una sola vez. Imprímelos o guárdalos en un gestor de contraseñas cifrado (KeePass, Bitwarden). Nunca los dejes en el mismo teléfono donde está la app TOTP — si pierdes el dispositivo, pierdes ambos.

Si pierdes el teléfono y los scratch codes, las opciones son:

  • Acceder al servidor por consola física (IPMI, iDRAC, KVM del proveedor) y correr google-authenticator otra vez para regenerar la semilla y los códigos.
  • Editar /etc/pam.d/sshd temporalmente para remover pam_google_authenticator.so y entrar solo con clave, regenerar, y volver a activar.
  • En proveedores cloud (Hetzner, DigitalOcean, AWS Lightsail), usar la consola de rescate del panel — ahí puedes montar el disco y editar los archivos aunque sshd esté roto.

La opción 1 es la más limpia. La opción 2 te deja una ventana de exposición (alguien podría entrar sin 2FA durante esos minutos) — solo logueé en horario controlado y revierte rápido.

Cuándo NO este método funciona

TOTP con Google Authenticator no es la opción correcta si:

  • Tu equipo es víctima de phishing sofisticado. Un atacante puede pedirte el código en tiempo real y usarlo antes de que expire. FIDO2 con llave física resiste este ataque porque la firma es criptográfica contra el dominio. Si manejas infraestructura crítica expuesta, salta directo a FIDO2.
  • No tienes NTP confiable. Si el servidor está aislado o detrás de una red que bloquea UDP 123, los códigos no van a coincidir. Configura chrony con un servidor NTP interno o usa NTS sobre TLS.
  • Necesitas login no-interactivo (scripts, ansible, rsync). TOTP requiere intervención humana. Para automatización, usa claves SSH dedicadas con passphrase + ssh-agent, no 2FA.
  • Tu teléfono se rompe o se pierde sin backup. Si no tienes scratch codes guardados fuera del teléfono, TOTP te deja fuera. FIDO2 con dos llaves (una primaria, una de backup) resuelve esto mejor.

Resumen

Configurar 2FA en SSH con Google Authenticator lleva 10 minutos si ya tienes NTP funcionando y acceso de recuperación. El setup básico —Instalar libpam, correr google-authenticator, tocar sshd_config y pam.d/sshd — cubre el 90% de los casos. El 10% restante es hardening: quitar nullok cuando todos los usuarios tengan semilla, configurar fail2ban para limitar intentos, y tener un plan de recuperación documentado.

El siguiente paso lógico es mirar FIDO2 si quieres el siguiente nivel. La pila libfido2 + ssh-keygen -t ed25519-sk te da autenticación resistente a phishing con una llave USB como el único elemento físico. Para la mayoría de sysadmins con 1-5 servidores, TOTP es suficiente. Para infraestructura productiva expuesta, FIDO2 vale la inversión.

Preguntas frecuentes

¿Por qué Protege tu SSH: Configura 2FA con Google Authenticator, Guía Definitiva para Sysadmins es relevante para sysadmins Linux?

Forma parte del flujo diario de administración. Los conceptos explicados se aplican directamente a servidores en producción y resuelven problemas reales que enfrentan sysadmins hispanohablantes.

¿Qué necesito para empezar con Protege tu SSH: Configura 2FA?

Distribución Linux actualizada (Debian, Ubuntu, RHEL, Fedora o Arch), acceso root, y conexión a internet. Para producción: entorno de staging separado antes de aplicar cambios.

¿Cuáles son los errores más comunes con Protege tu SSH: Configura 2FA?

Los tres más frecuentes: (1) saltar la lectura de logs, (2) aplicar cambios directos en producción sin probar, (3) olvidar permisos y ownership. La documentación y un plan de rollback siempre.

¿Cuándo usar Protege tu SSH: Configura 2FA y cuándo una alternativa?

Esta solución es ideal para el caso descrito. Alternativas como Docker, Ansible o configuración manual pueden ser mejores según contexto: portabilidad, escala y reproducibilidad son los factores clave.

¿Cómo migro desde una configuración previa a Protege tu SSH: Configura 2FA?

Documentar el estado actual, probar la nueva configuración en staging, validar funcionalmente, y aplicar en producción con rollback plan listo. Los posts de SoyLinux incluyen troubleshooting para los problemas más comunes.

Lee también

Alfonso Moreno | Sysadmin Senior

Soy Alfonso, sysadmin senior con RHCE y más de 10 años administrando sistemas Linux para empresas y proyectos personales. Me especializo en infraestructura, redes, virtualización, monitoring, automation y self-hosting. Sobre SoyLinux.com SoyLinux.com es un blog técnico en español sobre Linux, software libre y self-hosting. Lo mantengo en mi tiempo libre. Áreas de expertise - Linux server administration: RHEL, CentOS, Rocky, Alma, Fedora, Debian, Ubuntu - Network services: Postfix, BIND, Samba, NFS, Squid - Virtualización y containers: KVM, Proxmox, Docker, Podman - Monitoring: Prometheus, Grafana, Zabbix - Automation: Ansible, Bash scripting - Self-hosting: Vaultwarden, Nextcloud, Jellyfin, Immich, Homelab Contacto - Email: [email protected]

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *