
Hardening básico y efectivo para un VPS Linux expuesto a Internet
Medidas concretas para reducir superficie de ataque sin inflar innecesariamente la complejidad del servidor.
Tiempo de lectura: 8 min
Exponer un servidor Linux a Internet sin configuración de seguridad activa no es una cuestión de si será atacado, sino de cuándo. Los bots de escaneo masivo encuentran puertos abiertos en menos de 10 minutos tras el aprovisionamiento. Este artículo no vende miedo: entrega controles concretos, aplicables en menos de una hora, que eliminan la mayoría de los vectores de ataque comunes sin añadir complejidad operativa innecesaria.
1. SSH: el primer vector a endurecer
SSH mal configurado es la puerta de entrada más explotada en VPS expuestos. Cambios mínimos en /etc/ssh/sshd_config eliminan la mayoría de los ataques automatizados:
bash# /etc/ssh/sshd_config
Port 2222 # Cambia el puerto por defecto (reduce ruido de logs)
PermitRootLogin no # Nunca login directo como root
PasswordAuthentication no # Solo autenticación por llave pública
PubkeyAuthentication yes
AuthorizedKeysFile .ssh/authorized_keys
MaxAuthTries 3 # Limita intentos antes de cortar
ClientAliveInterval 300 # Cierra sesiones inactivas
ClientAliveCountMax 2
AllowUsers tu_usuario # Whitelist explícita de usuariosDespués de editar, recarga sin cortar tu sesión activa:
bashsshd -t # Valida la sintaxis antes de aplicar
systemctl reload sshdTrade-off importante: cambiar el puerto no es seguridad real, es reducción de ruido en logs. Un atacante con nmap lo encontrará igual. El valor real está en deshabilitar contraseñas y root.2. Firewall: principio de mínimo privilegio
Usa ufw si quieres simplicidad o nftables si necesitas control fino. Para la mayoría de VPS, ufw es suficiente:
bashapt install ufw -y
ufw default deny incoming
ufw default allow outgoing
ufw allow 2222/tcp
ufw allow 80/tcp
ufw allow 443/tcp
ufw enable
ufw status verbose¿Qué no abrir? Nunca expongas directamente: MySQL/MariaDB (3306), PostgreSQL (5432), Redis (6379), Elasticsearch (9200). Si una aplicación necesita acceso a base de datos desde afuera, usa un túnel SSH o VPN, no un puerto abierto.
3. Fail2ban: bloqueo automático de fuerza bruta
fail2ban monitorea logs y bloquea IPs que superan umbrales de fallos:
bashapt install fail2ban -y
cp /etc/fail2ban/jail.conf /etc/fail2ban/jail.localEdita /etc/fail2ban/jail.local:
ini[DEFAULT]
bantime = 1h
findtime = 10m
maxretry = 5
[sshd]
enabled = true
port = 2222
logpath = /var/log/auth.log
maxretry = 3bashsystemctl enable fail2ban
systemctl start fail2ban
fail2ban-client status sshd4. Actualizaciones: automatiza lo que no requiere criterio
bashapt install unattended-upgrades -y
dpkg-reconfigure --priority=low unattended-upgradesEn /etc/apt/apt.conf.d/50unattended-upgrades verifica:
Unattended-Upgrade::Allowed-Origins {
"${distro_id}:${distro_codename}-security";
};
Unattended-Upgrade::AutoFixInterruptedDpkg "true";
Unattended-Upgrade::Remove-Unused-Dependencies "true";Criterio: automatiza security updates solamente, no upgrades completos. Los upgrades de versión mayor pueden romper dependencias y requieren revisión manual.
5. Auditoría rápida de superficie expuesta
bashss -tlnp
systemctl list-units --type=service --state=running
ss -tnp state establishedServicios que frecuentemente corren por defecto y no se necesitan:
avahi-daemon— descubrimiento de red local, inútil en servidorcups— impresiónbluetooth
Para desactivar:
bashsystemctl disable --now avahi-daemon6. Usuario no-root con sudo controlado
bashadduser tu_usuario
usermod -aG sudo tu_usuario
mkdir -p /home/tu_usuario/.ssh
cp ~/.ssh/authorized_keys /home/tu_usuario/.ssh/
chown -R tu_usuario:tu_usuario /home/tu_usuario/.ssh
chmod 700 /home/tu_usuario/.ssh
chmod 600 /home/tu_usuario/.ssh/authorized_keysUna vez confirmado el acceso con el nuevo usuario, aplica PermitRootLogin no en SSH.
7. Lo que este artículo no cubre (y por qué)
Este hardening es la base. No cubre:
- IDS/IPS (Snort, Suricata): agrega valor en entornos con tráfico heterogéneo, pero introduce complejidad operativa real.
- SELinux / AppArmor: valioso, pero requiere tuning para no romper aplicaciones en producción.
- Auditoría de integridad (AIDE, Tripwire): útil, pero con overhead de mantenimiento.
- 2FA para SSH: recomendable si el servidor es crítico (Google Authenticator PAM funciona bien).
La decisión de agregar capas depende del perfil de riesgo del servidor, no de una checklist genérica.
Checklist de verificación final
- SSH no acepta contraseñas (
grep PasswordAuthentication /etc/ssh/sshd_config) - Root no puede conectarse por SSH
ufwactivo con políticadenypor defecto (ufw status)- Solo puertos necesarios abiertos (
ss -tlnp) fail2banactivo y monitoreando SSH (fail2ban-client status)- Actualizaciones de seguridad automatizadas
- Usuario no-root funcional con acceso por llave
- Sin servicios innecesarios corriendo
¿Tienes un VPS con configuración más compleja — múltiples aplicaciones, Docker expuesto, o acceso a base de datos remota? Esos escenarios tienen vectores adicionales que vale revisar por separado.