Qué resuelve
Con claves normales, cada servidor guarda una lista de claves permitidas, y cada portátil guarda una lista de claves de host. Con 50 servidores, añadir o quitar a una persona significa cambiar 50 archivos, y las claves viejas tienden a quedarse para siempre.
Con certificados, los servidores confían en una sola clave de CA. Firmas la clave pública de una persona por un tiempo determinado, y cuando el certificado caduca, el acceso termina. Son certificados de OpenSSH, no del tipo X.509 que se usa en los sitios web, y no necesitas ninguna empresa ni servicio externos.
Crear la CA
ssh-keygen -t ed25519 -f user_ca -C "user-ca"
Es un par de claves normal. Quien tenga la mitad privada user_ca puede iniciar sesión como cualquiera en todos los servidores que confían en ella, así que ponle una frase de contraseña robusta y mantenla fuera de tu máquina diaria y fuera de los servidores. Usa una CA aparte para los hosts, como se muestra más abajo.
Firmar la clave pública de un usuario
La persona te envía id_ed25519.pub, nunca la clave privada:
ssh-keygen -s user_ca -I "alice@example.com" -n deploy,alice -V +8h id_ed25519.pub
| Opción | Significado |
|---|---|
-s user_ca | La clave privada de la CA usada para firmar. |
-I | El ID de la clave. Se escribe en el registro del servidor en cada inicio de sesión, así que haz que nombre a la persona. |
-n | Los principals: los nombres para los que este certificado es válido. |
-V | La validez. +8h, +1d, o un rango como -5m:+1d, que además cubre un servidor cuyo reloj va un poco atrasado. |
El resultado es id_ed25519-cert.pub. Devuélveselo a la persona, que lo coloca junto a la clave privada. Entonces ssh lo encuentra por el nombre, sin configuración adicional. Si está en otro sitio, necesita una línea CertificateFile en ~/.ssh/config. Para leer uno:
ssh-keygen -L -f id_ed25519-cert.pub
Sin -V, un certificado nunca caduca, lo que elimina gran parte del beneficio.
Hacer que el servidor confíe en la CA
Copia user_ca.pub, solo la parte pública, a /etc/ssh/user_ca.pub en el servidor. Añade esto a la configuración de sshd, luego ejecuta sudo sshd -t y recarga:
TrustedUserCAKeys /etc/ssh/user_ca.pub
El usuario ya puede iniciar sesión sin ninguna línea en authorized_keys. El registro del servidor muestra quién fue:
Accepted publickey for deploy from 203.0.113.50 port 56276 ssh2: ED25519-CERT SHA256:... ID alice@example.com (serial 0) CA ED25519 SHA256:...
Principals
Por defecto, el servidor exige que el nombre de la cuenta sea uno de los principals del certificado. Un certificado para alice no abre la cuenta deploy.
Para usar roles en lugar de nombres de cuenta, enumera los principals aceptados para cada cuenta:
AuthorizedPrincipalsFile /etc/ssh/auth_principals/%u
Entonces /etc/ssh/auth_principals/deploy contiene un nombre por línea, por ejemplo ops, y firmas con -n ops. Con este ajuste activado, el nombre de la cuenta deja de aceptarse automáticamente: solo cuentan los nombres del archivo, y una cuenta sin archivo rechaza los certificados.
Limitar lo que puede hacer un certificado
Las opciones se fijan al firmar. Aquí el certificado solo funciona desde una red y no puede abrir una terminal:
ssh-keygen -s user_ca -I alice -n ops -V +1h -O source-address=203.0.113.0/24 -O no-pty id_ed25519.pub
-O clear quita todos los permisos por defecto, y luego puedes volver a añadir los que quieras, por ejemplo -O clear -O permit-pty.
Cuando falla un inicio de sesión
El cliente solo dice Permission denied (publickey). El motivo está en el registro del servidor:
| Línea del registro | Causa |
|---|---|
Certificate invalid: name is not a listed principal | La cuenta no está en la lista -n del certificado. |
Certificate invalid: expired | Pasó su fecha de fin. Fírmalo de nuevo. |
Refused by certificate options | Un límite como source-address no coincide. |
Authentication key ... revoked by file ... | La clave está en la lista de revocación. |
Revocar un certificado antes de que caduque
Mantén los certificados cortos, para necesitar esto pocas veces. Para el caso urgente, crea una lista de revocación de claves a partir de la clave pública y cópiala a cada servidor:
ssh-keygen -k -f revoked.krl id_ed25519.pub
ssh-keygen -Q -f revoked.krl id_ed25519.pub
RevokedKeys /etc/ssh/revoked.krl
Añade claves posteriores a la misma lista con -u. Ten cuidado con este archivo: si sshd no puede leerlo, el inicio de sesión con clave pública se rechaza para todos los usuarios.
Para claves sin certificado, consulta cómo revocar una clave SSH cuando alguien se va.
Certificados de host
Los certificados de host resuelven la dirección contraria. Tus usuarios dejan de ver el aviso de host desconocido, porque confían en una CA y no en cada clave de host. Firma la clave pública de host del servidor con -h, e indica los nombres con los que la gente se conecta:
ssh-keygen -t ed25519 -f host_ca -C "host-ca"
ssh-keygen -s host_ca -I server1 -h -n server1.example.com -V +52w ssh_host_ed25519_key.pub
En el servidor, con ssh_host_ed25519_key-cert.pub en /etc/ssh/:
HostKey /etc/ssh/ssh_host_ed25519_key
HostCertificate /etc/ssh/ssh_host_ed25519_key-cert.pub
En cada cliente, añade una línea a ~/.ssh/known_hosts, con el contenido de host_ca.pub:
@cert-authority *.example.com ssh-ed25519 AAAA...
El patrón debe coincidir con el nombre con el que te conectas. Cuando no coincide, ssh ignora la línea y trata el host como desconocido, o lo rechaza si StrictHostKeyChecking vale yes. Los certificados de host también caducan, así que renuévalos antes de esa fecha. Consulta known_hosts explicado para ver cómo funciona el resto de ese archivo.
Cuándo valen la pena los certificados
Para pocos servidores y pocas personas, las claves normales son más simples. Los certificados empiezan a compensar cuando la gente entra y sale a menudo, o cuando quieres un acceso de corta vida con un nombre en el registro. Lo difícil es el proceso alrededor de la CA: quién puede firmar, dónde vive la clave privada y cómo obtiene una persona un certificado nuevo cada día. ssh-keygen te da la firma, no ese proceso.
Preguntas
¿Qué diferencia hay entre una clave SSH y un certificado SSH?
Un certificado es una clave pública firmada por una CA, con una lista de usuarios permitidos y una fecha de caducidad. Un servidor que confía en la CA lo acepta sin una línea en authorized_keys para esa clave.
¿Cómo veo cuándo caduca un certificado SSH?
Ejecuta ssh-keygen -L -f id_ed25519-cert.pub. La línea Valid muestra el inicio y el fin de la validez.
¿Los certificados SSH sustituyen a authorized_keys?
Para los accesos con certificado, sí: al servidor le basta con TrustedUserCAKeys. Las claves normales de authorized_keys siguen funcionando al lado.
Fuentes
- ssh-keygen(1), sección CERTIFICATES, manual de OpenBSD
- sshd_config(5), manual de OpenBSD
- sshd(8), SSH_KNOWN_HOSTS FILE FORMAT, manual de OpenBSD