Autenticación SSH con FIDO2 y YubiKey en Linux 2026: Guía Completa con ed25519-sk
Aprende a configurar autenticación SSH con FIDO2 y YubiKey en Linux 2026 usando claves ed25519-sk residentes, PIN obligatorio y sshd_config endurecido. Incluye comandos, ejemplos de Ansible y solución de errores en despliegues reales.
La autenticación SSH con FIDO2 y YubiKey en Linux 2026 se configura generando una clave ed25519-sk residente con ssh-keygen -t ed25519-sk -O resident -O verify-required, habilitando PubkeyAcceptedAlgorithms [email protected] en sshd_config y exigiendo PIN más toque físico en cada acceso. Este esquema, disponible desde OpenSSH 8.2 y consolidado en OpenSSH 10.5 (agosto de 2026), elimina el robo remoto de claves privadas porque el material criptográfico nunca abandona el chip seguro de la llave hardware.
OpenSSH 10.5 (11 de agosto de 2026) es la versión estable de referencia; el soporte FIDO2 vía libfido2 lleva estable desde OpenSSH 8.2 (febrero de 2020).
Los tipos ed25519-sk y ecdsa-sk almacenan la parte privada dentro del hardware; ed25519-sk requiere YubiKey firmware 5.2.3 o superior.
Con -O resident la credencial vive dentro de la YubiKey y se puede recuperar en un equipo nuevo con ssh-keygen -K.
La directiva PubkeyAuthOptions verify-required en sshd_config obliga al PIN FIDO2 más el toque físico en cada autenticación.
Compra al menos dos YubiKeys y regístralas en paralelo: si pierdes una, la de respaldo evita quedar fuera del servidor.
La misma librería libfido2 también protege el arranque cifrado con systemd-cryptenroll, unificando el modelo hardware-first en todo Linux.
¿Qué es SSH con FIDO2 y por qué usarlo en 2026?
SSH con FIDO2 es una variante del algoritmo de clave pública en la que la parte privada se genera y almacena dentro de un autenticador hardware (como una YubiKey) y nunca sale de él. Cuando el servidor emite un desafío, la llave firma la respuesta internamente y devuelve la firma a través del transporte USB, NFC o Lightning. El resultado es que un atacante que obtenga acceso remoto a tu portátil ya no puede robar la clave privada: no hay archivo que exfiltrar. Ese cambio de modelo de amenaza es la razón principal por la que la documentación oficial de Yubico recomienda migrar cualquier acceso administrativo a claves -sk.
Honestamente, la primera vez que migré una flota entera de bastiones a ed25519-sk me quedé mirando la YubiKey durante diez segundos preguntándome si iba a parpadear. Sí lo hizo, y desde entonces no he vuelto a guardar una clave SSH sin protección hardware en ningún equipo de producción. La curva de aprendizaje es corta; el ahorro operativo tras el primer incidente evitado, enorme.
En 2026 hay tres factores que aceleran la adopción. Primero, la mayoría de organizaciones ya han desplegado 2FA en aplicaciones web mediante passkeys, y reutilizar la misma YubiKey para SSH reduce el coste operativo. Segundo, OpenSSH 10.x completó la retirada de DSA y endureció los algoritmos aceptados por defecto, así que los administradores están tocando sshd_config igualmente. Tercero, los ataques de exfiltración basados en infostealers como RedLine o Vidar buscan activamente ~/.ssh/id_ed25519; una clave hardware convierte ese vector en un callejón sin salida.
La contrapartida es doble: dependes físicamente del dispositivo (perder la llave equivale a perder el acceso si no hay respaldo) y el flujo de despliegue es distinto al de las claves clásicas. Todo el resto de esta guía se centra en resolver esas dos fricciones sin sacrificar seguridad.
Requisitos: OpenSSH, libfido2 y YubiKey compatibles
El soporte FIDO2 en OpenSSH depende de tres piezas encadenadas: un OpenSSH compilado con soporte de tokens de seguridad, la librería libfido2 del sistema, y un autenticador FIDO2 físico conectado por USB o NFC. Verifica cada capa antes de intentar generar la clave:
# 1. Versión de OpenSSH (mínimo 8.2, recomendado 10.5+)
ssh -V
# 2. libfido2 instalada y accesible
ldconfig -p | grep libfido2
# libfido2.so.1 (libc6,x86-64) => /usr/lib/x86_64-linux-gnu/libfido2.so.1
# 3. La YubiKey aparece como dispositivo FIDO
fido2-token -L
# /dev/hidraw2: vendor=0x1050, product=0x0407 (YubiKey OTP+FIDO+CCID)
Si fido2-token -L no lista la llave, el problema casi siempre está en las reglas udev. En Debian y Ubuntu instala el paquete libfido2-1 y fido2-tools; en Fedora usa dnf install libfido2 fido2-tools, y en Arch pacman -S libfido2. Yubico mantiene además el PPA ppa:yubico/stable con versiones actualizadas si tu distro va rezagada.
Modelos YubiKey compatibles
Todas las llaves de la serie YubiKey 5 (5, 5C, 5 NFC, 5C NFC, 5Ci, 5 Nano), la Security Key Series y la YubiKey Bio (con verificación biométrica) son compatibles. El firmware 5.7 y superior permite hasta 100 credenciales residentes, añade Ed25519 y X25519 nativos y habilita largeBlobs para certificados SSH. Cualquier unidad fabricada desde el 21 de mayo de 2024 incluye el fix para la vulnerabilidad Eucleak (YSA-2024-03), por lo que si compras nuevo estás cubierto.
Cómo generar una clave ed25519-sk residente
Una clave residente guarda la credencial dentro de la propia YubiKey junto a un identificador de aplicación. La ventaja es que puedes llegar a otro portátil, ejecutar ssh-keygen -K y recuperar el archivo id_ed25519_sk pidiendo el PIN. La contrapartida es que ocupa un slot de passkey de la llave (100 en firmware 5.7+). Este es el flujo canónico para 2026:
# Genera una passkey residente ligada a la aplicación "ssh:mi-servidor"
ssh-keygen -t ed25519-sk \
-O resident \
-O verify-required \
-O application=ssh:mi-servidor \
-C "[email protected]" \
-f ~/.ssh/id_ed25519_sk_prod
# ssh-keygen pedirá el PIN de la YubiKey y luego el toque físico.
# Salida: dos archivos, id_ed25519_sk_prod y id_ed25519_sk_prod.pub
# El "privado" es solo un handle: el secreto real vive en el hardware.
Explicación de cada opción:
-O resident: almacena la credencial dentro de la YubiKey. Requiere obligatoriamente un PIN FIDO2 configurado (si no lo tienes, ejecuta ykman fido access change-pin antes).
-O verify-required: pide PIN o biometría en cada uso, no solo el toque. Es la opción recomendada para acceso administrativo.
-O application=ssh:: identificador que permite tener varias credenciales SSH distintas en la misma llave (por entorno, cliente o servidor). El prefijo ssh: es obligatorio.
-C: comentario visible al listar claves; útil para inventario.
Copia la clave pública al servidor con ssh-copy-id -i ~/.ssh/id_ed25519_sk_prod.pub usuario@servidor como con cualquier clave clásica. En el primer login la YubiKey pedirá el PIN y luego parpadeará esperando el toque; sin ese contacto físico, la firma no se emite y la sesión no se abre.
Alternativa sin PIN para automatización controlada
Para procesos batch donde el PIN es inviable, existe la opción -O no-touch-required. Debe autorizarse explícitamente en el servidor (ver siguiente sección) porque anula el segundo factor humano. Úsala solo si el equipo cliente está bajo control físico permanente y ha desplegado además cifrado de disco completo, como el que describimos en nuestra guía de cifrado LUKS2 con TPM 2.0 y systemd-cryptenroll.
Configurar sshd_config para exigir FIDO2
Del lado servidor, hay que aceptar los tipos de clave hardware y decidir la política de verificación. Edita /etc/ssh/sshd_config (o mejor, un drop-in en /etc/ssh/sshd_config.d/50-fido2.conf) con este contenido mínimo:
# /etc/ssh/sshd_config.d/50-fido2.conf
# Solo algoritmos post-cuánticos y hardware; sin RSA legado
PubkeyAcceptedAlgorithms [email protected],[email protected],ssh-ed25519,rsa-sha2-512
# Exige PIN + toque en cada login con claves -sk
PubkeyAuthOptions verify-required
# Desactiva por completo contraseñas
PasswordAuthentication no
KbdInteractiveAuthentication no
# Solo login por clave pública
AuthenticationMethods publickey
Valida la sintaxis y recarga el servicio con:
sudo sshd -t && sudo systemctl reload ssh
# En Debian el unit se llama "ssh"; en RHEL/Fedora es "sshd".
La directiva PubkeyAuthOptions acepta tres valores: none (comportamiento por defecto), touch-required (solo toque) y verify-required (PIN o biometría más toque). Solo afecta a las claves *-sk, así que no rompe otras autenticaciones. Puedes también matizar por clave añadiendo prefijos en ~/.ssh/authorized_keys: por ejemplo, verify-required [email protected] AAAA... obliga PIN solo para esa entrada en concreto.
Recuperar claves residentes en un equipo nuevo
Uno de los superpoderes de las claves residentes es que puedes olvidarte del archivo privado y reconstruirlo desde el hardware. Al llegar a un equipo limpio (portátil nuevo, workstation compartida, contenedor de administración) basta con:
cd ~/.ssh && ssh-keygen -K
# Enter PIN for authenticator:
# Enter passphrase (empty for no passphrase):
# Saved ED25519-SK key ssh:mi-servidor to ./id_ed25519_sk_rk_mi-servidor
El comando pide el PIN, contacta con la YubiKey y regenera el par de archivos id_ed25519_sk_rk_<application> más .pub. El material secreto sigue dentro del chip; lo que se materializa en disco es únicamente el credential handle que OpenSSH necesita para hablar con el autenticador. Desde OpenSSH 10.5, ssh-add -K usa además la cadena de aplicación como comentario, así que ssh-add -L muestra directamente para qué sirve cada clave residente cargada.
Este flujo es la respuesta operativa a "¿qué hago si me roban el portátil?": revocas la clave pública en los servidores (basta con eliminar la línea de authorized_keys) mientras la YubiKey sigue en tu bolsillo y puedes rehidratar el acceso en cualquier equipo de reemplazo en segundos.
Diferencias entre ed25519-sk y ecdsa-sk
OpenSSH soporta dos tipos de clave hardware y elegir el correcto evita problemas de compatibilidad. Esta tabla resume las diferencias que importan en producción:
Característica
ed25519-sk
ecdsa-sk
Curva
Edwards25519 (EdDSA)
NIST P-256 (ECDSA)
Firmware YubiKey mínimo
5.2.3
Todas las FIDO2
Cliente Windows nativo
Requiere OpenSSH 8.9+ en Windows
Sí, desde Windows 10 21H2
Tamaño de firma
64 bytes
~72 bytes (variable)
Determinismo
Firma determinista
Requiere RNG en cada firma
Estándar FIDO2
Extensión opcional
Obligatorio en toda llave FIDO2
Recomendación 2026
Opción por defecto
Solo si necesitas compatibilidad legada
La regla práctica es: usa ed25519-sk a menos que un cliente o servidor legado te obligue lo contrario. La firma determinista de EdDSA elimina toda una clase de fallos criptográficos (como los que hundieron ECDSA en la PlayStation 3) y el tamaño reducido acelera el handshake en enlaces de alta latencia. GitHub, GitLab y Gitea aceptan ambos tipos desde 2022; ninguno soporta no-touch-required al empujar código, así que cada git push pedirá el toque físico. Eso es intencional.
Backup, rotación y qué hacer si pierdes la YubiKey
Las claves hardware no admiten backup del secreto (esa imposibilidad es el punto). El patrón correcto es registrar dos llaves en paralelo: una que llevas contigo y otra guardada en una caja fuerte física. Ambas generan claves públicas distintas y ambas se añaden a ~/.ssh/authorized_keys en cada servidor. Si pierdes la primaria, la de respaldo mantiene el acceso mientras revocas la comprometida.
# En cada YubiKey, con application distinta para trazabilidad:
ssh-keygen -t ed25519-sk -O resident -O verify-required \
-O application=ssh:prod-yk-primaria -f ~/.ssh/id_sk_primaria
# Cambia la llave y repite:
ssh-keygen -t ed25519-sk -O resident -O verify-required \
-O application=ssh:prod-yk-respaldo -f ~/.ssh/id_sk_respaldo
# Concatena ambas .pub y despliega
cat ~/.ssh/id_sk_primaria.pub ~/.ssh/id_sk_respaldo.pub > deploy.pub
scp deploy.pub servidor:~/.ssh/authorized_keys
Para rotación programada, adopta la misma cadencia que otras credenciales sensibles: cada 12 a 24 meses genera una nueva clave con application incrementada (ssh:prod-2026Q3), añádela a los servidores, desplaza la vieja durante 30 días y bórrala. Guarda un inventario simple en tu gestor de secretos (por ejemplo, en un secreto Vault con nombre ssh/yubikeys/inventario).
Despliegue en una flota de servidores
Escalar FIDO2 a decenas o cientos de hosts requiere separar dos preocupaciones: (1) distribuir las claves públicas y (2) hacer cumplir la política en sshd_config. Para lo primero, un rol de Ansible es la vía más limpia:
El truco crítico es la tarea sshd -t: si la configuración es inválida el playbook falla antes de tocar el handler de recarga, evitando dejar servidores sin acceso. Combina este rol con las prácticas de aislamiento de servicios que documentamos en hardening de servicios systemd con ProtectSystem y NoNewPrivileges para reducir el radio de daño incluso si un operador es comprometido en su estación.
Auditoría continua
Programa un chequeo semanal que revise que PubkeyAuthOptions sigue en verify-required y que ninguna entrada de authorized_keys lleva prefijo no-touch-required sin autorización explícita:
#!/usr/bin/env bash
# audit_fido2.sh - lanzar desde el bastión con SSH sin PIN a cada host
set -euo pipefail
for h in $(cat inventario.txt); do
ssh "$h" "sshd -T | grep -Ei 'pubkeyauthoptions|pubkeyacceptedalgorithms'" | \
grep -q 'verify-required' \
|| echo "FALLA: $h no exige verify-required"
ssh "$h" "grep -R 'no-touch-required' /home/*/.ssh/authorized_keys 2>/dev/null" \
&& echo "REVISAR: $h contiene claves no-touch-required"
done
Integración con ssh-agent, gpg-agent y GitHub
OpenSSH conoce las claves residentes desde el agente. Con la YubiKey conectada, ejecuta:
# Carga todas las passkeys SSH residentes desde el token
ssh-add -K
# Verifica qué claves cargó (el comentario incluye el "application string")
ssh-add -L
# [email protected] AAAA... ssh:mi-servidor
Cada firma pedirá el toque en la llave (y el PIN si activaste verify-required). Si prefieres usar gpg-agent (habitual si ya empleas la YubiKey para OpenPGP), apunta SSH_AUTH_SOCK al socket de GPG:
Ojo: OpenPGP (PIV) y FIDO2 son subsistemas independientes dentro de la YubiKey. Puedes usarlos a la vez, pero son universos criptográficos distintos: PIV usa RSA/ECDSA con PIN de 6-8 dígitos, mientras FIDO2 usa CTAP2 con PIN de hasta 63 caracteres.
Para GitHub y GitLab, sube la .pub como cualquier otra clave SSH. Ambos validan la firma verificando internamente el atestado FIDO. Publicar código requerirá tocar la llave en cada git push; si lo consideras demasiado fricción, mantén una clave ed25519 clásica solo para Git y reserva la -sk para el acceso a servidores. Es un compromiso razonable siempre que la clave clásica viva en un disco cifrado y esté protegida con passphrase fuerte.
Errores frecuentes y su diagnóstico
Vale, cambiemos de tema y hablemos de lo que suele romperse. Estos son los fallos que aparecen en la mayoría de despliegues iniciales (yo mismo caí en tres de los cinco antes de tomármelos en serio), con la causa raíz y el remedio inmediato:
"Key enrollment failed: requested feature not supported": el firmware de la YubiKey no soporta ed25519-sk. Actualiza con ykman o cambia a ecdsa-sk.
"sign_and_send_pubkey: signing failed for ED25519-SK ... device not found": la sesión SSH no ve la llave. Verifica fido2-token -L y las reglas udev del paquete libfido2.
"Permission denied (publickey)" pese a cargar la clave: sshd_config no incluye [email protected] en PubkeyAcceptedAlgorithms. Añádelo y recarga.
"user verification required" al firmar: generaste la clave con verify-required pero no configuraste PIN en la llave. Ejecuta ykman fido access change-pin.
Timeout esperando el toque: el LED de la YubiKey parpadea 30 segundos y luego aborta. Ten paciencia (o revisa que el puerto USB no esté en modo bajo consumo).
Cuando algo se comporta raro, el mejor punto de partida es leer los mensajes crudos de OpenSSH con ssh -vvv usuario@servidor. Los logs muestran exactamente qué algoritmo ofrece el cliente, cuál acepta el servidor y en qué punto falla el handshake. Contrastar esa salida con el manual oficial de sshd_config(5) de OpenBSD y las notas de versión de OpenSSH resuelve casi todos los enigmas sin necesidad de tirar más de tcpdump.
Preguntas frecuentes
¿Puedo usar la misma YubiKey en varios equipos sin copiar la clave privada?
Sí. Con claves residentes basta con conectar la YubiKey al equipo nuevo y ejecutar ssh-keygen -K para regenerar el handle local. El secreto nunca sale del chip, y el mismo authorized_keys del servidor sigue funcionando sin cambios.
¿Qué hago si pierdo la YubiKey principal?
Accede al servidor con la YubiKey de respaldo que registraste en paralelo, elimina la línea de la clave perdida de ~/.ssh/authorized_keys y genera un par nuevo. Sin respaldo previo tendrás que usar la consola física o el acceso out-of-band del proveedor cloud.
¿Es obligatorio el PIN o basta con el toque?
Depende de la política. Con PubkeyAuthOptions verify-required en el servidor y -O verify-required al generar la clave, el PIN es obligatorio en cada login. Para escritorios de administrador con control físico estricto puedes usar solo toque, pero pierdes el segundo factor.
¿Funciona FIDO2 SSH con GitHub, GitLab y Bitbucket?
Sí: los tres aceptan claves ed25519-sk y ecdsa-sk desde 2022. Cada git push pide el toque físico y no soportan no-touch-required, así que la fricción es intencional. Sube la .pub igual que cualquier otra clave SSH.
¿Cuál es la diferencia entre ed25519-sk y ecdsa-sk?
ed25519-sk usa la curva Edwards25519 (EdDSA), firma más rápida y determinista, y requiere firmware YubiKey 5.2.3 o superior. ecdsa-sk usa NIST P-256, es obligatorio en toda llave FIDO2 y ofrece máxima compatibilidad con clientes antiguos. Elige ed25519-sk por defecto.
Guía práctica para endurecer SSH en servidores Linux en 2026. Cubre criptografía post-cuántica con OpenSSH 10.0, certificados con CA propia, Fail2Ban, 2FA, bastiones SSH e integración con HashiCorp Vault.