--- title: "Cómo activar 2FA en SSH con Google Authenticator en Ubuntu" description: "Protege el acceso SSH en Ubuntu 24.04 exigiendo clave SSH y un código TOTP de Google Authenticator, con códigos de emergencia y un despliegue gradual seguro." category: "Seguridad del Servidor" language: es source: https://cubepath.com/es/docs/seguridad-del-servidor/configuracion-de-autenticacion-de-dos-factores-2fa-con-google-authenticator updated: 2026-09-25 --- # Cómo activar 2FA en SSH con Google Authenticator en Ubuntu La autenticación de dos factores (2FA) exige algo que tienes además de algo que sabes. En SSH, la combinación más práctica es una clave SSH más un código temporal de seis dígitos (TOTP) generado en el móvil: aunque alguien robe tu clave privada, no podrá entrar sin el teléfono. En este tutorial instalarás el módulo PAM de Google Authenticator en Ubuntu 24.04, lo configurarás para tu usuario y ajustarás SSH para que pida clave y código. Los códigos funcionan con cualquier aplicación TOTP: Google Authenticator, Aegis, Microsoft Authenticator, 1Password o Bitwarden. ## Requisitos previos - Un servidor con Ubuntu 24.04 LTS, por ejemplo un VPS de CubePath. - Un usuario no root con privilegios `sudo` que ya entra por **clave SSH**. Si aún usas contraseña, sigue primero la guía de gestión de claves SSH de esta sección. - Un móvil con una aplicación TOTP instalada. - Acceso a la consola web de tu proveedor por si te quedas fuera, y una sesión SSH abierta durante todo el proceso. > Advertencia: no cierres la sesión SSH con la que trabajas hasta haber comprobado el acceso con 2FA desde una segunda terminal. ## Paso 1: Comprobar la hora del servidor Los códigos TOTP dependen de la hora: el servidor y el móvil calculan el mismo código a partir de un secreto compartido y del reloj. Si el reloj del servidor se desvía más de un minuto o dos, los códigos se rechazarán. Comprueba que está sincronizado: ```bash timedatectl ``` ```output Local time: Fri 2026-09-25 10:40:12 UTC Universal time: Fri 2026-09-25 10:40:12 UTC RTC time: Fri 2026-09-25 10:40:12 Time zone: Etc/UTC (UTC, +0000) System clock synchronized: yes NTP service: active ``` Si `System clock synchronized` es `no`, activa la sincronización: ```bash sudo timedatectl set-ntp true ``` ## Paso 2: Instalar el módulo PAM de Google Authenticator El paquete `libpam-google-authenticator` incluye el módulo PAM que verifica los códigos y la herramienta `google-authenticator` que genera el secreto de cada usuario: ```bash sudo apt update sudo apt install libpam-google-authenticator ``` Verifica que el módulo está en su sitio: ```bash ls /usr/lib/x86_64-linux-gnu/security/pam_google_authenticator.so ``` En servidores ARM la ruta es `/usr/lib/aarch64-linux-gnu/security/`. ## Paso 3: Generar el secreto para tu usuario Ejecuta `google-authenticator` con tu usuario, **sin** `sudo`: el secreto se guarda en `~/.google_authenticator` del usuario que ejecuta el comando. Las opciones evitan las preguntas interactivas: ```bash google-authenticator -t -d -f -r 3 -R 30 -w 3 ``` | Opción | Efecto | |---|---| | `-t` | Códigos basados en tiempo (TOTP), los que usan las aplicaciones móviles. | | `-d` | Cada código solo se puede usar una vez. | | `-f` | Escribe el archivo sin pedir confirmación. | | `-r 3 -R 30` | Máximo 3 intentos de inicio de sesión cada 30 segundos. | | `-w 3` | Acepta el código actual, el anterior y el siguiente para tolerar pequeñas desviaciones de reloj. | La herramienta muestra un código QR en la terminal, la clave secreta y te pide un código para confirmar: ```output Warning: pasting the following URL into your browser exposes the OTP secret to Google: https://www.google.com/chart?chs=200x200&chld=M|0&cht=qr&chl=otpauth://totp/your_user@web01%3Fsecret%3D... [código QR] Your new secret key is: JBSWY3DPEHPK3PXPJBSWY3DPEH Enter code from app (-1 to skip): 482913 Code confirmed Your emergency scratch codes are: 18273645 90817263 55120938 71029384 46382910 ``` Escanea el código QR con la aplicación del móvil (si la terminal no lo muestra bien, amplía la ventana o introduce la clave secreta a mano). Después escribe el código de seis dígitos que muestra la aplicación. > Importante: guarda los cinco **códigos de emergencia** en tu gestor de contraseñas. Cada uno sirve una sola vez para entrar si pierdes el móvil. No abras la URL de Google que aparece en la salida: expone tu secreto a un tercero. Comprueba que el archivo existe y que solo tu usuario puede leerlo: ```bash ls -l ~/.google_authenticator ``` ```output -r-------- 1 your_user your_user 146 Sep 25 10:45 /home/your_user/.google_authenticator ``` ## Paso 4: Configurar PAM para SSH PAM decide qué se pide durante la autenticación. En Ubuntu, `/etc/pam.d/sshd` incluye `common-auth`, que solicita la contraseña del sistema. Como el primer factor será la clave SSH, sustituye esa línea por el módulo de Google Authenticator. Haz primero una copia: ```bash sudo cp /etc/pam.d/sshd /etc/pam.d/sshd.bak sudo nano /etc/pam.d/sshd ``` Comenta la línea `@include common-auth` y añade debajo el módulo: ```text # Standard Un*x authentication. #@include common-auth auth required pam_google_authenticator.so nullok ``` La opción `nullok` permite entrar sin código a los usuarios que todavía no han ejecutado `google-authenticator`. Es útil para desplegar 2FA de forma gradual en servidores con varios usuarios; la quitarás en el paso 7. ## Paso 5: Configurar SSH para exigir clave y código Ahora indica a `sshd` que use el método `keyboard-interactive` (el que pasa por PAM y pide el código) y que exija los dos métodos en orden: primero clave pública y después código. Crea un archivo de configuración adicional: ```bash sudo nano /etc/ssh/sshd_config.d/10-2fa.conf ``` ```text UsePAM yes KbdInteractiveAuthentication yes AuthenticationMethods publickey,keyboard-interactive ``` En Ubuntu 24.04 el archivo principal `/etc/ssh/sshd_config` incluye `KbdInteractiveAuthentication no`, pero los archivos de `sshd_config.d/` se leen antes y, para cada opción, gana el primer valor encontrado. Si en ese directorio tienes otro archivo que se ordene antes que `10-2fa.conf` y ponga `KbdInteractiveAuthentication no`, elimina esa línea de él. Valida la sintaxis y comprueba la configuración efectiva: ```bash sudo sshd -t sudo sshd -T | grep -Ei '^(usepam|kbdinteractiveauthentication|authenticationmethods|passwordauthentication) ' ``` ```output usepam yes kbdinteractiveauthentication yes passwordauthentication no authenticationmethods publickey,keyboard-interactive ``` Aplica los cambios sin cerrar tu sesión: ```bash sudo systemctl reload ssh ``` ## Paso 6: Probar el acceso con 2FA Abre una **nueva terminal** en tu equipo local, sin cerrar la sesión actual, y conéctate: ```bash ssh your_user@your_server_ip ``` Tras autenticarse con la clave, SSH pedirá el código de la aplicación: ```output (your_user@your_server_ip) Verification code: Welcome to Ubuntu 24.04.3 LTS (GNU/Linux 6.8.0-84-generic x86_64) ``` Comprueba en el registro del servidor que se usaron los dos métodos: ```bash sudo journalctl -u ssh -n 20 --no-pager | grep Accepted ``` ```output sshd[3120]: Accepted publickey for your_user from 198.51.100.7 port 52114 ssh2: ED25519 SHA256:mQ3b7l1xT0H9... sshd[3120]: Accepted keyboard-interactive/pam for your_user from 198.51.100.7 port 52114 ssh2 ``` Prueba también que un código incorrecto se rechaza. Si todo funciona, ya puedes cerrar la sesión antigua. Si algo falla, restaura la configuración desde la sesión que dejaste abierta: ```bash sudo cp /etc/pam.d/sshd.bak /etc/pam.d/sshd sudo rm /etc/ssh/sshd_config.d/10-2fa.conf sudo systemctl reload ssh ``` ## Paso 7: Exigir 2FA a todos los usuarios Cada usuario que entre por SSH debe ejecutar `google-authenticator` en su propia sesión (paso 3) y escanear su propio código. No generes los secretos por ellos: el secreto es personal y debe quedarse solo en su móvil. Para ver qué usuarios con shell aún no tienen 2FA configurado: ```bash for home in /home/*; do sudo test -f "$home/.google_authenticator" || echo "Sin 2FA: $home"; done ``` Cuando todos lo tengan configurado, quita `nullok` de `/etc/pam.d/sshd` para que ningún usuario pueda entrar sin código: ```bash sudo nano /etc/pam.d/sshd ``` ```text auth required pam_google_authenticator.so ``` Los cambios en PAM se aplican en el siguiente inicio de sesión, sin reiniciar SSH. Vuelve a probar desde una nueva terminal. ## Paso 8 (opcional): No pedir código desde la red interna Si administras el servidor desde una red privada de confianza, por ejemplo una VPN, puedes omitir el código para esas direcciones con `pam_access`. Crea el archivo de reglas: ```bash sudo nano /etc/security/access-2fa.conf ``` ```text + : ALL : 10.8.0.0/24 - : ALL : ALL ``` Sustituye `10.8.0.0/24` por tu red interna. Después añade una línea en `/etc/pam.d/sshd` justo **antes** del módulo de Google Authenticator: ```text auth [success=1 default=ignore] pam_access.so accessfile=/etc/security/access-2fa.conf auth required pam_google_authenticator.so ``` Si la IP de origen coincide con una regla `+`, PAM salta la línea siguiente y no pide el código; en cualquier otro caso continúa y lo exige. La clave SSH sigue siendo obligatoria siempre. Comprueba ambos casos: desde la red interna no debe pedir código y desde fuera sí. ## Recuperar el acceso si pierdes el móvil - **Con un código de emergencia:** escríbelo cuando SSH pida `Verification code`. Cada código solo vale una vez; después genera un secreto nuevo con `google-authenticator` para tener códigos frescos. - **Sin códigos de emergencia:** otro administrador puede borrar tu archivo con `sudo rm /home/your_user/.google_authenticator`. Si `nullok` está activo entrarás solo con la clave; si no, el administrador debe regenerarlo contigo. Si no hay otro administrador, entra por la consola web del proveedor, que no pasa por SSH. ## Solución de problemas **Los códigos se rechazan siempre.** Casi siempre es la hora. Comprueba `timedatectl` en el servidor y que el móvil tiene la hora automática activada. Revisa el registro: ```bash sudo journalctl -u ssh -n 30 --no-pager | grep -i google ``` Un mensaje `Invalid verification code` con la hora correcta indica que escaneaste un QR antiguo; genera el secreto de nuevo. **SSH pide la contraseña además del código.** La línea `@include common-auth` sigue activa en `/etc/pam.d/sshd`. Coméntala como en el paso 4. **SSH no pide el código y entra solo con la clave.** Comprueba con `sudo sshd -T | grep -i -E 'authenticationmethods|kbdinteractive'` que los valores son los del paso 5; otro archivo de `sshd_config.d/` puede estar sobrescribiéndolos. Si los valores son correctos y el usuario no tiene `~/.google_authenticator`, es el efecto de `nullok`. **`Permission denied (keyboard-interactive)` con el código correcto.** El módulo no puede leer el secreto. El archivo debe pertenecer al usuario y tener permisos `400` o `600`: ```bash chmod 400 ~/.google_authenticator ``` **Tras un código válido, el siguiente inicio de sesión falla.** Con `-d` cada código se usa una sola vez; espera a que la aplicación muestre uno nuevo (30 segundos). ## Conclusión Has instalado el módulo PAM de Google Authenticator, generado tu secreto TOTP con códigos de emergencia y configurado SSH para exigir clave pública y código, con un despliegue gradual mediante `nullok` y una excepción opcional para la red interna. A partir de ahora, una clave privada robada no basta para entrar en el servidor. Como siguientes pasos puedes: - Revisar el resto de la configuración del servidor con una auditoría de seguridad o con Lynis. - Instalar Fail2ban para bloquear las IP que acumulan intentos fallidos. - Sustituir el TOTP por llaves de seguridad FIDO2 con claves `ed25519-sk`.