SSH es la puerta principal a tu VPS. Si un atacante la cruza, tiene acceso total a tu servidor.
Cada VPS recibe miles de intentos de acceso SSH al día. La configuración por defecto no es suficiente.
Esta guía cubre técnicas avanzadas de hardening SSH que van más allá de lo básico.
El problema con SSH por defecto
Configuración típica (insegura)
Puerto: 22 (conocido por todos)
Root login: Permitido
Autenticación: Contraseña (adivinable)
Cifrado: Algoritmos antiguos habilitados
Lo que enfrentas
| Métrica | Valor típico |
|---|---|
| Intentos de login/día | 5.000 - 50.000 |
| Bots escaneando | 24/7 |
| Tiempo para comprometer contraseña débil | Horas |
| Tiempo con clave SSH | Prácticamente infinito |
Capas de seguridad SSH
Capa 1: Firewall (bloquear puertos)
Capa 2: Fail2ban (bloquear IPs)
Capa 3: Puerto no estándar (reducir ruido)
Capa 4: Solo claves SSH (eliminar contraseñas)
Capa 5: Algoritmos modernos (cifrado fuerte)
Capa 6: 2FA (segunda verificación)
Capa 7: Port knocking (puerto oculto)
Configuración base segura
Archivo sshd_config completo
sudo nano /etc/ssh/sshd_config
# ===== CONFIGURACIÓN SSH HARDENING =====
# Puerto no estándar (elige uno alto)
Port 2222
# Solo IPv4 (o IPv6 si lo usas)
AddressFamily inet
# Interfaces específicas (opcional)
#ListenAddress 0.0.0.0
# ===== AUTENTICACIÓN =====
# Deshabilitar root login
PermitRootLogin no
# Solo autenticación por clave
PubkeyAuthentication yes
PasswordAuthentication no
PermitEmptyPasswords no
# Deshabilitar métodos inseguros
ChallengeResponseAuthentication no
KerberosAuthentication no
GSSAPIAuthentication no
# Usuarios permitidos (whitelist)
AllowUsers tu_usuario admin_backup
# Grupos permitidos (alternativa)
#AllowGroups sshusers
# ===== CIFRADO MODERNO =====
# Solo algoritmos seguros
KexAlgorithms curve25519-sha256,[email protected],diffie-hellman-group16-sha512,diffie-hellman-group18-sha512
Ciphers [email protected],[email protected],[email protected]
MACs [email protected],[email protected]
HostKeyAlgorithms ssh-ed25519,rsa-sha2-512,rsa-sha2-256
# ===== TIMEOUTS Y LÍMITES =====
# Tiempo para autenticarse
LoginGraceTime 30
# Intentos máximos por conexión
MaxAuthTries 3
# Sesiones simultáneas por usuario
MaxSessions 3
# Conexiones no autenticadas pendientes
MaxStartups 3:50:10
# Keepalive
ClientAliveInterval 300
ClientAliveCountMax 2
# ===== SEGURIDAD ADICIONAL =====
# Deshabilitar forwarding si no lo necesitas
AllowTcpForwarding no
X11Forwarding no
AllowAgentForwarding no
# Deshabilitar túneles
PermitTunnel no
# Banner de advertencia
Banner /etc/ssh/banner
# Logging detallado
LogLevel VERBOSE
# Strict mode (verifica permisos)
StrictModes yes
# ===== SFTP (si lo necesitas) =====
Subsystem sftp /usr/lib/openssh/sftp-server -f AUTHPRIV -l INFO
Aplicar cambios
# Verificar sintaxis
sudo sshd -t
# Si no hay errores, reiniciar
sudo systemctl restart sshd
⚠️ IMPORTANTE: Mantén una sesión SSH abierta mientras pruebas. Si algo falla, podrás corregirlo.
Claves SSH modernas
ED25519 vs RSA
| Aspecto | ED25519 | RSA 4096 |
|---|---|---|
| Seguridad | Excelente | Buena |
| Velocidad | Muy rápida | Lenta |
| Tamaño clave | 256 bits | 4096 bits |
| Compatibilidad | OpenSSH 6.5+ | Universal |
| Recomendación | Usar esta | Fallback |
Generar clave ED25519
# En tu máquina local (no en el servidor)
ssh-keygen -t ed25519 -a 100 -C "[email protected]"
Parámetros:
-t ed25519: Tipo de clave-a 100: Iteraciones KDF (más = más seguro)-C: Comentario identificativo
Generar clave RSA (si necesitas compatibilidad)
ssh-keygen -t rsa -b 4096 -a 100 -C "[email protected]"
Copiar clave al servidor
ssh-copy-id -i ~/.ssh/id_ed25519.pub -p 2222 usuario@tu-servidor
O manualmente:
# En el servidor
mkdir -p ~/.ssh
chmod 700 ~/.ssh
echo "tu-clave-publica" >> ~/.ssh/authorized_keys
chmod 600 ~/.ssh/authorized_keys
Permisos correctos
# En el servidor
chmod 700 ~/.ssh
chmod 600 ~/.ssh/authorized_keys
# En local
chmod 700 ~/.ssh
chmod 600 ~/.ssh/id_ed25519
chmod 644 ~/.ssh/id_ed25519.pub
Autenticación 2FA con Google Authenticator
Instalar
sudo apt install libpam-google-authenticator -y
Configurar para tu usuario
google-authenticator
Responde:
- Time-based tokens: y
- Update .google_authenticator: y
- Disallow multiple uses: y
- Rate limiting: y
Guarda los códigos de emergencia.
Configurar PAM
sudo nano /etc/pam.d/sshd
Añadir al principio:
auth required pam_google_authenticator.so
Configurar SSH
sudo nano /etc/ssh/sshd_config
# Habilitar challenge-response para 2FA
ChallengeResponseAuthentication yes
# Requerir clave + 2FA
AuthenticationMethods publickey,keyboard-interactive
sudo systemctl restart sshd
Flujo de login con 2FA
1. Conexión SSH
2. Verificación de clave pública ✓
3. Solicita código 2FA
4. Introduces código de Google Authenticator
5. Acceso concedido
Port Knocking
Port knocking oculta SSH completamente. El puerto solo se abre después de “tocar” una secuencia de puertos.
Instalar knockd
sudo apt install knockd -y
Configurar secuencia
sudo nano /etc/knockd.conf
[options]
UseSyslog
[openSSH]
sequence = 7000,8000,9000
seq_timeout = 5
command = /sbin/iptables -A INPUT -s %IP% -p tcp --dport 2222 -j ACCEPT
tcpflags = syn
[closeSSH]
sequence = 9000,8000,7000
seq_timeout = 5
command = /sbin/iptables -D INPUT -s %IP% -p tcp --dport 2222 -j ACCEPT
tcpflags = syn
Habilitar
sudo nano /etc/default/knockd
START_KNOCKD=1
KNOCKD_OPTS="-i eth0"
sudo systemctl enable knockd
sudo systemctl start knockd
Bloquear puerto SSH por defecto
sudo iptables -A INPUT -p tcp --dport 2222 -j DROP
Usar port knocking
Desde el cliente:
# Knock para abrir
knock servidor.com 7000 8000 9000
# Conectar (tienes 5 segundos)
ssh -p 2222 [email protected]
# Knock para cerrar (opcional)
knock servidor.com 9000 8000 7000
Script de conexión
#!/bin/bash
# connect-vps.sh
SERVER="tu-servidor.com"
PORTS="7000 8000 9000"
echo "Knocking..."
knock $SERVER $PORTS
sleep 1
echo "Connecting..."
ssh -p 2222 usuario@$SERVER
Bastión SSH (Jump Host)
Para infraestructuras con múltiples servidores:
Internet → Bastión → Servidores internos
Configurar cliente SSH
# ~/.ssh/config
# Bastión (único punto de entrada)
Host bastion
HostName bastion.tudominio.com
Port 2222
User admin
IdentityFile ~/.ssh/id_ed25519
# Servidor interno (a través de bastión)
Host servidor-web
HostName 10.0.0.10
User deploy
ProxyJump bastion
Host servidor-db
HostName 10.0.0.20
User deploy
ProxyJump bastion
Uso
# Conectar al servidor web a través del bastión
ssh servidor-web
# Es equivalente a:
# ssh -J bastion [email protected]
SSH Agent y gestión de claves
Iniciar SSH Agent
eval $(ssh-agent -s)
ssh-add ~/.ssh/id_ed25519
Añadir al .bashrc
# Iniciar ssh-agent si no está corriendo
if [ -z "$SSH_AUTH_SOCK" ]; then
eval $(ssh-agent -s)
ssh-add ~/.ssh/id_ed25519 2>/dev/null
fi
Forwarding de agent (con precaución)
# Solo para conexiones de confianza
ssh -A usuario@servidor
Cuidado: El forwarding de agent puede ser peligroso si el servidor está comprometido.
Monitorización de accesos
Ver intentos de login
# Intentos fallidos
sudo grep "Failed password" /var/log/auth.log | tail -20
# Logins exitosos
sudo grep "Accepted" /var/log/auth.log | tail -20
# Usuarios que intentaron conectar
sudo grep "Invalid user" /var/log/auth.log | awk '{print $8}' | sort | uniq -c | sort -rn | head -20
Script de alerta
#!/bin/bash
# /root/scripts/ssh-alert.sh
LOGINS=$(grep "Accepted" /var/log/auth.log | grep "$(date +%b\ %d)" | wc -l)
FAILED=$(grep "Failed" /var/log/auth.log | grep "$(date +%b\ %d)" | wc -l)
if [ $LOGINS -gt 0 ] || [ $FAILED -gt 100 ]; then
echo "SSH Report $(date)
Logins exitosos: $LOGINS
Intentos fallidos: $FAILED" | mail -s "SSH Daily Report" [email protected]
fi
Cron diario
0 8 * * * /root/scripts/ssh-alert.sh
Banner de advertencia
Crear banner
sudo nano /etc/ssh/banner
*******************************************************************
* ACCESO RESTRINGIDO *
* *
* Este sistema es privado. Todo acceso no autorizado está *
* prohibido y será perseguido legalmente. *
* *
* Todas las actividades son monitorizadas y registradas. *
*******************************************************************
Activar en sshd_config
Banner /etc/ssh/banner
Configuración cliente SSH
~/.ssh/config optimizado
# Configuración global
Host *
# Algoritmos modernos
HostKeyAlgorithms ssh-ed25519,rsa-sha2-512,rsa-sha2-256
KexAlgorithms curve25519-sha256,[email protected]
Ciphers [email protected],[email protected]
MACs [email protected],[email protected]
# Seguridad
HashKnownHosts yes
VisualHostKey yes
# Conexión
ServerAliveInterval 60
ServerAliveCountMax 3
# Compresión
Compression yes
# Tu VPS principal
Host mi-vps
HostName tu-servidor.com
Port 2222
User tu_usuario
IdentityFile ~/.ssh/id_ed25519
IdentitiesOnly yes
Uso
ssh mi-vps
# En lugar de: ssh -p 2222 [email protected]
Auditoría de configuración SSH
ssh-audit
# Instalar
pip3 install ssh-audit
# Auditar tu servidor
ssh-audit tu-servidor.com:2222
Verificar algoritmos
# Ver qué algoritmos acepta tu servidor
nmap --script ssh2-enum-algos -p 2222 tu-servidor.com
Checklist de hardening SSH
Básico (obligatorio)
| Tarea | ✓ |
|---|---|
| Root login deshabilitado | ☐ |
| Solo autenticación por clave | ☐ |
| Contraseñas deshabilitadas | ☐ |
| Puerto no estándar | ☐ |
| Fail2ban activo | ☐ |
Avanzado (recomendado)
| Tarea | ✓ |
|---|---|
| Solo algoritmos modernos | ☐ |
| AllowUsers configurado | ☐ |
| Timeouts configurados | ☐ |
| Logging verbose | ☐ |
| Banner de advertencia | ☐ |
Extra (alta seguridad)
| Tarea | ✓ |
|---|---|
| 2FA habilitado | ☐ |
| Port knocking | ☐ |
| Bastión para múltiples servers | ☐ |
| Alertas de login | ☐ |
Errores comunes
Error 1: Bloquearte a ti mismo
Prevención:
- Mantén sesión SSH abierta mientras configuras
- Ten acceso por consola VNC
- Prueba con
sshd -tantes de reiniciar
Error 2: Permisos incorrectos
# SSH es muy estricto con permisos
chmod 700 ~/.ssh
chmod 600 ~/.ssh/authorized_keys
chmod 600 ~/.ssh/id_*
Error 3: Olvidar recargar
sudo systemctl reload sshd
# reload mantiene conexiones existentes
# restart las corta
Error 4: 2FA sin códigos de emergencia
Siempre guarda los códigos de emergencia en lugar seguro.
Preguntas frecuentes
¿El puerto no estándar realmente ayuda?
Sí. Reduce el 99% del ruido de bots que solo escanean puerto 22. No es seguridad real, pero reduce logs y carga.
¿Puedo usar contraseña + clave?
Técnicamente sí, pero no aporta seguridad. Si tienes clave, desactiva contraseñas.
¿Port knocking es necesario?
Para la mayoría no. Es útil para servidores muy expuestos o que requieren máxima seguridad.
¿2FA ralentiza la conexión?
Añade unos segundos para introducir el código. Puedes configurar sesiones persistentes con ControlMaster.
Nuestra recomendación
Para cualquier VPS:
- Deshabilitar root y contraseñas
- Solo claves ED25519
- Puerto no estándar
- Fail2ban + firewall
- AllowUsers configurado
Para alta seguridad: Añade 2FA.
Para infraestructuras: Implementa bastión.
¿No quieres complicarte? La administración gestionada incluye hardening SSH profesional.
Conclusión
SSH seguro requiere múltiples capas. La configuración por defecto es insuficiente para un servidor expuesto a internet.
Implementa al menos el checklist básico hoy. Tu VPS estará mucho más seguro esta noche.
¿Quieres un VPS con SSH preconfigurado de forma segura? Explora los VPS de Avantys con hardening incluido.
Guías relacionadas
¿Quieres la guía completa con todos los casos de uso?
¿Quieres que lo hagamos por ti?
En Avantys gestionamos tu web, hosting y crecimiento digital de punta a punta. Tú a lo importante.