Ir al contenido

Hardening de servidores Linux: guía práctica

·4 mins
Rogelio Guerra Riverón
Autor
Rogelio Guerra Riverón
Construyendo mi propia infraestructura web desde cero. Aquí documento cada paso: servidores, redes, contenedores y lo que vaya surgiendo.

Tener un servidor expuesto a Internet sin una configuración de seguridad mínima es dejar la puerta entreabierta. En este artículo recojo los pasos que aplico en mis propios servidores para reducir la superficie de ataque sin complicar la gestión del día a día.

SSH: la primera línea de defensa
#

El servicio SSH es el punto de entrada más atacado en cualquier servidor Linux. Estos son los ajustes más importantes en /etc/ssh/sshd_config:

# Deshabilitar acceso root
PermitRootLogin no

# Solo autenticación por clave pública
PasswordAuthentication no
ChallengeResponseAuthentication no

# Limitar intentos de autenticación
MaxAuthTries 3

# Desactivar forwarding innecesario
X11Forwarding no
AllowTcpForwarding no

Después de cada cambio:

sudo systemctl reload ssh   # Ubuntu/Debian
sudo systemctl reload sshd  # CentOS/RHEL

¿Por qué PermitRootLogin no y no prohibit-password? Aunque prohibit-password ya bloquea el acceso root por contraseña, dejar activo el login root por clave sigue siendo un riesgo: si esa clave se compromete, el atacante tiene acceso total al sistema sin necesidad de escalar privilegios.

Cambiar el puerto SSH (seguridad por oscuridad)
#

Cambiar el puerto por defecto (22) no es seguridad real, pero elimina el ruido de los bots de internet que escanean continuamente ese puerto:

Port 2222   # cualquier número entre 1024 y 65535

En el router o firewall, crea la regla de NAT para redirigir el puerto externo al 22 interno, o configura UFW para aceptar el nuevo puerto.

Firewall con UFW
#

UFW (Uncomplicated Firewall) simplifica la gestión de iptables:

# Política por defecto: denegar todo
sudo ufw default deny incoming
sudo ufw default allow outgoing

# Permitir solo lo necesario
sudo ufw allow 2222/tcp    # SSH en puerto personalizado
sudo ufw allow 80/tcp      # HTTP
sudo ufw allow 443/tcp     # HTTPS

# Activar
sudo ufw enable
sudo ufw status verbose

Actualizaciones de seguridad automáticas
#

Los servidores que no se actualizan acaban siendo vulnerables. unattended-upgrades aplica parches de seguridad sin intervención manual:

sudo apt install unattended-upgrades
sudo dpkg-reconfigure unattended-upgrades

Para verificar que está activo:

systemctl is-active unattended-upgrades

El fichero de configuración está en /etc/apt/apt.conf.d/50unattended-upgrades. Por defecto solo aplica actualizaciones de seguridad, lo cual es el comportamiento correcto para producción.

Gestión de usuarios
#

Principio de mínimo privilegio
#

Cada usuario solo debe tener los permisos que necesita. Revisa periódicamente qué usuarios tienen shell activa:

grep -v nologin /etc/passwd | grep -v false

Para deshabilitar un usuario sin eliminarlo:

sudo usermod -s /usr/sbin/nologin usuario
sudo passwd -l usuario   # Bloquear contraseña

sudo sin contraseña — con cabeza
#

Es tentador poner NOPASSWD en sudoers para evitar escribir la contraseña, pero limítalo a los comandos específicos que lo necesiten:

# Bien: solo para comandos concretos
usuario ALL=(ALL) NOPASSWD: /usr/bin/docker, /usr/bin/systemctl restart nginx

# Mal: acceso total sin contraseña
usuario ALL=(ALL) NOPASSWD: ALL

Protección contra fuerza bruta con fail2ban
#

fail2ban monitoriza los logs del sistema y bloquea automáticamente IPs que realizan demasiados intentos fallidos:

sudo apt install fail2ban

Configuración básica en /etc/fail2ban/jail.local:

[DEFAULT]
bantime  = 1h
findtime = 10m
maxretry = 5

[sshd]
enabled = true
port    = 2222
logpath = %(sshd_log)s
backend = %(sshd_backend)s
sudo systemctl enable fail2ban
sudo systemctl start fail2ban

# Ver IPs baneadas
sudo fail2ban-client status sshd

Auditoría: qué revisar periódicamente
#

Una vez configurado el servidor, conviene revisar estos puntos con cierta frecuencia:

# Intentos de acceso fallidos
sudo lastb | head -20

# Puertos escuchando (detectar servicios inesperados)
ss -tlnp

# Binarios con SUID (posibles vectores de escalada de privilegios)
find / -perm -4000 -type f 2>/dev/null

# Actualizaciones pendientes
apt list --upgradable 2>/dev/null | grep -i security

Cifrado entre servidores con WireGuard
#

Si tienes varios servidores que necesitan comunicarse (rsync, bases de datos, APIs internas), evita exponer esos servicios a Internet. WireGuard ofrece un túnel VPN rápido y sencillo con cifrado ChaCha20-Poly1305:

sudo apt install wireguard
wg genkey | tee privatekey | wg pubkey > publickey

El tráfico entre servidores viaja cifrado por el túnel (10.10.0.x) en lugar de usar las IPs públicas. Así, servicios como rsync o PostgreSQL nunca quedan expuestos aunque alguien intercepte el tráfico de red.

Tengo un artículo específico sobre réplica de emergencia con rsync y WireGuard con la configuración completa.

Resumen: checklist de hardening
#

AcciónPrioridad
PermitRootLogin no en sshd_configAlta
PasswordAuthentication noAlta
Firewall UFW activo y reglas mínimasAlta
unattended-upgrades activoAlta
Cambiar puerto SSHMedia
AllowTcpForwarding noMedia
MaxAuthTries 3Media
fail2ban instalado y configuradoMedia
Revisar usuarios con shell activaMedia
Auditoría periódica de puertos y SUIDBaja

La seguridad perfecta no existe, pero aplicar estos pasos reduce drásticamente la probabilidad de ser el objetivo fácil que los bots automatizados buscan.