0%
Seguridad en Linux: endurecer un servidor en producción

Seguridad en Linux: endurecer un servidor en producción

Guía de endurecimiento de un servidor Linux: SSH con claves, cortafuegos ufw y firewalld, fail2ban, actualizaciones automáticas, auditd y mínimo privilegio.

I

InSkillCoach

· min

Seguridad en Linux: endurecer un servidor en producción

Un servidor Linux expuesto a Internet recibe sus primeros intentos de intrusión a los pocos minutos de ponerse en línea: escaneos de puertos, pruebas de contraseñas SSH, explotación de servicios mal configurados. La buena noticia es que un puñado de medidas sencillas elimina la inmensa mayoría de estos ataques oportunistas. En esta guía endurecemos un servidor paso a paso: SSH, cortafuegos, fail2ban, actualizaciones automáticas, permisos, auditoría y vigilancia de puertos. Cada sección incluye los comandos exactos, probados en Debian/Ubuntu y Rocky Linux/Fedora. Una lista de comprobación final cierra el artículo.

1. Endurecimiento de SSH

SSH es la puerta de entrada principal de su servidor y, por tanto, el objetivo número uno. Se imponen tres medidas: la autenticación por claves, la desactivación del acceso como root y la desactivación de las contraseñas.

Autenticación por claves

# En su máquina local: generar un par de claves ed25519
ssh-keygen -t ed25519 -C "admin@poste-travail"

# Copiar la clave pública al servidor
ssh-copy-id -i ~/.ssh/id_ed25519.pub admin@serveur.exemple.com

# Verificar la conexión por clave ANTES de desactivar las contraseñas
ssh -i ~/.ssh/id_ed25519 admin@serveur.exemple.com

Configuración del demonio SSH

Edite /etc/ssh/sshd_config (o, mejor aún, cree un archivo en /etc/ssh/sshd_config.d/):

# /etc/ssh/sshd_config.d/10-durcissement.conf

# Prohibir la conexión directa como root
PermitRootLogin no

# Desactivar la autenticación por contraseña: solo claves
PasswordAuthentication no
KbdInteractiveAuthentication no

# Limitar los usuarios autorizados a conectarse
AllowUsers admin deploy

# Reducir la ventana de autenticación y los intentos
LoginGraceTime 30
MaxAuthTries 3

# Desconectar las sesiones inactivas tras 15 minutos
ClientAliveInterval 300
ClientAliveCountMax 3
# Validar la sintaxis antes de recargar: un error puede dejarle fuera
sudo sshd -t

# Recargar la configuración
sudo systemctl reload ssh     # Debian/Ubuntu
sudo systemctl reload sshd    # Rocky/Fedora

Mantenga siempre una sesión SSH abierta mientras prueba la nueva configuración en un segundo terminal. Si la nueva sesión falla, podrá corregirlo desde la primera.

Cambiar el puerto: útil, pero no suficiente

Mover SSH del puerto 22 a un puerto no estándar no protege frente a un atacante que le haya elegido como objetivo, pero reduce drásticamente el ruido de los escaneos automáticos en sus logs.

# En /etc/ssh/sshd_config.d/10-durcissement.conf
Port 2222

No olvide abrir este puerto en el cortafuegos antes de recargar SSH, y especificarlo después al conectarse: ssh -p 2222 admin@serveur.

2. Cortafuegos: ufw y firewalld

El principio: bloquear todo el tráfico entrante por defecto y abrir únicamente los puertos necesarios.

ufw (Debian/Ubuntu)

# Instalar y definir las políticas por defecto
sudo apt install ufw
sudo ufw default deny incoming
sudo ufw default allow outgoing

# IMPRESCINDIBLE: permitir SSH antes de activar el cortafuegos
sudo ufw allow 2222/tcp comment 'SSH'

# Abrir los puertos web
sudo ufw allow 80/tcp comment 'HTTP'
sudo ufw allow 443/tcp comment 'HTTPS'

# Restringir un puerto a una dirección IP de origen (p. ej. base de datos)
sudo ufw allow from 10.0.0.5 to any port 5432 proto tcp

# Activar el cortafuegos
sudo ufw enable

# Verificar las reglas con sus números
sudo ufw status numbered

# Eliminar una regla por su número
sudo ufw delete 3

firewalld (Rocky Linux/Fedora)

# Comprobar que firewalld está activo
sudo systemctl enable --now firewalld

# Listar la configuración de la zona activa
sudo firewall-cmd --list-all

# Abrir servicios de forma permanente
sudo firewall-cmd --permanent --add-service=http
sudo firewall-cmd --permanent --add-service=https

# Abrir un puerto personalizado
sudo firewall-cmd --permanent --add-port=2222/tcp

# Retirar un servicio abierto por defecto si no es necesario
sudo firewall-cmd --permanent --remove-service=cockpit

# Aplicar los cambios permanentes
sudo firewall-cmd --reload

3. fail2ban: bloquear a los atacantes

fail2ban lee los registros, detecta los intentos de autenticación repetidos y bloquea la dirección IP infractora a través del cortafuegos.

# Instalación
sudo apt install fail2ban          # Debian/Ubuntu
sudo dnf install fail2ban          # Rocky/Fedora

No modifique nunca jail.conf: cree jail.local, que lo sobrescribe.

# /etc/fail2ban/jail.local
[DEFAULT]
# Bloquear durante 1 hora tras 5 fallos en 10 minutos
bantime  = 1h
findtime = 10m
maxretry = 5
# No bloquear nunca sus propias direcciones
ignoreip = 127.0.0.1/8 ::1 203.0.113.10

[sshd]
enabled = true
port    = 2222
# Activar y verificar
sudo systemctl enable --now fail2ban
sudo fail2ban-client status sshd

# Desbloquear una dirección por error
sudo fail2ban-client set sshd unbanip 198.51.100.7

# Endurecimiento progresivo: duplicar la duración en cada reincidencia
# (añadir en [DEFAULT] de jail.local)
# bantime.increment = true
# bantime.maxtime   = 1w

4. Actualizaciones automáticas

La mayoría de los compromisos explotan vulnerabilidades que ya estaban corregidas. Automatice, como mínimo, las actualizaciones de seguridad.

Debian/Ubuntu: unattended-upgrades

# Instalación y activación
sudo apt install unattended-upgrades
sudo dpkg-reconfigure -plow unattended-upgrades

# Verificar la configuración
cat /etc/apt/apt.conf.d/20auto-upgrades
# APT::Periodic::Update-Package-Lists "1";
# APT::Periodic::Unattended-Upgrade "1";

# Probar en simulación
sudo unattended-upgrade --dry-run --debug

En /etc/apt/apt.conf.d/50unattended-upgrades puede activar el reinicio automático en horas de baja actividad:

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

Rocky/Fedora: dnf-automatic

sudo dnf install dnf-automatic

# En /etc/dnf/automatic.conf: aplicar únicamente las de seguridad
# upgrade_type = security
# apply_updates = yes

sudo systemctl enable --now dnf-automatic.timer

5. Permisos y umask

Verificar los archivos sensibles

# Los archivos de contraseñas deben estar estrictamente protegidos
ls -l /etc/shadow
# Esperado: -rw-r----- root shadow (640) o más restrictivo

# Encontrar los archivos con permiso de escritura para todos (peligrosos)
sudo find / -xdev -type f -perm -0002 -not -path "/proc/*" 2>/dev/null

# Encontrar los binarios setuid (auditar con regularidad)
sudo find / -xdev -type f -perm -4000 2>/dev/null

# Las claves SSH privadas deben tener permisos 600
chmod 600 ~/.ssh/id_ed25519
chmod 700 ~/.ssh

umask: los permisos por defecto

El umask determina los permisos que se retiran a los archivos nuevos. Con un umask de 022, un archivo se crea con 644; con 027, con 640 (ningún acceso para «el resto»).

# Verificar el umask actual
umask

# Endurecer para los archivos nuevos: añadir en /etc/profile.d/umask.sh
echo "umask 027" | sudo tee /etc/profile.d/umask.sh
umaskArchivo creadoDirectorio creadoUso
022644 (rw-r—r—)755 (rwxr-xr-x)Valor por defecto clásico
027640 (rw-r-----)750 (rwxr-x---)Servidor endurecido recomendado
077600 (rw-------)700 (rwx------)Datos estrictamente privados

6. auditd: registrar las acciones sensibles

auditd registra los eventos del sistema a nivel del kernel: accesos a archivos críticos, llamadas al sistema, ejecuciones de comandos.

# Instalación
sudo apt install auditd audispd-plugins   # Debian/Ubuntu
sudo dnf install audit                     # Rocky/Fedora
sudo systemctl enable --now auditd

Reglas útiles en /etc/audit/rules.d/durcissement.rules:

# Vigilar cualquier modificación de las cuentas y de sudo
-w /etc/passwd -p wa -k comptes
-w /etc/shadow -p wa -k comptes
-w /etc/sudoers -p wa -k sudoers
-w /etc/sudoers.d/ -p wa -k sudoers

# Vigilar la configuración de SSH
-w /etc/ssh/sshd_config -p wa -k sshd

# Registrar los comandos ejecutados como root (arquitectura de 64 bits)
-a always,exit -F arch=b64 -F euid=0 -S execve -k commandes_root
# Cargar las reglas y verificar
sudo augenrules --load
sudo auditctl -l

# Buscar eventos por clave
sudo ausearch -k sudoers --start today

# Informe resumido de las autenticaciones
sudo aureport -au --summary

7. Vigilancia de puertos: ss y nmap

Vista interna con ss

# Todos los puertos TCP y UDP en escucha, con el proceso asociado
sudo ss -tulpn

# Solo los puertos TCP en escucha
sudo ss -tlnp

# Conexiones establecidas hacia el exterior
ss -tn state established

Cada línea de ss -tulpn debe corresponder a un servicio que usted conozca y que haya instalado voluntariamente. Un puerto en escucha desconocido merece una investigación inmediata.

Vista externa con nmap

Escanee su servidor desde otra máquina para ver lo que un atacante ve realmente:

# Escaneo de los 1000 puertos TCP más comunes
nmap serveur.exemple.com

# Escaneo completo de todos los puertos TCP con detección de versión
nmap -p- -sV serveur.exemple.com

# Escaneo UDP de los puertos comunes (lento, requiere root)
sudo nmap -sU --top-ports 50 serveur.exemple.com

Escanee únicamente máquinas que le pertenezcan o para las que disponga de una autorización por escrito.

Desactivar los servicios innecesarios

# Listar los servicios activos
systemctl list-units --type=service --state=running

# Desactivar y detener un servicio superfluo
sudo systemctl disable --now cups

8. El principio de mínimo privilegio

Cada proceso, usuario y servicio debe disponer únicamente de los derechos estrictamente necesarios para su función.

# Crear un usuario de sistema sin shell para un servicio de aplicación
sudo useradd --system --no-create-home --shell /usr/sbin/nologin monapp

# Limitar sudo a un comando concreto en lugar de ALL
# En /etc/sudoers.d/deploy (mediante visudo -f):
# deploy ALL=(root) NOPASSWD: /usr/bin/systemctl restart monapp

A nivel de systemd, aísle sus servicios en un sandbox mediante su archivo de unidad:

# Extracto de /etc/systemd/system/monapp.service
[Service]
User=monapp
# Prohibir la adquisición de nuevos privilegios
NoNewPrivileges=true
# Sistema de archivos en solo lectura salvo excepciones
ProtectSystem=strict
ReadWritePaths=/var/lib/monapp
# /home inaccesible
ProtectHome=true
# /tmp privado
PrivateTmp=true
# Medir la exposición de un servicio (puntuación de 0 a 10, cuanto más baja, mejor)
systemd-analyze security monapp.service

Por último, mantenga activados SELinux (Rocky/Fedora) o AppArmor (Debian/Ubuntu): confinan los servicios comprometidos.

# Verificar el estado de SELinux
getenforce
# Esperado: Enforcing

# Verificar el estado de AppArmor
sudo aa-status

9. Lista de comprobación de endurecimiento

MedidaComando de verificaciónEstado esperado
SSH solo por clavessudo sshd -T | grep passwordauthenticationpasswordauthentication no
Acceso root prohibidosudo sshd -T | grep permitrootloginpermitrootlogin no
Cortafuegos activosudo ufw status o sudo firewall-cmd --stateactive / running
Entradas bloqueadas por defectosudo ufw status verbosedeny (incoming)
fail2ban en serviciosudo fail2ban-client status sshdjail sshd activa
Actualizaciones de seguridad automáticassystemctl status unattended-upgrades o dnf-automatic.timeractivo
Ningún puerto inesperadosudo ss -tulpnsolo los servicios conocidos
Ningún archivo con escritura para todosfind / -xdev -type f -perm -0002lista vacía
umask endurecidoumask0027
auditd en funcionamientosudo auditctl -lreglas cargadas
SELinux/AppArmor activogetenforce / aa-statusEnforcing / perfiles cargados
Servicios superfluos desactivadossystemctl list-units --type=service --state=runninglista mínima

Buenas prácticas

  • Pruebe cada cambio de SSH en una segunda sesión antes de cerrar la primera: es su red de seguridad contra el autobloqueo.
  • Abra el puerto SSH en el cortafuegos antes de activarlo, nunca después.
  • Añada sus direcciones IP de administración a ignoreip de fail2ban para no bloquearse nunca a sí mismo.
  • No desactive nunca SELinux ni AppArmor para «resolver» un problema: corrija la política en su lugar.
  • Audite los puertos en escucha (ss -tulpn) después de cada instalación de software.
  • Vuelva a pasar la lista de comprobación completa tras cada actualización mayor del sistema.
  • Externalice sus registros a un servidor remoto: un atacante que obtiene root borra las huellas locales.
  • La seguridad es un proceso, no un estado: programe una revisión trimestral de esta lista de comprobación.

Conclusión

Endurecer un servidor Linux no requiere herramientas exóticas ni presupuesto: SSH restringido a claves, un cortafuegos con lista blanca, fail2ban, actualizaciones automáticas, permisos estrictos, auditd y una revisión periódica de los puertos bastan para descartar la práctica totalidad de los ataques oportunistas que barren Internet de forma permanente. El hilo conductor de todas estas medidas es el principio de mínimo privilegio: cada acceso que no es indispensable es un acceso que hay que eliminar.

Aplique la lista de comprobación de la sección 9 en cada uno de sus servidores, automatícela en sus scripts de aprovisionamiento y partirá de una base sólida que las medidas avanzadas (SELinux afinado, registro centralizado, detección de intrusiones) reforzarán después.

InSkillCoach

Acerca de InSkillCoach

Experto en formación y tecnologías

Coach especializado en tecnologías avanzadas e IA, impulsado por GNeurone Inc.

Certificaciones:

  • AWS Certified Solutions Architect – Professional
  • Certificaciones de Google Cloud
  • Microsoft Certified: DevOps Engineer Expert
  • Certified Kubernetes Administrator (CKA)
  • CompTIA Security+
906
267

Comentarios

Los comentarios funcionan con GitHub Discussions

Inicia sesión con GitHub para participar en la discusión

¡Enlace copiado!