2026-02-18
By Santiago Bugnón
SecurityLinuxDevOps

VPS Configuration and Hardening Guide

VPS Configuration and Hardening Guide

Guía de Configuración y Hardening de un VPS

Referencia base: [Ubuntu Server Guide](https://ubuntu.com/server/docs), [CIS Benchmarks](https://www.cisecurity.org/cis-benchmarks), [SSH Hardening - Mozilla](https://infosec.mozilla.org/guidelines/openssh)

Nota: a lo largo del documento hay usuarios y textos de ejemplo los cuales tendrás que reemplazar por tu propio usuario u opciones personalizadas.

Datos del servidor de ejemplo

Estos datos son los que el proveedor de tu VPS te provee al crear la instancia del servidor.

CampoValor
IP`203.0.113.42`
Usuario`root`
Password`Xk9#mP2@vL5nQw`
`203.0.113.x` es un rango reservado para documentación (RFC 5737), no es una IP real.

Conectarse por primera vez:

ssh [email protected]

Paso 1 — Actualizar el sistema

apt update && apt upgrade -y

¿Por qué? El servidor recién creado tiene paquetes desactualizados desde la imagen base. Actualizar cierra vulnerabilidades conocidas antes de hacer cualquier otra cosa. Es el primer paso en cualquier guía de hardening seria (CIS, NIST).


Paso 2 — Crear un usuario sin privilegios con sudo

adduser santikz
usermod -aG sudo santikz

Para que no pida password al usar sudo:

visudo

Agregar al final del archivo:

santikz ALL=(ALL) NOPASSWD:ALL

(crea un usuario con cualquier nombre de tu preferencia, ej: admin, dev, sysadmin, marcelo, etc…)

¿Por qué? Operar siempre como `root` es una mala práctica. Si alguien compromete tu sesión, tiene control total del sistema. Un usuario sin privilegios limita el radio de acción de un atacante. `NOPASSWD` en sudo es un balance entre seguridad y comodidad aceptable en entornos de dev donde ya se usa autenticación por clave.


Paso 3 — Generar claves SSH y configurar acceso por clave pública

Cómo funcionan las claves SSH

SSH usa criptografía asimétrica: se generan dos claves matemáticamente vinculadas. La clave privada se queda en tu máquina local y nunca sale de ahí. La clave pública se copia al servidor. Cuando intentas conectarte, el servidor te manda un desafío cifrado con tu clave pública; solo quien tenga la clave privada correspondiente puede resolverlo. Si coincide, entras, sin necesidad de escribir una contraseña. Esto elimina el riesgo de que alguien intercepte o adivine tu password, ya que nunca viaja por la red. `ed25519` es el algoritmo recomendado actualmente por Mozilla y NIST: más corto, rápido y seguro que el tradicional RSA.

Generar las claves (en tu máquina local, no en el servidor)

# Linux / macOS
ssh-keygen -t ed25519 -f ~/.ssh/myserver

# Windows (PowerShell)
ssh-keygen -t ed25519 -f C:\Users\santikz\.ssh\myserver

Esto genera dos archivos:

  • `myserver` — clave privada (nunca compartir, nunca subir a git)
  • `myserver.pub` — clave pública (esta va al servidor)
  • Nota: dale un nombre descriptivo al archivo para poder diferenciar entre otras llaves de diferentes servidores.

    Copiar la clave pública al servidor con SCP

    Primero copiamos el archivo `.pub` al servidor usando `scp` (ssh copy). En este punto todavía usamos password porque aún no hemos configurado el acceso por clave:

    # Linux / macOS
    scp ~/.ssh/myserver.pub [email protected]:/home/santikz/
    
    # Windows (PowerShell)
    scp C:\Users\tuusuario\.ssh\myserver.pub [email protected]:/home/santikz/

    Agregar la clave pública a authorized_keys (en el servidor)

    Conectarse al servidor y ejecutar:

    ssh [email protected]
    mkdir -p ~/.ssh
    cat ~/myserver.pub >> ~/.ssh/authorized_keys
    rm ~/myserver.pub

    El archivo `authorized_keys` es la lista de claves públicas que el servidor acepta para autenticar. El operador `>>` agrega la clave al final del archivo sin borrar las existentes, lo que permite tener múltiples claves (por ejemplo, de distintos miembros del equipo).

    Verificar permisos en el servidor

    SSH es estricto con los permisos de estos archivos. Si están mal configurados, rechaza la clave aunque todo lo demás esté correcto.

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

    Configurar el archivo SSH local

    Este archivo permite definir alias para conectarse sin escribir usuario, IP y clave cada vez.

    Linux / macOS — archivo: `~/.ssh/config`

    Host myserver
        User santikz
        HostName 203.0.113.42
        IdentityFile ~/.ssh/myserver

    Windows — archivo: `C:\Users\tuusuario\.ssh\config`

    Host myserver
        User santikz
        HostName 203.0.113.42
        IdentityFile C:\Users\tuusuario\.ssh\myserver

    Con esto podrás conectarte simplemente con:

    ssh myserver

    Si el login por clave pública no funciona

    Verificar que esté habilitado en el servidor:

    sudo nano /etc/ssh/sshd_config

    Asegurarse que estas líneas existen y no están comentadas:

    PubkeyAuthentication yes
    AuthorizedKeysFile .ssh/authorized_keys

    Paso 4 — Configurar SSH: deshabilitar password y root login

    sudo nano /etc/ssh/sshd_config

    Buscar y modificar (o agregar) estas líneas:

    PermitRootLogin no
    PasswordAuthentication no
    ChallengeResponseAuthentication no
    UsePAM no

    Reiniciar SSH:

    sudo systemctl restart sshd
    **Antes de cerrar tu sesión actual**, abre una segunda terminal y verifica que puedes conectarte con la clave. Si algo falla y cierras la sesión, quedas afuera del servidor.

    ¿Por qué? Deshabilitar el login de `root` por SSH es uno de los primeros pasos en cualquier checklist de hardening. Deshabilitar passwords elimina el vector de ataque más común: fuerza bruta y credential stuffing. A partir de aquí solo se puede entrar con la clave privada correcta.

    Nota: esto deshabilita el login ssh usando contraseña, lo cual si perdemos la private key nos quedaremos sin acceso al servidor, por lo cual asegurar la llave con algún backup o respaldo. Si te sientes inseguro, deja habilitado el root login y password login, pero deja una contraseña larga y segura para root.


    Paso 5 — Instalar Fail2Ban

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

    Configuración básica (crear archivo override):

    sudo cp /etc/fail2ban/jail.conf /etc/fail2ban/jail.local
    sudo nano /etc/fail2ban/jail.local

    Verificar que la sección `[sshd]` esté habilitada:

    [sshd]
    enabled = true
    maxretry = 5
    bantime = 3600
    findtime = 600

    Reiniciar:

    sudo systemctl restart fail2ban

    Ver IPs baneadas:

    sudo fail2ban-client status sshd

    ¿Por qué? Aunque hayamos deshabilitado el login por password, el puerto SSH sigue expuesto a scanners automatizados que intentan miles de conexiones. Fail2Ban monitorea los logs del sistema y banea automáticamente IPs que superen el número de intentos fallidos. Reduce el ruido en los logs y protege contra ataques de enumeración.


    Paso 6 — Configurar el Firewall con UFW

    sudo apt install ufw -y
    **Importante:** Permitir SSH **antes** de activar el firewall o te bloqueará.
    sudo ufw allow 22/tcp   # SSH
    sudo ufw allow 80/tcp   # HTTP
    sudo ufw allow 443/tcp  # HTTPS

    Activar:

    sudo ufw enable

    Ver estado:

    sudo ufw status verbose

    ¿Por qué? Un servidor recién creado tiene todos los puertos expuestos a internet. UFW (Uncomplicated Firewall) es el frontend estándar de `iptables` en Ubuntu. La regla es simple: solo está abierto lo que explícitamente se permite. Esto reduce drásticamente la superficie de ataque.


    Pasos opcionales

    Docker

    Seguir la guía oficial, es la más actualizada y varía según versión de Ubuntu:

    https://docs.docker.com/engine/install/ubuntu/

    Después de instalar, agregar tu usuario al grupo docker para no tener que usar sudo cada vez:

    sudo usermod -aG docker santikz
    newgrp docker

    Herramientas de monitoreo y utilidades

    sudo apt install -y htop btop tmux curl git wget unzip
    HerramientaPara qué sirve
    `htop`Monitor de procesos interactivo
    `btop`Monitor de recursos moderno (CPU, RAM, red)
    `tmux`Terminal multiplexer, mantiene sesiones SSH activas
    `curl`Hacer requests HTTP desde la terminal
    `git`Control de versiones
    `wget`Descargar archivos desde la terminal
    SecurityLinuxDevOps
    VPS Configuration and Hardening Guide | Nebula Solutions | Nebula Solutions