SSH con autenticación por clave sin contraseña: guía completa Ed25519
Configura SSH con autenticación por clave sin contraseña usando Ed25519 o RSA, desactiva el login por contraseña y protege servidores Linux contra ataques de fuerza bruta.
La contraseña en SSH es la mayor superficie de ataque de fuerza bruta que un servidor Linux expuesto a internet enfrenta. Los logs de cualquier VPS con puerto 22 abierto en internet muestran miles de intentos por día provenientes de botnets escaneando rangos enteros de IP en busca de combinaciones comunes. La defensa definitiva no es una contraseña más fuerte — es eliminar la autenticación por contraseña del servidor y aceptar solamente claves criptográficas.
Este tutorial es para sysadmins y desarrolladores que administran VPS o servidores dedicados Linux y quieren migrar a la autenticación por clave pública. Vas a generar un par de claves Ed25519 en tu máquina local, copiar la clave pública al servidor, validar el login por clave en una sesión paralela y solo entonces desactivar PasswordAuthentication con seguridad — el procedimiento evita que quedes bloqueado fuera en caso de que algo salga mal en la configuración.
Tiempo estimado: 15-20 minutos desde cero, asumiendo que ya tienes acceso SSH activo vía contraseña en el servidor de destino.
Requisitos previos
Acceso SSH activo al servidor vía contraseña (root o usuario con sudo), una máquina local Linux/macOS/WSL con OpenSSH instalado (ssh -V debe retornar 8.0 o superior), y dos terminales disponibles en tu máquina local — vamos a mantener la sesión original abierta como “red de seguridad” mientras validamos la nueva configuración en una segunda sesión.
Ed25519 256 bits 6.5+ (2014) ~/.ssh/authorized_keys 700 600 Generando el par de claves Ed25519
La generación de claves ocurre en tu máquina local (cliente), no en el servidor. La clave privada nunca debe salir de la máquina donde fue generada — solo la pública circula. Ed25519 es el estándar moderno: claves de 32 bytes, firma más rápida que RSA-4096 y resistencia criptográfica equivalente a RSA-3072.
Abre la terminal en tu máquina local y ejecuta:
ssh-keygen -t ed25519 -C "[email protected]" -f ~/.ssh/id_ed25519_hostiniEl parámetro -t ed25519 define el algoritmo, -C añade un comentario identificador (generalmente tu email — queda embebido en la clave pública y ayuda a identificar el origen en listas de claves), y -f define el nombre del archivo. Usa un nombre específico en vez del default id_ed25519 si gestionas múltiples servidores y quieres separar las claves.
Define una passphrase fuerte cuando se solicite:
Enter passphrase (empty for no passphrase): [escribe passphrase fuerte]
Enter same passphrase again: [confirma]La passphrase cifra la clave privada en disco — si alguien copia el archivo ~/.ssh/id_ed25519_hostini, todavía necesita la passphrase para usarla. No saltes esta etapa. Usa 4-6 palabras aleatorias o una frase larga — el ssh-agent (próxima sección) hace que escribas esto una vez por sesión, no en cada login.
Confirma que los dos archivos fueron creados:
ls -la ~/.ssh/id_ed25519_hostini*Debes ver id_ed25519_hostini (privada, permiso 600) y id_ed25519_hostini.pub (pública, permiso 644). La privada NUNCA sale de esa máquina — no la envíes por email, no la subas a Git, no la copies a un pendrive. Respaldo solo en gestor de contraseñas cifrado o cofre offline.
Copiando la clave pública al servidor
El método canónico es ssh-copy-id, que añade la clave pública en el ~/.ssh/authorized_keys del usuario remoto, creando el archivo con permisos correctos si no existe. Necesitarás escribir la contraseña SSH actual una última vez.
Ejecuta en la máquina local (sustituye usuario e IP):
ssh-copy-id -i ~/.ssh/id_ed25519_hostini.pub [email protected]Si usas puerto SSH no estándar: ssh-copy-id -i ~/.ssh/id_ed25519_hostini.pub -p 2222 [email protected]. El comando hace SSH al servidor (autenticando por contraseña), anexa la clave pública a ~/.ssh/authorized_keys, ajusta los permisos de ~/.ssh a 700 y del archivo a 600 — cualquier permiso más permisivo hace que el sshd rechace la clave silenciosamente.
Si ssh-copy-id no está disponible (raro en macOS antiguo), usa el método manual:
cat ~/.ssh/id_ed25519_hostini.pub | ssh [email protected] \
"mkdir -p ~/.ssh && chmod 700 ~/.ssh && \
cat >> ~/.ssh/authorized_keys && chmod 600 ~/.ssh/authorized_keys"Este pipe envía el contenido de la clave pública vía stdin, crea la carpeta .ssh con permiso correcto si no existe, anexa la clave al archivo authorized_keys (sin sobrescribir claves anteriores) y ajusta el permiso final.
Validando el login por clave antes de cambiar el servidor
Esta etapa es crítica. Necesitas confirmar que el login por clave funciona ANTES de deshabilitar la contraseña — de lo contrario, cualquier error de permiso o typo en el servidor te bloquea fuera.
Abre una SEGUNDA terminal (mantén la primera conectada como red de seguridad) e intenta conectar usando la clave:
ssh -i ~/.ssh/id_ed25519_hostini [email protected]Se te solicitará escribir la passphrase de la clave (no la contraseña del servidor). Si te logueas con éxito y caes en el shell del servidor, la autenticación por clave está funcionando. Si el servidor pide la contraseña del usuario en vez de la passphrase, algo está mal — no continúes.
Verifica en el servidor: ls -la ~/.ssh/ debe mostrar la carpeta con permiso 700 y authorized_keys con 600. El dueño de los archivos debe ser el propio usuario (no root). Los logs en /var/log/auth.log (Debian/Ubuntu) o /var/log/secure (RHEL/Rocky) muestran la razón exacta del rechazo — generalmente es “bad ownership or modes”.
Configurando ssh-agent para no escribir la passphrase a cada rato
Sin ssh-agent, escribes la passphrase en cada conexión SSH — lo cual es tedioso y lleva a passphrases cortas y débiles. El agent mantiene la clave descifrada en memoria durante la sesión.
Añade la clave al agent en la máquina local:
ssh-add ~/.ssh/id_ed25519_hostiniEn macOS, usa ssh-add --apple-use-keychain ~/.ssh/id_ed25519_hostini para integrar con Keychain — la passphrase queda guardada permanentemente y el agent abre sin prompt en reinicios. En Linux, añade eval "$(ssh-agent -s)" al ~/.bashrc si el agent no inicia automáticamente.
Crea un archivo ~/.ssh/config para simplificar las conexiones:
Host hostini-prod
HostName 45.xxx.xxx.xxx
User usuario
Port 22
IdentityFile ~/.ssh/id_ed25519_hostini
IdentitiesOnly yesAhora te conectas con ssh hostini-prod en vez del comando completo. IdentitiesOnly yes fuerza el uso solamente de la clave especificada — sin eso, el agent ofrece TODAS las claves cargadas al servidor, lo cual puede causar “Too many authentication failures” en servidores con MaxAuthTries bajo.
Desactivando la autenticación por contraseña en el servidor
Con el login por clave validado, ahora es seguro deshabilitar la autenticación por contraseña. Edita el archivo /etc/ssh/sshd_config en el servidor.
Conecta al servidor por la sesión validada (clave) y edita la configuración:
sudo nano /etc/ssh/sshd_configBusca y ajusta las siguientes directivas (descomenta removiendo el # si es necesario):
PasswordAuthentication no
PubkeyAuthentication yes
PermitRootLogin prohibit-password
ChallengeResponseAuthentication no
UsePAM yesPermitRootLogin prohibit-password permite root vía clave pero bloquea root vía contraseña — útil para automatización que necesita root. Si no necesitas root vía SSH (recomendado), usa PermitRootLogin no y haz sudo en el usuario común.
Valida la sintaxis antes de reiniciar el servicio:
sudo sshd -tOutput vacío = configuración válida. Si aparece error, NO reinicies sshd — corrige primero. Reiniciar sshd con config inválida puede dejar el servidor sin SSH activo hasta el reinicio.
Reinicia el servicio SSH:
sudo systemctl restart sshdEn Ubuntu/Debian recientes, el servicio puede llamarse ssh en vez de sshd — sudo systemctl restart ssh. La sesión actual NO se desconecta por el reinicio — sshd solo aplica las nuevas reglas a conexiones nuevas.
Mantén la sesión actual abierta. Abre una TERCERA terminal e intenta conectar desde cero con tu clave. Si funciona, la configuración está completa. Si falla, usa la sesión original (todavía abierta) para revertir PasswordAuthentication yes y reiniciar sshd. Solo cierra todas las sesiones después de validar que las conexiones nuevas funcionan.
Verificación final
Confirma que el servidor ahora rechaza contraseñas:
ssh -o PreferredAuthentications=password -o PubkeyAuthentication=no [email protected]
Output esperado: Permission denied (publickey). Este comando fuerza al cliente a intentar solamente contraseña, ignorando claves — si el servidor responde rechazando, está correctamente configurado para aceptar solo clave pública. Intenta también la conexión normal con clave (ssh hostini-prod) — debe loguear sin prompt de contraseña del servidor (solo passphrase si el agent no tiene la clave).
Resolución de problemas
”Permission denied” incluso con clave correcta
Verifica los permisos en el servidor (causa más común):
stat -c "%a %n" ~/.ssh ~/.ssh/authorized_keys
# Esperado: 700 /home/usuario/.ssh
# 600 /home/usuario/.ssh/authorized_keys
Si es diferente, corrige con chmod 700 ~/.ssh && chmod 600 ~/.ssh/authorized_keys. SELinux en servidores RHEL/Rocky puede bloquear la lectura incluso con permisos correctos — restorecon -R ~/.ssh aplica el contexto correcto.
”Too many authentication failures”
Sucede cuando ssh-agent intenta varias claves antes de llegar a la correcta. Fuerza solo la clave correcta:
ssh -o IdentitiesOnly=yes -i ~/.ssh/id_ed25519_hostini usuario@servidor
O añade IdentitiesOnly yes en el ~/.ssh/config de la máquina local como se mostró en el paso 8.
Bloqueado fuera después de deshabilitar contraseña
Usa la consola web del panel de la VPS para acceder al servidor directamente (bypass de SSH), edita /etc/ssh/sshd_config revirtiendo a PasswordAuthentication yes, reinicia el servicio e investiga el problema con calma. En proveedores que ofrecen consola serial, ese es el método de recuperación oficial.
Próximos pasos
- Configura fail2ban para bloquear intentos sospechosos en otras superficies (HTTP, SMTP) — SSH ya no lo necesita con la contraseña deshabilitada
- Cambia el puerto SSH por defecto (22 → 2222 o similar) — reduce el ruido de logs en ~95%, aunque no aumenta la seguridad real
- Configura 2FA vía TOTP en SSH con
pam_google_authenticatorpara una capa adicional en servidores críticos - Documenta las claves autorizadas en cada servidor — las claves abandonadas de ex-empleados son un vector real de incidente
- Considera SSH certificates con CA propia si gestionas una flota de 20+ servidores — escala mejor que distribuir claves manualmente
Si vas a poner esto en producción en una VPS Hostini, todos los planes VPS ya vienen con consola web de emergencia integrada al panel — respaldo seguro en caso de que una configuración SSH te bloquee fuera.
Preguntas frecuentes
¿Ed25519 o RSA: cuál elegir en 2026?
Ed25519 es el estándar recomendado para cualquier servidor nuevo — claves de 32 bytes, generación instantánea, firma más rápida que RSA-4096 y resistencia criptográfica equivalente. Usa RSA-4096 solo si necesitas interoperar con sistemas heredados (OpenSSH < 6.5, algunos appliances de red antiguos) que aún no soportan Ed25519. RSA-2048 ya no es aceptable para producción.
¿Puedo usar la misma clave SSH en varios servidores?
Técnicamente sí, y es común usar una clave por máquina cliente (laptop, escritorio) replicada en N servidores. El riesgo: si el cliente se ve comprometido, el atacante accede a todo. Mitigación: proteger la clave privada con una passphrase fuerte y usar ssh-agent. Entornos más sensibles (producción crítica) pueden aislar con una clave por grupo de servidores.
¿Qué sucede si pierdo mi clave privada?
Sin la clave privada y sin otro método de acceso, quedas bloqueado fuera — no existe recuperación criptográfica. Por eso el tutorial insiste en mantener PasswordAuthentication activo hasta validar el login por clave en una sesión paralela. En VPS, siempre tienes la consola web del panel como respaldo de emergencia para revertir la configuración.
¿Necesito desactivar el login por contraseña incluso con fail2ban instalado?
Sí. Fail2ban reduce la tasa de intentos, pero no elimina el vector — un atacante con una botnet distribuida de miles de IPs evade el umbral de intentos. Desactivar PasswordAuthentication elimina la categoría entera de ataques de fuerza bruta contra contraseña. Fail2ban sigue siendo útil para otras superficies (HTTP, SMTP).
¿Cómo funciona ssh-agent y por qué vale la pena usarlo?
ssh-agent es un daemon que mantiene tus claves descifradas en memoria durante la sesión, así escribes la passphrase una vez y usas la clave N veces sin volver a escribirla. En macOS el agent se integra con Keychain; en Linux, inicia junto con la sesión gráfica. En servidores intermedios, ssh-agent con ForwardAgent permite saltar a hosts internos sin copiar la clave privada — pero úsalo con moderación por seguridad.
¿Puedo restringir una clave SSH a comandos específicos?
Sí. El archivo ~/.ssh/authorized_keys acepta opciones antes de la clave: command="rsync ..." fuerza la ejecución de un único comando, from="1.2.3.4" restringe IPs de origen, no-port-forwarding y no-X11-forwarding deshabilitan funciones. Útil para claves de automatización (backup, deploy) que no deben dar shell interactivo si la clave se filtra.