Cómo gestionar llaves SSH correctamente
Guía sobre uso de ed25519, permisos de archivos para sshd, configuración de bloques Host y cómo revocar llaves perdidas en Ubuntu 24.04 y OpenSSH.
Cómo funcionan las llaves SSH
Una llave SSH es un par de archivos: una llave privada que permanece en su dispositivo y una llave pública que se copia en cada servidor al que desee acceder. Al conectarse, el servidor utiliza la llave pública para enviar un desafío que solo la llave privada correspondiente puede responder. La llave privada nunca sale de su dispositivo, por lo que ningún secreto viaja por la red y un servidor comprometido no tiene nada útil que robar. Por eso las llaves son superiores a las contraseñas. La gestión correcta de las llaves SSH se basa en cuatro hábitos: una llave por dispositivo, los permisos de archivo que exige sshd, un archivo ~/.ssh/config para evitar escribir opciones y saber cómo eliminar una llave el día que se pierda una laptop.
Esta guía cubre cada hábito en Ubuntu 24.04, aunque casi todo lo aquí expuesto se aplica a cualquier servidor Linux y a cualquier versión reciente de OpenSSH.
Una aclaración de vocabulario antes de comenzar para evitar errores graves. La llave pública no es secreta. Puede pegarla en un ticket, enviarla por correo electrónico o publicarla, y nadie podrá iniciar sesión con ella. La llave privada es el secreto. Para sus servidores, cualquier persona que copie ese archivo y conozca su frase de paso (si tiene una) es usted.
Crear una clave: ed25519 es el estándar recomendado
En su propio equipo, no en el servidor, ejecute:
ssh-keygen -t ed25519 -C "laptop"-t ed25519 define el tipo de clave. Ed25519 es el estándar moderno: las claves son cortas, rápidas y son compatibles con todas las versiones de OpenSSH desde 2014. Use ssh-keygen -t rsa -b 4096 solo si es estrictamente necesario conectarse a un dispositivo antiguo que no soporte ed25519. -C "laptop" establece un comentario. El comentario no tiene funciones criptográficas, pero sirve para identificar esta clave en el archivo authorized_keys del servidor dentro de dos años; por ello, use el nombre del dispositivo donde reside la clave.
ssh-keygen solicita la ruta de guardado de la clave. Acepte el valor predeterminado, ~/.ssh/id_ed25519. Luego solicitará una frase de paso (passphrase). Configure una; la sección de passphrase a continuación explica por qué no afecta su flujo de trabajo diario. Obtendrá dos archivos: ~/.ssh/id_ed25519 es la clave privada y ~/.ssh/id_ed25519.pub es la clave pública. Revise la mitad pública:
cat ~/.ssh/id_ed25519.pubssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIF3k2s0vQx7GdKQhX1yBz... laptopEs una sola línea: el tipo de clave, el contenido de la clave y su comentario. Esa línea es la que se copiará en sus servidores.
Una clave por dispositivo, no una por servidor
La pregunta inicial es: ¿necesito una clave nueva para cada servidor? No. Crea una clave para cada dispositivo que utilices y añade esa clave pública en cada servidor al que el dispositivo deba acceder. La clave identifica al dispositivo. El archivo authorized_keys en cada servidor es la lista de dispositivos permitidos.
Este es el modelo escalable; las alternativas fallan de forma predecible. Una clave por servidor implica que un portátil con veinte servidores contiene veinte claves privadas, lo que dificulta el control de cada una. Usar una única clave para todos los dispositivos es peor: si roban el portátil, no puedes revocar el acceso de ese dispositivo sin bloquear también el escritorio, ya que ambos poseen la misma clave privada. Esto te obligaría a reemplazar la clave en todos lados y redistribuirla en todos los dispositivos a la vez.
Con una clave por dispositivo, la pérdida del portátil solo requiere una línea por servidor: elimina la línea del portátil en authorized_keys y el resto de los dispositivos seguirán funcionando. El comentario que configures con -C permite localizar esa línea fácilmente.
La regla de este modelo: una clave privada se crea en un dispositivo y expira con dicho dispositivo. Nunca copies una clave privada a una segunda máquina ni la subas a un servidor. Cuando un nuevo dispositivo necesite acceso, genera una clave nueva en él.
Copie la clave pública en el servidor
La opción sencilla es ssh-copy-id, que se incluye con OpenSSH:
ssh-copy-id matt@10.0.0.10Inicia sesión con el método que aún funcione, generalmente una contraseña, añade su clave pública a ~/.ssh/authorized_keys en el servidor y crea el directorio y el archivo con los permisos correctos si no existen. Pruebe el resultado abriendo una nueva sesión SSH: el servidor debería permitirle el acceso sin solicitar la contraseña de la cuenta. Si su clave tiene una passphrase, es posible que su propia máquina se la solicite; ese aviso es local y no es la contraseña del servidor.
Cuando el acceso por contraseña ya está deshabilitado, ssh-copy-id no puede entrar, por lo que debe añadir la línea manualmente. Inicie sesión mediante una sesión que aún funcione o la consola web de su proveedor, y ejecute esto en el servidor:
mkdir -p ~/.ssh && chmod 700 ~/.ssh
echo "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIF3k2s0vQx7GdKQhX1yBz... laptop" >> ~/.ssh/authorized_keys
chmod 600 ~/.ssh/authorized_keysPegue su clave pública real dentro de las comillas, la línea completa de id_ed25519.pub. authorized_keys contiene una clave pública por línea, y esa es toda la base de datos de acceso: añadir un dispositivo consiste en agregar una línea, y revocar un dispositivo consiste en eliminar una. En un servidor nuevo, este paso forma parte de los primeros 10 minutos en un nuevo VPS, justo antes de desactivar el acceso por contraseña.
Los permisos que bloquean el inicio de sesión con llave
Esta es la causa más común de fallos en el inicio de sesión con llave, y el error no se muestra en el cliente. sshd se ejecuta con StrictModes yes por defecto en Ubuntu 24.04, lo que significa que rechaza el uso de un archivo authorized_keys que otros usuarios puedan editar. Si el archivo, el directorio ~/.ssh o su directorio home permiten la escritura a cualquier usuario distinto al suyo, sshd ignorará su llave y solicitará una contraseña sin dar explicaciones en el cliente. (El OpenSSH de Ubuntu permite exactamente un caso específico: un archivo con permisos de grupo para su propio grupo privado, en el que nadie más esté incluido. No dependa de esto; mantenga los modos indicados abajo). El motivo solo aparece en el log del servidor:
sudo grep 'Authentication refused' /var/log/auth.logEn una imagen mínima sin rsyslog no hay auth.log; la misma línea se encuentra en el journal: sudo journalctl -u ssh | grep 'Authentication refused'.
Authentication refused: bad ownership or modes for file /home/matt/.ssh/authorized_keysLa solución consiste en dos cambios de permisos y una verificación de propiedad, ejecutados en el servidor como el usuario afectado:
chmod 700 ~/.ssh
chmod 600 ~/.ssh/authorized_keys
chown -R matt:matt ~/.sshLa regla a recordar: 700 en el directorio .ssh, 600 en todo su contenido. Los mismos valores se aplican en su propio equipo, ya que el cliente también realiza la comprobación. Una llave privada legible por otros usuarios hace que ssh rechace la llave directamente, y en este caso el error es visible:
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@ WARNING: UNPROTECTED PRIVATE KEY FILE! @
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
Permissions 0644 for '/home/matt/.ssh/id_ed25519' are too open.chmod 600 ~/.ssh/id_ed25519 lo soluciona.
~/.ssh/config: deje de escribir opciones
Un archivo ~/.ssh/config en su propio equipo asigna un nombre corto a cada servidor y recuerda las opciones que escribe repetidamente. Créelo con permisos 600 y añada un bloque Host por cada servidor:
Host web1
HostName 10.0.0.10
User matt
IdentityFile ~/.ssh/id_ed25519
IdentitiesOnly yes
Host db1
HostName 10.0.0.11
User matt
Port 2222
IdentityFile ~/.ssh/id_ed25519
IdentitiesOnly yesAhora ssh web1 reemplaza a ssh -p 22 matt@10.0.0.10, y el mismo nombre corto funciona en scp, rsync y git, porque todos leen este archivo. HostName es la dirección real, User le evita escribir el nombre de usuario y IdentityFile define qué clave utilizar.
IdentitiesOnly yes merece una mención, ya que corrige un error confuso. Cuando su agent tiene varias claves, el client las ofrece una por una y el servidor cuenta cada oferta como un intento fallido. Con suficientes claves cargadas, obtendrá Received disconnect: Too many authentication failures antes de que se pruebe la clave correcta. IdentitiesOnly yes hace que el client ofrezca únicamente la clave especificada en IdentityFile, evitando así el error.
Passphrases y ssh-agent
Una passphrase cifra el archivo de la clave privada en el disco. Sin ella, cualquier persona que copie el archivo puede usarlo inmediatamente; con ella, el archivo robado es inútil hasta que se adivine la passphrase. Para una clave en un portátil, este es el nivel de protección necesario, ya que los portátiles se roban y las copias de seguridad de estos pueden filtrarse.
La razón por la que una passphrase no tiene coste práctico es ssh-agent. El agent mantiene su clave descifrada en memoria, por lo que solo escribe la passphrase una vez por sesión de inicio de sesión y cada conexión posterior es instantánea. La mayoría de las distribuciones de Linux para escritorio y macOS ya ejecutan un agent por usted. Cargue su clave en él con:
ssh-add ~/.ssh/id_ed25519ssh-add -l muestra las claves que el agent contiene actualmente. Una advertencia: el agent forwarding (ssh -A) permite que el servidor remoto use su agent para autenticarse en conexiones posteriores mientras usted está conectado; por tanto, actívelo solo hacia servidores de total confianza y manténgalo desactivado por defecto.
Rotación y revocación: el simulacro de la laptop perdida
Revocar una clave SSH simple consiste únicamente en eliminar su línea de authorized_keys en cada servidor que la contenga. No es necesario notificar a una autoridad de certificación ni esperar a una fecha de expiración. En cuanto se elimina la línea, los nuevos inicios de sesión con esa clave fallarán.
Realice el simulacro ahora, mientras no sea una emergencia. Elija un servidor, abra ~/.ssh/authorized_keys y localice la clave mediante su comentario. Elimine la línea con un editor o fíltrela por comentario:
grep -v ' laptop$' ~/.ssh/authorized_keys > ~/.ssh/authorized_keys.tmp
mv ~/.ssh/authorized_keys.tmp ~/.ssh/authorized_keysLuego, confirme desde el dispositivo que acaba de revocar que el inicio de sesión falla, y desde otro dispositivo que el inicio de sesión sigue funcionando. Tenga en cuenta un detalle: eliminar una clave no cierra las sesiones que ya están abiertas, porque la clave solo se verifica al iniciar sesión. Si está revocando un dispositivo robado, verifique también who en el servidor y finalice cualquier sesión que no reconozca.
La rotación es la misma operación con un orden distinto: genere una nueva clave en el dispositivo, instálela con ssh-copy-id, confirme que la nueva clave permite el acceso y luego elimine la línea antigua. Realice este proceso cuando un dispositivo cambie de propietario, cuando una clave pueda haber quedado expuesta o cuando alguien deje un equipo. Hacer esto manualmente en dos servidores es viable; en veinte servidores requiere automatización, y gestionar múltiples servidores Linux muestra cómo aplicar el mismo estado authorized_keys a toda una flota.
Qué no hacer
- No comparta una única clave privada en todos sus dispositivos. Esto impide revocar un dispositivo robado sin tener que reemplazar la clave en todos los demás equipos.
- No suba una clave privada a un repositorio git, aunque sea privado. Los escáneres automatizados monitorean los repositorios públicos e intentan usar las claves filtradas a los pocos minutos de un push; además, si un repositorio se vuelve público después, se filtra todo su historial.
- No suba la clave privada de su laptop a un servidor para que este pueda acceder a otro servidor. Genere una clave independiente en el propio servidor y autorice esa clave únicamente donde sea necesario.
- No pegue una clave privada en chats, correos electrónicos o tickets. La clave pública, el archivo
.pub, es la única parte que debe compartirse.
Una vez que su clave le permita iniciar sesión de forma fiable, desactive la autenticación por contraseña para evitar que los intentos de adivinación contra su servidor tengan éxito. La configuración necesaria para esto se encuentra en SSH hardening on a VPS.
FAQ
¿Cómo funcionan las llaves SSH sin enviar una contraseña?
El servidor almacena su llave pública en ~/.ssh/authorized_keys. Al iniciar sesión, el servidor envía un desafío, su cliente firma el desafío con la llave privada y el servidor verifica la firma con la llave pública. La llave privada nunca sale de su dispositivo, por lo que no hay nada que interceptar en tránsito ni nada reutilizable que robar del servidor. Un servidor comprometido solo filtra llaves públicas, las cuales no pueden usarse para iniciar sesión en ningún otro lugar.
¿Debo usar la misma llave SSH para todos mis servidores?
Usar una misma llave en varios servidores es correcto, siempre que esa llave permanezca en un único dispositivo. La regla es una llave por dispositivo, no una por servidor: la llave pública de su laptop debe estar en cada servidor al que la laptop necesite acceder, y su desktop debe tener su propia llave. Esto simplifica la revocación, ya que perder un dispositivo solo requiere eliminar una línea identificable de cada servidor, manteniendo el acceso de los demás dispositivos.
¿Qué permisos deben tener el directorio .ssh y el archivo authorized_keys?
Asigne 700 a ~/.ssh y 600 a authorized_keys y a cada llave privada; el propietario debe ser la cuenta que las utiliza. sshd se ejecuta con StrictModes yes por defecto, por lo que si un archivo o el directorio home permiten la escritura a otros usuarios, el servicio ignorará su llave silenciosamente. El único rastro será Authentication refused: bad ownership or modes en el log de auth o en el journal del servidor.
¿Cómo elimino una llave SSH de un servidor?
Elimine la línea de la llave en ~/.ssh/authorized_keys de la cuenta autorizada. Localice la línea correcta mediante su comentario (la etiqueta después del contenido de la llave). Los nuevos inicios de sesión con esa llave fallarán inmediatamente, pero las sesiones ya abiertas permanecerán activas; si el dispositivo fue robado, cierre también cualquier sesión activa de ese dispositivo. Repita este proceso en cada servidor donde se haya copiado la llave.
¿Necesito una passphrase en mi llave SSH?
Para una llave en una laptop o desktop, sí. La passphrase cifra el archivo de la llave, por lo que una copia robada o filtrada es inútil por sí sola. Además, ssh-agent permite escribirla una vez por sesión en lugar de hacerlo en cada conexión. Las llaves utilizadas por automatizaciones sin intervención humana en un servidor generalmente no tienen passphrase, ya que no hay una persona presente para escribirla; proteja estas llaves limitando los permisos de la cuenta de destino.