SSH es la puerta de entrada a tu servidor Linux. Cada servidor expuesto a internet recibe miles de intentos de inicio de sesión por fuerza bruta diariamente — bots automatizados escaneando en busca de contraseñas débiles, credenciales predeterminadas y servicios mal configurados. Una sola sesión SSH comprometida le da a un atacante control total. Esta guía te lleva a través de 12 pasos concretos para endurecer SSH, cada uno con los cambios exactos de configuración que necesitas hacer.
Antes de comenzar: Mantén siempre una sesión de terminal separada abierta mientras haces cambios en la configuración de SSH. Si configuras algo mal, puedes usar la sesión existente para corregirlo. Bloquearte fuera de un servidor remoto es un riesgo real, y es completamente prevenible.
Paso 1: Deshabilitar el inicio de sesión de root
El usuario root existe en todo sistema Linux, lo que lo convierte en el objetivo principal de ataques de fuerza bruta. Deshabilita el inicio de sesión directo de root y usa un usuario regular con sudo en su lugar.
Edita /etc/ssh/sshd_config:
PermitRootLogin no
Si necesitas acceso root para procesos automatizados (como respaldos), usa la opción más restrictiva:
PermitRootLogin prohibit-password
Esto permite el inicio de sesión de root solo con claves SSH, nunca con contraseña.
Paso 2: Usar autenticación basada en claves
Las claves SSH son fundamentalmente más seguras que las contraseñas. Una clave Ed25519 de 256 bits es virtualmente imposible de atacar por fuerza bruta, mientras que incluso una contraseña fuerte puede ser adivinada dado el tiempo suficiente.
Genera un par de claves en tu máquina local:
ssh-keygen -t ed25519 -C "tunombre@estacion"
Copia la clave pública al servidor:
ssh-copy-id -i ~/.ssh/id_ed25519.pub usuario@ip-de-tu-servidor
Verifica que el inicio de sesión basado en claves funcione antes de proceder al paso 3:
ssh -i ~/.ssh/id_ed25519 usuario@ip-de-tu-servidor
Consejo: Usa una frase de contraseña al generar tu clave. Sin una frase de contraseña, cualquiera que obtenga acceso a tu archivo de clave privada puede iniciar sesión en cada servidor que la confíe. Usa
ssh-agentpara evitar reescribir la frase de contraseña en cada conexión.
Paso 3: Deshabilitar la autenticación por contraseña
Una vez que la autenticación basada en claves está confirmada funcionando, deshabilita las contraseñas completamente.
Edita /etc/ssh/sshd_config:
PasswordAuthentication no
ChallengeResponseAuthentication no
UsePAM no
Advertencia: Si deshabilitas la autenticación por contraseña antes de configurar el inicio de sesión basado en claves, te quedarás bloqueado fuera de tu servidor. Siempre verifica que el inicio de sesión basado en claves funcione primero usando una sesión de terminal separada.
Paso 4: Cambiar el puerto SSH predeterminado
Mover SSH fuera del puerto 22 elimina la gran mayoría de bots de escaneo automatizado. Esto no es seguridad por oscuridad solamente — es reducción de ruido que hace tus logs más limpios y reduce la superficie de ataque.
Edita /etc/ssh/sshd_config:
Port 2222
Elige un puerto por encima de 1024 y por debajo de 65535. Las opciones comunes incluyen 2222, 2345 o un puerto alto aleatorio.
Actualiza tu firewall para permitir el nuevo puerto antes de reiniciar SSH:
sudo ufw allow 2222/tcp
sudo ufw deny 22/tcp
Conéctate usando el nuevo puerto:
ssh -p 2222 usuario@ip-de-tu-servidor
Paso 5: Usar solo el protocolo SSH 2
El protocolo SSH 1 tiene debilidades criptográficas conocidas. Aunque las versiones modernas de OpenSSH usan el protocolo 2 por defecto, aplicarlo explícitamente agrega defensa en profundidad.
Edita /etc/ssh/sshd_config:
Protocol 2
En versiones recientes de OpenSSH (7.0+), el soporte del protocolo 1 ha sido eliminado completamente, pero agregar esta línea no perjudica y protege contra escenarios de downgrade en sistemas antiguos.
Paso 6: Limitar el acceso de usuarios con AllowUsers y AllowGroups
Restringe qué usuarios pueden iniciar sesión vía SSH. Esto es especialmente importante en servidores multiusuario:
# Permitir usuarios específicos
AllowUsers deployer admin
# O permitir un grupo
AllowGroups sshusers
Para usar el enfoque basado en grupos, crea el grupo y agrega tus usuarios:
sudo groupadd sshusers
sudo usermod -aG sshusers deployer
sudo usermod -aG sshusers admin
Solo los miembros de sshusers podrán iniciar sesión vía SSH. Todos los demás usuarios del sistema (incluyendo cuentas de servicio) son denegados automáticamente.
Paso 7: Configurar el tiempo de inactividad
Las sesiones SSH inactivas son un riesgo de seguridad — una terminal desatendida puede ser explotada por alguien con acceso físico a la estación de trabajo.
Edita /etc/ssh/sshd_config:
ClientAliveInterval 300
ClientAliveCountMax 2
Esto envía un mensaje keep-alive cada 300 segundos (5 minutos). Si el cliente no responde después de 2 intentos, la sesión se desconecta. Tiempo total de inactividad: 10 minutos.
Paso 8: Usar algoritmos de clave fuertes
Restringe SSH a algoritmos modernos y seguros y deshabilita los débiles:
# Algoritmos de clave de host
HostKey /etc/ssh/ssh_host_ed25519_key
HostKey /etc/ssh/ssh_host_rsa_key
# Algoritmos de intercambio de claves
KexAlgorithms curve25519-sha256,curve25519-sha256@libssh.org,diffie-hellman-group16-sha512,diffie-hellman-group18-sha512
# Cifrados
Ciphers chacha20-poly1305@openssh.com,aes256-gcm@openssh.com,aes128-gcm@openssh.com
# MACs (Códigos de Autenticación de Mensaje)
MACs hmac-sha2-512-etm@openssh.com,hmac-sha2-256-etm@openssh.com
Elimina módulos Diffie-Hellman pequeños (menos de 3072 bits):
sudo awk '$5 >= 3071' /etc/ssh/moduli > /etc/ssh/moduli.safe
sudo mv /etc/ssh/moduli.safe /etc/ssh/moduli
Esto previene ataques de downgrade que explotan parámetros débiles de intercambio de claves.
Paso 9: Instalar y configurar Fail2ban
Fail2ban monitorea archivos de log y bloquea direcciones IP que muestran patrones maliciosos (como intentos repetidos de inicio de sesión fallidos).
sudo apt update
sudo apt install fail2ban -y
Crea un archivo de configuración local (nunca edites el jail.conf principal directamente):
sudo nano /etc/fail2ban/jail.local
[DEFAULT]
bantime = 3600
findtime = 600
maxretry = 3
banaction = ufw
[sshd]
enabled = true
port = 2222
filter = sshd
logpath = /var/log/auth.log
maxretry = 3
bantime = 86400
Esta configuración bloquea una IP por 24 horas después de 3 intentos fallidos de SSH dentro de 10 minutos. Ajusta el valor port para que coincida con tu puerto SSH personalizado del Paso 4.
Inicia y habilita fail2ban:
sudo systemctl enable fail2ban
sudo systemctl start fail2ban
Verifica las IPs bloqueadas:
sudo fail2ban-client status sshd
Paso 10: Configurar reglas de firewall con UFW
Usa el Uncomplicated Firewall (UFW) de Ubuntu para restringir el acceso de red:
# Establecer políticas predeterminadas
sudo ufw default deny incoming
sudo ufw default allow outgoing
# Permitir SSH en puerto personalizado
sudo ufw allow 2222/tcp comment 'SSH'
# Permitir otros servicios según sea necesario
sudo ufw allow 80/tcp comment 'HTTP'
sudo ufw allow 443/tcp comment 'HTTPS'
# Habilitar el firewall
sudo ufw enable
# Verificar reglas
sudo ufw status verbose
Para seguridad adicional, limita las conexiones SSH a direcciones IP específicas:
# Permitir SSH solo desde la IP de tu oficina
sudo ufw allow from 203.0.113.50 to any port 2222 proto tcp comment 'SSH from office'
# Permitir SSH desde tu subred VPN
sudo ufw allow from 10.8.0.0/24 to any port 2222 proto tcp comment 'SSH from VPN'
# Eliminar la regla general de SSH
sudo ufw delete allow 2222/tcp
Consejo: Si usas una VPN como WireGuard para acceder a tus servidores, puedes restringir SSH solo a la interfaz VPN. Consulta nuestra guía de configuración de WireGuard VPN para más detalles.
Paso 11: Habilitar la autenticación de dos factores (2FA)
Agrega una segunda capa de autenticación usando Google Authenticator:
sudo apt install libpam-google-authenticator -y
Ejecuta la configuración como tu usuario regular (no root):
google-authenticator
Responde las preguntas:
- Tokens basados en tiempo: Sí
- Actualizar archivo .google_authenticator: Sí
- No permitir múltiples usos: Sí
- Aumentar ventana de tiempo: No (a menos que tu reloj sea poco confiable)
- Habilitar límite de tasa: Sí
Edita /etc/pam.d/sshd y agrega al final:
auth required pam_google_authenticator.so
Edita /etc/ssh/sshd_config:
ChallengeResponseAuthentication yes
AuthenticationMethods publickey,keyboard-interactive
UsePAM yes
Esto requiere tanto una clave SSH como un código TOTP para iniciar sesión. La directiva AuthenticationMethods encadena los dos métodos — el usuario debe pasar ambos para obtener acceso.
Importante: Asegúrate de guardar los códigos de emergencia del setup de
google-authenticator. Almacénalos de forma segura fuera de línea. Si pierdes tu dispositivo autenticador, estos códigos son tu única forma de volver a entrar.
Reinicia SSH para aplicar:
sudo systemctl restart sshd
Prueba el inicio de sesión desde un nuevo terminal (mantén tu sesión existente abierta):
ssh -p 2222 usuario@ip-de-tu-servidor
Deberías recibir una solicitud de tu frase de contraseña de la clave y luego un código de verificación.
Paso 12: Usar SSH Config para conveniencia
Con todos estos pasos de endurecimiento, conectarse requiere recordar puertos, archivos de claves y nombres de usuario. Simplifica esto con un archivo de configuración SSH en tu máquina local.
Edita ~/.ssh/config:
Host miservidor
HostName 203.0.113.50
Port 2222
User deployer
IdentityFile ~/.ssh/id_ed25519
IdentitiesOnly yes
ServerAliveInterval 60
ServerAliveCountMax 3
Host staging
HostName 203.0.113.51
Port 2222
User deployer
IdentityFile ~/.ssh/id_ed25519
IdentitiesOnly yes
Host *.internal.knowledgexchange.xyz
ProxyJump bastion
User admin
Port 2222
Ahora puedes conectarte con un comando simple:
ssh miservidor
La directiva ProxyJump te permite acceder a servidores detrás de un host bastión sin reenvío de puertos manual. La configuración IdentitiesOnly yes previene que el cliente SSH intente cada clave en tu agente, lo que evita bloqueos accidentales por demasiados fallos de autenticación.
Referencia completa de sshd_config
Aquí tienes un /etc/ssh/sshd_config consolidado incorporando los 12 pasos:
# Red
Port 2222
Protocol 2
AddressFamily inet
ListenAddress 0.0.0.0
# Claves de host
HostKey /etc/ssh/ssh_host_ed25519_key
HostKey /etc/ssh/ssh_host_rsa_key
# Autenticación
PermitRootLogin no
PasswordAuthentication no
ChallengeResponseAuthentication yes
UsePAM yes
AuthenticationMethods publickey,keyboard-interactive
PubkeyAuthentication yes
MaxAuthTries 3
# Control de acceso
AllowGroups sshusers
# Tiempos de espera
ClientAliveInterval 300
ClientAliveCountMax 2
LoginGraceTime 30
# Seguridad
X11Forwarding no
AllowTcpForwarding no
AllowAgentForwarding no
PermitTunnel no
Banner /etc/ssh/banner
# Algoritmos
KexAlgorithms curve25519-sha256,curve25519-sha256@libssh.org,diffie-hellman-group16-sha512,diffie-hellman-group18-sha512
Ciphers chacha20-poly1305@openssh.com,aes256-gcm@openssh.com,aes128-gcm@openssh.com
MACs hmac-sha2-512-etm@openssh.com,hmac-sha2-256-etm@openssh.com
# Registro
LogLevel VERBOSE
Probar sin bloquearte
Sigue este protocolo cada vez que cambies la configuración de SSH:
- Abre dos sesiones de terminal al servidor
- Edita sshd_config en una sesión
- Prueba la sintaxis de configuración antes de recargar:
sudo sshd -t
- Reinicia SSH si la prueba pasa:
sudo systemctl restart sshd
- Prueba el inicio de sesión desde un nuevo terminal (mantén los otros dos abiertos)
- Solo cierra tus sesiones originales después de confirmar que la nueva configuración funciona
Si algo sale mal, usa tu sesión existente para revertir los cambios.
Monitorear el acceso SSH
Usa journalctl para monitorear los intentos de inicio de sesión SSH:
# Ver logs recientes de SSH
sudo journalctl -u sshd --since "1 hour ago"
# Ver logs en tiempo real
sudo journalctl -u sshd -f
# Encontrar intentos de inicio de sesión fallidos
sudo journalctl -u sshd | grep "Failed password"
# Contar IPs atacantes únicas
sudo journalctl -u sshd | grep "Failed password" | awk '{print $(NF-3)}' | sort | uniq -c | sort -rn | head -20
Para una vista más estructurada, revisa el log de autenticación directamente:
# Ver los últimos 50 eventos de autenticación
sudo tail -50 /var/log/auth.log
# Contar inicios de sesión exitosos hoy
sudo grep "Accepted" /var/log/auth.log | grep "$(date +%b\ %d)" | wc -l
Recomendaciones adicionales
Más allá de los 12 pasos anteriores, considera estas medidas adicionales:
- Configura un banner de inicio de sesión para advertir a usuarios no autorizados:
echo "Authorized access only. All activity is monitored and logged." | sudo tee /etc/ssh/banner
- Deshabilita métodos de autenticación no utilizados como GSSAPI:
GSSAPIAuthentication no
KerberosAuthentication no
-
Usa certificados SSH en lugar de archivos authorized_keys individuales para entornos con muchos servidores y usuarios
-
Rota las claves SSH regularmente — genera nuevos pares de claves anualmente y elimina las antiguas de
authorized_keys
Resumen
El endurecimiento de SSH no es opcional para ningún servidor expuesto a internet. Implementa estos 12 pasos en orden, probando cada cambio antes de continuar. Los pasos más impactantes son la autenticación basada en claves (Paso 2), deshabilitar el inicio de sesión por contraseña (Paso 3) e instalar fail2ban (Paso 9). Combinados, eliminan más del 99% de los ataques SSH comunes.
Para temas de seguridad relacionados, explora nuestras guías de servidor Ubuntu. Si quieres agregar una capa extra de protección enrutando SSH a través de una VPN, consulta nuestros artículos sobre redes seguras de servidor.