Actualizado el

Seguridad SSH en servidores VPS: una guía práctica para empezar bien


Seguridad SSH en servidores VPS: una guía práctica para empezar bien

Ahora que estamos desarrollando más aplicaciones gracias a las posibilidades que dan los codificadores agénticos, es más fácil llevar ideas a la vida. Podemos construir prototipos, APIs, sitios internos, automatizaciones y pequeñas plataformas con una velocidad que antes era difícil de imaginar.

Para poner todo eso en línea, muchas veces terminamos usando un VPS. Se consiguen a buenos precios, dan bastante control y permiten ahorrar frente a servicios más administrados. Pero ese ahorro trae un compromiso: si el servidor queda mal configurado, también queda expuesto.

Esta guía busca ayudarte a mejorar la seguridad básica de tus VPS, sobre todo en el acceso por SSH. No pretende cubrir todos los escenarios posibles, pero sí darte una base práctica para empezar con menos riesgos.

La idea principal: no abras todo por comodidad

Un VPS conectado a internet recibe intentos de conexión todo el tiempo. Algunos son simples escaneos automáticos. Otros buscan contraseñas débiles, puertos abiertos, paneles sin protección o bases de datos expuestas.

La regla de partida es simple:

En un VPS no se abre todo “por si acaso”. Se habilitan solo los puertos necesarios, para los usuarios necesarios y desde los orígenes necesarios.

La seguridad no depende de una sola configuración. Conviene pensarla en capas.

CapaPregunta que respondeHerramientas habituales
Identidad¿Quién puede entrar?Usuarios Linux, llaves SSH, grupos
Acceso¿Cómo puede entrar?sshd_config, autenticación por llave, bloqueo de root
Red¿Por dónde puede entrar?ufw, reglas por puerto, reglas por IP

Si una capa falla, las demás deben reducir el daño.

Antes de tocar nada: mantén una salida de emergencia

Antes de cambiar SSH o activar firewall, revisa si tu proveedor permite abrir una consola web de recuperación. Casi todos los proveedores de VPS la tienen.

También trabaja con dos sesiones abiertas:

  1. Una sesión SSH donde haces los cambios.
  2. Otra sesión para probar que todavía puedes entrar.

No cierres la sesión original hasta confirmar que la nueva configuración funciona. Este detalle evita muchos sustos.

Paso 1: crea un usuario administrador distinto de root

Entrar como root por SSH es cómodo, pero no es una buena práctica. Lo recomendable es crear un usuario normal con permisos de administración mediante sudo.

Un ejemplo:

adduser devadmin
usermod -aG sudo devadmin

Luego entra con ese usuario:

ssh devadmin@IP_DE_TU_VPS

La idea es que root quede reservado para recuperación o tareas desde la consola del proveedor, no para el acceso diario.

Una separación básica de usuarios podría verse así:

UsuarioPermisosUso recomendado
rootControl totalRecuperación o consola del proveedor
devadminPuede usar sudoAdministración del servidor
deploySin sudo o con permisos limitadosDespliegues automatizados
www-dataSin login SSHEjecución del servidor web
backupPermisos limitadosTareas de respaldo

No entregues sudo a usuarios que ejecutan servicios, agentes o tareas automáticas salvo que exista una razón clara.

Paso 2: usa llaves SSH, no contraseñas

Una llave SSH tiene dos partes:

  • La llave privada, que se queda en tu computador y no se comparte.
  • La llave pública, que se copia al servidor.

Para crear una llave moderna puedes usar:

ssh-keygen -t ed25519 -C "[email protected]"

Luego copia la llave pública al servidor:

ssh-copy-id devadmin@IP_DE_TU_VPS

Prueba el acceso:

ssh devadmin@IP_DE_TU_VPS

En el servidor, los permisos del directorio .ssh deben ser restrictivos:

chmod 700 ~/.ssh
chmod 600 ~/.ssh/authorized_keys

Cuando confirmes que puedes entrar con llave, recién tiene sentido desactivar el acceso por contraseña.

Paso 3: endurece la configuración de SSH

El archivo principal suele estar en:

sudo nano /etc/ssh/sshd_config

Una configuración base puede incluir esto:

PermitRootLogin no
PasswordAuthentication no
PubkeyAuthentication yes
KbdInteractiveAuthentication no
X11Forwarding no
AllowTcpForwarding no
AllowUsers devadmin deploy
ClientAliveInterval 300
ClientAliveCountMax 2

Qué significa cada línea:

DirectivaPara qué sirve
PermitRootLogin noEvita entrar directamente como root
PasswordAuthentication noObliga a usar llaves SSH
PubkeyAuthentication yesPermite autenticación con llave pública
KbdInteractiveAuthentication noDesactiva métodos interactivos parecidos a contraseña
X11Forwarding noCierra una función que no suele usarse en VPS comunes
AllowTcpForwarding noEvita túneles SSH si no los necesitas
AllowUsers devadmin deployLimita qué usuarios pueden entrar por SSH
ClientAliveInterval 300Ayuda a cerrar sesiones inactivas
ClientAliveCountMax 2Define cuántas comprobaciones fallidas se toleran

Antes de reiniciar SSH, valida la configuración:

sudo sshd -t

Si no muestra errores, reinicia el servicio:

sudo systemctl restart ssh

En algunas distribuciones el servicio se llama sshd:

sudo systemctl restart sshd

Después abre una segunda conexión y verifica que puedes entrar. No cierres la primera sesión hasta probarlo.

Paso 4: decide si cambiarás el puerto SSH

Cambiar el puerto SSH no reemplaza las llaves, el firewall ni una buena configuración. Solo reduce algo de ruido de bots que prueban el puerto 22 por defecto.

Si decides usar otro puerto, por ejemplo 2222, agrega esta línea en sshd_config:

Port 2222

Antes de reiniciar SSH, abre ese puerto en el firewall:

sudo ufw allow 2222/tcp
sudo ufw reload

Luego conectas así:

ssh -p 2222 devadmin@IP_DE_TU_VPS

No cambies el puerto SSH sin abrir primero el puerto nuevo. Es una forma rápida de quedarte fuera.

Paso 5: activa UFW con una política cerrada

UFW permite administrar el firewall de forma sencilla. Para la mayoría de VPS, una base razonable es bloquear entradas y permitir salidas.

sudo ufw default deny incoming
sudo ufw default allow outgoing
sudo ufw limit ssh
sudo ufw enable
sudo ufw status verbose

Si usas un puerto personalizado:

sudo ufw limit 2222/tcp

La diferencia entre allow y limit importa:

ReglaEfecto
allow sshPermite SSH sin limitar intentos
limit sshPermite SSH, pero limita intentos repetidos desde una misma IP
deny incomingBloquea conexiones entrantes no autorizadas
allow outgoingPermite que el servidor salga a internet

ufw limit no reemplaza llaves SSH ni fail2ban, pero agrega una barrera útil cuando SSH queda expuesto.

Paso 6: restringe SSH por IP si puedes

Si tienes una IP fija o usas VPN, lo mejor es permitir SSH solo desde esa dirección.

sudo ufw allow from TU_IP_PUBLICA to any port 22 proto tcp

Si usas puerto personalizado:

sudo ufw allow from TU_IP_PUBLICA to any port 2222 proto tcp

Luego revisa las reglas numeradas y elimina la regla general de SSH si ya no la necesitas:

sudo ufw status numbered
sudo ufw delete NUMERO_DE_REGLA

Si no tienes IP fija, puedes dejar SSH abierto con limit ssh, pero debes compensar con llaves, fail2ban y revisión de logs.

Paso 7: abre puertos según el tipo de servicio

No todos los VPS deben exponer lo mismo. Un servidor web no necesita abrir los puertos de base de datos. Un servidor de monitoreo no debería publicar todos sus paneles a internet.

VPS solo para administración o agentes remotos

Si el servidor se usa para scripts, bots internos, tareas programadas o herramientas de desarrollo remoto, probablemente solo necesite SSH.

sudo ufw default deny incoming
sudo ufw default allow outgoing
sudo ufw allow from TU_IP_PUBLICA to any port 22 proto tcp
sudo ufw enable

Si no tienes IP fija:

sudo ufw limit ssh

Servidor web público

Para Nginx, Apache, aplicaciones estáticas o apps detrás de proxy, lo normal es abrir HTTP y HTTPS.

sudo ufw allow from TU_IP_PUBLICA to any port 22 proto tcp
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp

Si usas perfiles de UFW:

sudo ufw app list
sudo ufw allow "Nginx Full"

API pública

Si tienes una API en FastAPI, Express, Django, Laravel o similar, evita exponer directamente el puerto interno de la aplicación.

Lo recomendable es usar Nginx o Apache como proxy inverso y abrir solo 80 y 443 al público.

sudo ufw allow from TU_IP_PUBLICA to any port 22 proto tcp
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp

La aplicación debería escuchar en 127.0.0.1, no en 0.0.0.0, si solo será atendida por el proxy.

Base de datos

Una base de datos no debería quedar abierta a todo internet.

ServicioPuerto frecuenteRecomendación
PostgreSQL5432/tcpAbrir solo desde IPs autorizadas
MySQL o MariaDB3306/tcpAbrir solo desde IPs autorizadas
MongoDB27017/tcpEvitar exposición pública
Redis6379/tcpNo exponer públicamente

Ejemplo para PostgreSQL desde un servidor de aplicación:

sudo ufw allow from IP_DEL_SERVIDOR_APP to any port 5432 proto tcp

Ejemplo para MySQL:

sudo ufw allow from IP_DEL_SERVIDOR_APP to any port 3306 proto tcp

Para Redis, si no hay una razón muy clara, bloquea acceso público:

sudo ufw deny 6379/tcp

No uses reglas como sudo ufw allow 5432/tcp salvo que sepas exactamente por qué necesitas exponer ese puerto.

Moodle, WordPress o LMS

En plataformas educativas o sitios con usuarios, lo normal es abrir web y mantener la base de datos cerrada si vive en el mismo VPS.

sudo ufw allow from TU_IP_PUBLICA to any port 22 proto tcp
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp
sudo ufw deny 3306/tcp

Si la base de datos está en otro servidor, permite el puerto solo entre servidores.

sudo ufw allow from IP_DEL_SERVIDOR_MOODLE to any port 3306 proto tcp

Docker

Con Docker hay que tener cuidado. Docker puede publicar puertos aunque UFW parezca restrictivo.

Buenas prácticas:

  • No publiques puertos innecesarios con ports:.
  • Expón al público solo 80 y 443 si usas proxy inverso.
  • Usa redes internas de Docker para comunicación entre contenedores.
  • No expongas bases de datos en 0.0.0.0.

Ejemplo inseguro para una base de datos:

ports:
  - "5432:5432"

Ejemplo más seguro para un servicio interno:

expose:
  - "5432"

Además de revisar UFW, mira qué puertos publicó Docker:

docker ps

VPN

Si usas WireGuard u OpenVPN, abre solo el puerto de la VPN y luego limita SSH a la red privada.

WireGuard:

sudo ufw allow 51820/udp

OpenVPN:

sudo ufw allow 1194/udp

Cuando la VPN funcione, puedes permitir SSH solo desde la red VPN:

sudo ufw allow from 10.8.0.0/24 to any port 22 proto tcp

Monitoreo

Herramientas como Grafana, Prometheus o Node Exporter no deberían quedar abiertas sin control.

ServicioPuerto frecuenteRecomendación
Grafana3000/tcpAcceso por VPN o IP autorizada
Prometheus9090/tcpMejor acceso privado
Node Exporter9100/tcpNo abrir a internet

Ejemplo para Grafana solo desde tu IP:

sudo ufw allow from TU_IP_PUBLICA to any port 3000 proto tcp

Ejemplo para Node Exporter solo desde el servidor de monitoreo:

sudo ufw allow from IP_MONITOR to any port 9100 proto tcp

Paso 8: instala fail2ban

fail2ban bloquea IPs que realizan muchos intentos fallidos. No reemplaza una buena configuración SSH, pero ayuda a bajar ataques de fuerza bruta.

En Ubuntu o Debian:

sudo apt update
sudo apt install fail2ban -y
sudo systemctl enable fail2ban
sudo systemctl start fail2ban

Verifica el estado:

sudo systemctl status fail2ban

Paso 9: mantén el sistema actualizado

La seguridad no termina el día de la instalación. Un VPS requiere mantenimiento.

sudo apt update
sudo apt upgrade -y

También conviene revisar intentos de acceso.

En Ubuntu y Debian:

sudo journalctl -u ssh

En otros sistemas puede ser:

sudo journalctl -u sshd

Para revisar sesiones recientes:

last

Comandos de consulta rápida

Ver estado del firewall:

sudo ufw status verbose

Ver reglas numeradas:

sudo ufw status numbered

Eliminar una regla por número:

sudo ufw delete NUMERO_DE_REGLA

Ver puertos escuchando en el servidor:

sudo ss -tulpn

Validar configuración SSH:

sudo sshd -t

Reiniciar SSH:

sudo systemctl restart ssh

Checklist antes de cerrar la sesión

Antes de dar por terminado el trabajo, revisa esto:

  • Existe un usuario administrador distinto de root.
  • El usuario administrador puede usar sudo.
  • Los usuarios de servicios o agentes no tienen sudo si no lo necesitan.
  • Puedes entrar con llave SSH.
  • PermitRootLogin no está configurado.
  • PasswordAuthentication no está configurado.
  • sudo sshd -t no muestra errores.
  • UFW está activo.
  • UFW bloquea entradas por defecto.
  • Solo están abiertos los puertos necesarios.
  • SSH está restringido por IP si es posible.
  • Las bases de datos no están abiertas públicamente.
  • Los paneles internos no están expuestos sin protección.
  • Existe una forma de recuperación desde la consola del proveedor.

Cierre

Un VPS seguro no es el que tiene más herramientas instaladas. Es el que expone menos superficie, usa llaves SSH, separa usuarios, restringe privilegios y abre solo los puertos necesarios.

Los codificadores agénticos ayudan a construir más rápido, pero publicar una aplicación también implica hacerse cargo del entorno donde vive. Si vas a usar VPS baratos para ahorrar, está bien. Solo conviene pagar ese ahorro con orden, no con descuido.

Recursos

  • Herramientas mencionadas: OpenSSH, UFW, fail2ban, Docker