Un servidor recién creado con IP pública empieza a recibir intentos de login automatizados en cuestión de minutos. En esta guía aplicarás la configuración básica que todo servidor Ubuntu o Debian debería tener antes de alojar nada: un usuario administrador sin privilegios de root, acceso SSH solo con claves, un firewall que bloquea todo excepto lo necesario, Fail2Ban contra ataques de fuerza bruta y parches de seguridad automáticos. Los comandos son para Ubuntu 24.04 LTS; las diferencias con Debian 12 se indican donde importan.

Requisitos previos

  • Un servidor recién instalado con Ubuntu 24.04 LTS o Debian 12, por ejemplo un VPS de CubePath.
  • Acceso como root por SSH, con contraseña o clave.
  • Una clave SSH en tu equipo local. Si todavía no tienes una, créala con ssh-keygen -t ed25519 como se explica en la guía para conectarse a un servidor por SSH.
  • Acceso a la consola del panel de CubePath por si te quedas sin SSH durante los cambios.

Paso 1: Actualizar el sistema

Empieza con todos los paquetes al día para no desplegar software con vulnerabilidades ya corregidas. Conéctate como root:

ssh root@your_server_ip

Actualiza la lista de paquetes e instala las actualizaciones:

apt update && apt upgrade -y

Si se actualizó el kernel o alguna librería básica, el sistema crea el archivo /var/run/reboot-required. Compruébalo:

ls /var/run/reboot-required 2>/dev/null && echo "Reinicio necesario"

Si aparece el mensaje, reinicia con reboot y vuelve a conectarte antes de seguir.

Paso 2: Crear un usuario administrador

Trabajar siempre como root significa que cualquier error o comando mal copiado tiene efecto sobre todo el sistema. Crea un usuario normal; sustituye your_user por el nombre que quieras:

adduser your_user

adduser te pedirá una contraseña (la necesitarás para sudo) y unos datos opcionales que puedes dejar en blanco. Añade el usuario al grupo sudo para que pueda ejecutar comandos administrativos:

usermod -aG sudo your_user

Comprueba los grupos del usuario:

groups your_user
your_user : your_user sudo users

Paso 3: Dar acceso SSH con clave al nuevo usuario

Si ya entras como root con una clave, lo más sencillo es copiar el authorized_keys de root al nuevo usuario con los permisos correctos:

rsync --archive --chown=your_user:your_user ~/.ssh /home/your_user

Si entras como root con contraseña, ejecuta en su lugar este comando desde tu equipo local:

ssh-copy-id your_user@your_server_ip

Ahora, sin cerrar la sesión de root, abre una segunda terminal en tu equipo y conéctate con el nuevo usuario:

ssh your_user@your_server_ip

Debes entrar sin contraseña (o solo con la frase de paso de tu clave). Comprueba que sudo funciona:

sudo whoami
root

A partir de aquí, trabaja desde la sesión de your_user.

Paso 4: Endurecer la configuración de SSH

Con el acceso por clave funcionando, desactiva el login de root y la autenticación por contraseña. En lugar de editar /etc/ssh/sshd_config, crea un archivo propio en /etc/ssh/sshd_config.d/, que sobrevive a las actualizaciones del paquete. OpenSSH aplica el primer valor que encuentra para cada opción y lee los archivos de ese directorio por orden alfabético, así que el prefijo 00- garantiza que tus valores ganan a otros archivos como 50-cloud-init.conf, que en muchas imágenes activa PasswordAuthentication yes.

sudo nano /etc/ssh/sshd_config.d/00-hardening.conf
PermitRootLogin no
PasswordAuthentication no
KbdInteractiveAuthentication no
PubkeyAuthentication yes
MaxAuthTries 3

Comprueba que la sintaxis es correcta. Si no hay errores, el comando no muestra nada:

sudo sshd -t

Revisa la configuración efectiva que usará el servicio:

sudo sshd -T | grep -Ei '^(permitrootlogin|passwordauthentication|kbdinteractiveauthentication|pubkeyauthentication|maxauthtries)'
maxauthtries 3
permitrootlogin no
pubkeyauthentication yes
passwordauthentication no
kbdinteractiveauthentication no

Recarga el servicio para aplicar los cambios. Las sesiones abiertas no se cortan:

sudo systemctl reload ssh

Desde otra terminal local, comprueba que tu usuario sigue entrando y que root ya no puede:

ssh your_user@your_server_ip
ssh root@your_server_ip
root@your_server_ip: Permission denied (publickey).

Paso 5: Activar el firewall UFW

UFW (Uncomplicated Firewall) es la forma sencilla de gestionar el firewall del kernel en Ubuntu. La política por defecto recomendada es bloquear todo el tráfico entrante y permitir el saliente. Ubuntu 24.04 lo trae instalado; en Debian 12 instálalo con sudo apt install ufw.

sudo ufw default deny incoming
sudo ufw default allow outgoing

Permite SSH antes de activar el firewall o perderás la conexión:

sudo ufw allow OpenSSH

Si vas a servir webs, abre también HTTP y HTTPS (sudo ufw allow 80/tcp y sudo ufw allow 443/tcp). Activa el firewall y confirma con y:

sudo ufw enable
Command may disrupt existing ssh connections. Proceed with operation (y|n)? y
Firewall is active and enabled on system startup

Comprueba las reglas:

sudo ufw status verbose
Status: active
Logging: on (low)
Default: deny (incoming), allow (outgoing), deny (routed)
New profiles: skip

To                         Action      From
--                         ------      ----
22/tcp (OpenSSH)           ALLOW IN    Anywhere
22/tcp (OpenSSH (v6))      ALLOW IN    Anywhere (v6)

Paso 6: Instalar Fail2Ban

Aunque SSH ya no acepte contraseñas, los bots seguirán intentándolo y llenando los logs. Fail2Ban lee los intentos fallidos y bloquea temporalmente las IPs que insisten. Instálalo junto con el módulo que le permite leer el journal de systemd:

sudo apt install fail2ban python3-systemd

Nunca edites jail.conf, que se sobrescribe al actualizar. Crea jail.local con tu configuración:

sudo nano /etc/fail2ban/jail.local
[DEFAULT]
bantime = 1h
findtime = 10m
maxretry = 5
ignoreip = 127.0.0.1/8 ::1

[sshd]
enabled = true
backend = systemd

Con esto, una IP que falle 5 veces en 10 minutos queda bloqueada una hora. backend = systemd hace que funcione igual en Debian 12, que no instala rsyslog ni crea /var/log/auth.log. Si te conectas siempre desde una IP fija, añádela a ignoreip para no bloquearte a ti mismo.

Activa el servicio y comprueba la jail:

sudo systemctl enable --now fail2ban
sudo fail2ban-client status sshd
Status for the jail: sshd
|- Filter
|  |- Currently failed:	0
|  |- Total failed:	0
|  `- Journal matches:	_SYSTEMD_UNIT=sshd.service + _COMM=sshd
`- Actions
   |- Currently banned:	0
   |- Total banned:	0
   `- Banned IP list:

Tras unas horas verás crecer Total banned. Para desbloquear una IP concreta usa sudo fail2ban-client set sshd unbanip 203.0.113.50.

Paso 7: Activar las actualizaciones de seguridad automáticas

El paquete unattended-upgrades instala cada día las actualizaciones de seguridad sin intervención. Viene instalado en Ubuntu; asegúrate de que está y actívalo:

sudo apt install unattended-upgrades
sudo dpkg-reconfigure --priority=low unattended-upgrades

Responde Yes en la pantalla que aparece. Esto crea /etc/apt/apt.conf.d/20auto-upgrades; comprueba su contenido:

cat /etc/apt/apt.conf.d/20auto-upgrades
APT::Periodic::Update-Package-Lists "1";
APT::Periodic::Unattended-Upgrade "1";

Por defecto solo se instalan actualizaciones del origen de seguridad y el servidor no se reinicia solo. Si quieres reinicios automáticos cuando un parche del kernel lo requiera, edita /etc/apt/apt.conf.d/50unattended-upgrades y descomenta estas líneas ajustando la hora:

Unattended-Upgrade::Automatic-Reboot "true";
Unattended-Upgrade::Automatic-Reboot-Time "04:00";

Haz una prueba en seco para verificar que la configuración es válida:

sudo unattended-upgrade --dry-run --debug 2>&1 | tail -n 5

El registro de cada ejecución real queda en /var/log/unattended-upgrades/.

Paso 8: Ajustar zona horaria y sincronización de hora

Unos logs con la hora correcta son imprescindibles para investigar cualquier incidente, y Fail2Ban depende de ellos. Ubuntu 24.04 y Debian 12 sincronizan la hora con systemd-timesyncd. Ajusta la zona horaria (en servidores, UTC también es una buena elección):

sudo timedatectl set-timezone Europe/Madrid
timedatectl
               Local time: jue 2026-09-24 10:15:32 CEST
           Universal time: jue 2026-09-24 08:15:32 UTC
                Time zone: Europe/Madrid (CEST, +0200)
System clock synchronized: yes
              NTP service: active

Si System clock synchronized indica no, activa la sincronización con sudo timedatectl set-ntp true.

Paso 9: Revisar los servicios expuestos

Todo servicio que escucha en una interfaz pública es superficie de ataque. Lista los puertos abiertos:

sudo ss -tulpn

En un servidor recién configurado solo deberías ver SSH en el puerto 22 y servicios locales (en 127.0.0.1 o 127.0.0.53, como el resolvedor DNS de systemd). Si aparece algo que no necesitas, desactívalo, por ejemplo:

sudo systemctl disable --now nombre_del_servicio

Solución de problemas

Te has quedado sin acceso SSH. Entra por la consola del panel de CubePath con tu usuario, revierte el cambio (por ejemplo, borra /etc/ssh/sshd_config.d/00-hardening.conf o ejecuta sudo ufw allow OpenSSH) y recarga SSH con sudo systemctl reload ssh.

Permission denied (publickey) con el usuario nuevo. Casi siempre son permisos o propietario. Desde root:

chown -R your_user:your_user /home/your_user/.ssh
chmod 700 /home/your_user/.ssh
chmod 600 /home/your_user/.ssh/authorized_keys

Fail2Ban ha bloqueado tu propia IP. Desde la consola o desde otra IP, ejecuta sudo fail2ban-client set sshd unbanip tu_ip y añade tu IP a ignoreip.

fail2ban no arranca. Revisa el error con sudo journalctl -u fail2ban -n 30. Suele ser un error de sintaxis en jail.local; sudo fail2ban-client -t valida la configuración.

Conclusión

Tu servidor ya tiene un usuario administrador con sudo, SSH solo por clave y sin root, un firewall que únicamente deja pasar SSH, Fail2Ban bloqueando a quien insiste y parches de seguridad instalados a diario. Es una base sólida para instalar cualquier aplicación. A partir de aquí puedes cambiar el puerto SSH por defecto, repasar la gestión de usuarios y permisos en Linux o configurar copias de seguridad antes de poner el servidor en producción.