Parte 2 del endurecimiento de seguridad de Linux, aquí hablaré sobre asegurar SSH, componentes orientados a la red, configuración del firewall y algunas buenas opciones de mantenimiento del sistema.

linux-hardening.webp



Endurecimiento del Servidor SSH

Proteger SSH es clave para prevenir el acceso a un sistema. Las configuraciones predeterminadas de SSH están diseñadas para la conveniencia, no para la seguridad. Si no está protegido y expuesto, muchos scripts/bots intentarán iniciar sesión en tu sistema.

Deshabilita completamente la autenticación basada en contraseñas, restringe el acceso a usuarios específicos y agrega algo de limitación de tasa básica para reducir el ruido en los registros de ataques de fuerza bruta automatizados.


Deshabilitar la Autenticación por Contraseña

La autenticación por contraseña a través de SSH es insegura. Las contraseñas pueden ser atacadas por fuerza bruta, phishing o filtradas en violaciones de datos. La autenticación por clave SSH, por otro lado, se basa en pares de claves que es mucho más seguro.

La clave privada permanece en tu máquina local y nunca sale. La clave pública se copia al servidor. Cuando te conectas, el servidor desafía a tu cliente a demostrar que tiene la clave privada correspondiente sin transmitir nunca la clave en sí. No se envía ninguna contraseña a través de la red, y no hay nada que un atacante pueda atacar por fuerza bruta.


Genera un par de claves SSH en tu máquina local (no en el servidor).

# Ed25519 es el estándar moderno (claves más cortas, mejor rendimiento)
ssh-keygen -t ed25519 -C "[email protected]"

# Si necesitas compatibilidad con sistemas más antiguos, usa RSA con claves de 4096 bits
ssh-keygen -t rsa -b 4096 -C "[email protected]"

# Las claves se guardan en ~/.ssh/id_ed25519 (privada) y ~/.ssh/id_ed25519.pub (pública)

Copia tu clave pública al servidor.

# La forma fácil (agrega automáticamente a ~/.ssh/authorized_keys)
ssh-copy-id [email protected]

Prueba la autenticación basada en claves en una “nueva ventana de terminal” antes de hacer cambios.

# Esto debería iniciarte sesión sin pedir una contraseña
ssh [email protected]

# Si todavía pide una contraseña, verifica los registros del servidor para depurar
ssh -v [email protected]

Una vez que funcione, deshabilita la autenticación por contraseña.

# Edita la configuración del demonio SSH
sudo vim /etc/ssh/sshd_config

# Establece estas directivas para deshabilitar la autenticación por contraseña y respuestas
PasswordAuthentication no
ChallengeResponseAuthentication no

# Aplica los cambios
sudo systemctl restart sshd

Deshabilitar el Inicio de Sesión Root por SSH

Incluso con autenticación por clave SSH, permitir el inicio de sesión directo como root a través de SSH es innecesario. Si necesitas acceso root, inicia sesión como tu usuario regular y usa sudo. Esto crea un registro de auditoría que muestra quién ejecutó qué comando como root, lo cual el inicio de sesión root sin contraseña omite completamente.

Cubrí la deshabilitación completa de la cuenta root en la Parte 1, pero incluso si mantienes root habilitado para el acceso a la consola local, deberías bloquearlo a través de SSH.

# En /etc/ssh/sshd_config
PermitRootLogin no

# Reinicia sshd para implementar los cambios
sudo systemctl restart sshd

Algunas personas usan PermitRootLogin prohibit-password que permite el inicio de sesión root con claves pero no con contraseñas. Yo no hago esto ya que no encuentro ninguna razón real para iniciar sesión SSH como root.


Restringir el Acceso SSH a Usuarios Específicos

Por defecto, cualquier cuenta de usuario en el sistema puede intentar conectarse por SSH. Eso está bien para sistemas de un solo usuario, pero en servidores multiusuario probablemente solo quieras que algunas cuentas tengan acceso remoto.

Las directivas AllowUsers y AllowGroups te permiten crear una lista blanca de exactamente quién puede conectarse vía SSH.

# En /etc/ssh/sshd_config

# Método 1: Lista blanca de usuarios específicos
AllowUsers cloud admin

# Método 2: Lista blanca de un grupo
AllowGroups sshusers

# Puedes combinar ambas directivas si es necesario

Si usas grupos, crea el grupo de usuarios SSH y agrega tus usuarios autorizados.

# Crea el grupo de usuarios SSH
sudo groupadd sshusers

# Agrega tu usuario al grupo
sudo usermod -aG sshusers cloud

# Verifica la membresía del grupo
groups cloud

También existen las directivas DenyUsers y DenyGroups para listas negras, pero prefiero las listas blancas con directivas Allow. Las listas de permitidos explícitas son más claras y más difíciles de configurar incorrectamente, mucho más fácil ver quién tiene acceso.


Limitación de Tasa con fail2ban

Fail2ban monitorea archivos de registro en busca de intentos de autenticación fallidos y crea automáticamente reglas temporales de firewall para bloquear a los reincidentes. Esto reduce la carga del servidor por intentos de conexión y disminuye el ruido en los registros de ataques de fuerza bruta SSH automatizados que escanean internet.

No es estrictamente necesario si ya deshabilitaste la autenticación por contraseña (ya que no hay nada que atacar por fuerza bruta), pero es posible que aún quieras ejecutarlo porque mantiene los registros más limpios y reduce los ciclos de CPU desperdiciados por bots que intentan muchas conexiones fallidas por día.


Instala fail2ban.

# Fedora/RHEL
sudo dnf install fail2ban fail2ban-firewalld

# Habilita e inicia el servicio
sudo systemctl enable --now fail2ban

Crea un archivo de configuración local /etc/fail2ban/jail.local.

# Crea archivo de anulación local
sudo vim /etc/fail2ban/jail.local

# Agrega configuración de jaula SSH
[DEFAULT]
# Duración del baneo en segundos (10 minutos)
bantime = 600

# Ventana de tiempo para contar fallos (10 minutos)
findtime = 600

# Número de fallos antes del baneo
maxretry = 5

# Ignorar localhost y tus IPs de confianza
ignoreip = 127.0.0.1/8 ::1 192.168.1.0/24

[sshd]
enabled = true
port = ssh
logpath = /var/log/secure
backend = systemd

Si cambiaste tu puerto SSH del predeterminado 22, actualiza el puerto.

[sshd]
enabled = true
port = 2222  # Tu puerto SSH personalizado
logpath = /var/log/secure
backend = systemd

Reinicia fail2ban para aplicar la configuración.

# Reinicia el servicio
sudo systemctl restart fail2ban

Fail2ban funciona analizando registros de autenticación y creando reglas enriquecidas de firewalld (o reglas de iptables, dependiendo de tu configuración de backend). Puedes ver los baneos activos en tu firewall.

# Ver reglas enriquecidas de firewalld creadas por fail2ban
sudo firewall-cmd --list-rich-rules

¿Cambiar el Puerto SSH Predeterminado?

No cambio el puerto SSH predeterminado del 22 por pereza… Cambiar el puerto sí reduce el ruido en los registros de escaneos automatizados, pero alguien que realmente quiera acceso o algunos bots avanzados descubrirán cuando SSH está en otro puerto.

Si estás detrás de un firewall o usando algo como Tailscale o Headscale (que es mi caso), el puerto SSH ni siquiera está expuesto a internet público de todos modos. Pero si estás ejecutando un servidor directamente expuesto a internet y quieres reducir el ruido constante de escaneo en tus registros, así es como cambiarlo.

# En /etc/ssh/sshd_config
Port 2222  # Elige un número de puerto alto (1024-65535)

# Actualiza las reglas del firewall (elimina el servicio ssh de firewalld en el puerto 22 y agrega el puerto personalizado)
sudo firewall-cmd --permanent --add-port=2222/tcp
sudo firewall-cmd --permanent --remove-service=ssh
sudo firewall-cmd --reload

# Reinicia SSH
sudo systemctl restart sshd

La principal desventaja es que tienes que recordar especificar el puerto cada vez que te conectas, lo cual es molesto, pero también puedes especificarlo como una configuración predeterminada en tu archivo local ~/.ssh/config.

Host myserver
    HostName your-server.com
    Port 2222
    User cloud

Entonces simplemente puedes ejecutar ssh myserver y automáticamente usa el puerto y nombre de usuario configurados.



Configuración del Firewall

Linux usa firewalld (en RHEL/Fedora) o ufw (en Debian/Ubuntu) como interfaz para netfilter, el marco de filtrado de paquetes del kernel. Estoy usando firewalld, que agrupa las reglas del firewall en zonas y servicios para una gestión más fácil en comparación con iptables.

La configuración predeterminada del firewall suele ser bastante buena, pero hay algunos pequeños cambios que me gusta hacer.


¿Qué son las Zonas de Firewalld?

Firewalld usa “zonas” para agrupar interfaces de red y definir niveles de confianza. Cada zona tiene una política predeterminada para el tráfico entrante. Las zonas más comúnmente usadas son:

  • drop: Descarta todos los paquetes entrantes sin respuesta (más restrictiva)
  • block: Rechaza todos los paquetes entrantes con mensajes icmp-host-prohibited
  • public: Zona predeterminada para redes no confiables, permite solo servicios específicos
  • trusted: Permite todo el tráfico (usar con cuidado, típicamente para interfaces VPN)

Verifica tu configuración actual del firewall.

# Mostrar zonas activas y sus interfaces
sudo firewall-cmd --get-active-zones

# Verificar zona predeterminada
sudo firewall-cmd --get-default-zone

# Listar todas las reglas en la zona actual
sudo firewall-cmd --list-all

# Ver todas las zonas y sus configuraciones
sudo firewall-cmd --list-all-zones

Restringe tus puertos y servicios permitidos para aceptar solo el tráfico que estás esperando. Bloquea todo lo demás.


Gestión de Servicios del Firewall

Firewalld viene con definiciones de servicios predefinidas para aplicaciones comunes como HTTP, HTTPS, SSH y DNS. Estos son más fáciles de trabajar que recordar números de puerto.

# Listar servicios predefinidos disponibles
sudo firewall-cmd --get-services

# Permitir un servicio permanentemente
sudo firewall-cmd --permanent --add-service=http
sudo firewall-cmd --permanent --add-service=https

# Eliminar un servicio
sudo firewall-cmd --permanent --remove-service=dhcpv6-client

# Agregar un puerto personalizado si no existe un servicio predefinido
sudo firewall-cmd --permanent --add-port=8080/tcp

# Eliminar un puerto
sudo firewall-cmd --permanent --remove-port=8080/tcp

# Recargar el firewall para aplicar todos los cambios
sudo firewall-cmd --reload

La opción --permanent escribe los cambios en el disco para que persistan a través de reinicios. Sin ella, las reglas solo se aplican hasta que se recarga el firewall o se reinicia el sistema.


Filtrado ICMP

ICMP se usa para diagnósticos de red como ping y descubrimiento de MTU de ruta. El consejo de seguridad común es “deshabilitar ping” bloqueando paquetes ICMP echo-request. Esto evita que alguien enumere fácilmente hosts activos en tu red a través de barridos de ping.

Ten cuidado ya que bloquear ICMP puede romper funciones legítimas de red, pero permitir todos los tipos de ICMP habilita el reconocimiento de red. Así que es un compromiso como todo en la vida.


Si quieres bloquear solicitudes de ping.

# Bloquear ICMP echo-request (pings entrantes)
sudo firewall-cmd --permanent --add-icmp-block=echo-request

# Bloquear echo-reply también (respuestas a pings salientes)
sudo firewall-cmd --permanent --add-icmp-block=echo-reply

# Aplicar cambios
sudo firewall-cmd --reload

# Probar desde otra máquina
ping your-server.com  # Debería expirar

Personalmente, no bloqueo ICMP ya que solucionar problemas de red sin ping es un dolor y los escáneres de puertos no dependen solo de ping.


Habilitar el Registro del Firewall

Por defecto, firewalld no registra los paquetes descartados. Habilitar el registro te permite ver qué está siendo bloqueado, lo cual es útil para solucionar configuraciones incorrectas y detectar actividad de escaneo de bots:

# Registrar todos los paquetes descartados
sudo firewall-cmd --set-log-denied=all
sudo firewall-cmd --permanent --set-log-denied=all

# Opciones: off, all, unicast, broadcast, multicast
# 'unicast' es menos ruidoso que 'all' pero aún útil

# Ver paquetes descartados en registros del sistema
sudo journalctl -f -u firewalld
sudo tail -f /var/log/messages | grep -i REJECT


Actualizaciones de Seguridad Automatizadas

Aplica actualizaciones de seguridad tan pronto como estén disponibles ya sea con un temporizador systemd o dnf-automatic.

A algunos puede que no les guste pero soy perezoso.


DNF Automatic

DNF Automatic es la herramienta oficial en Fedora y sistemas basados en RHEL para automatizar la descarga e instalación de paquetes.

Yo la uso para instalar automáticamente actualizaciones de seguridad mientras dejo las actualizaciones regulares de características para revisión manual.


Instala DNF Automatic.

# Instalar paquete
sudo dnf install dnf-automatic

Configura el comportamiento de actualización en /etc/dnf/automatic.conf.

# Editar configuración
sudo vim /etc/dnf/automatic.conf

# Configuraciones clave a modificar:
[commands]
# Qué hacer con las actualizaciones
# apply = descargar e instalar
# download = solo descargar
# check = solo verificar actualizaciones
upgrade_type = security
apply_updates = yes

[emitters]
# Cómo recibir notificaciones
emit_via = stdio

[email]
# Configuración de correo si quieres notificaciones por email (requiere postfix o similar)
email_from = root@localhost
email_to = [email protected]
email_host = localhost

Yo establezco upgrade_type = security y apply_updates = yes. Esto instala automáticamente actualizaciones de seguridad pero deja las actualizaciones regulares de características para revisión manual. Puede que prefieras upgrade_type = default para instalar todo automáticamente, lo cual es muy conveniente.


Habilita e inicia el temporizador systemd.

# Habilitar temporizador (se ejecuta diariamente por defecto)
sudo systemctl enable --now dnf-automatic.timer

# Verificar estado del temporizador
systemctl status dnf-automatic.timer

# Ver calendario del temporizador
systemctl list-timers dnf-automatic.timer

# Activar manualmente una verificación de actualización
sudo systemctl start dnf-automatic.service

Verifica los registros para verificar que está funcionando.

# Ver registros de DNF automatic
sudo journalctl -u dnf-automatic.service

# Salida de última ejecución
sudo journalctl -u dnf-automatic.service -n 50

Actualizaciones Automáticas de Flatpak

Si estás usando Flatpaks y quieres actualizaciones automatizadas puedes usar la aplicación del centro de software de Gnome para activar las auto-actualizaciones o simplemente crear un temporizador systemd simple para actualizar a intervalos regulares.

# Crear servicio systemd para actualizaciones de Flatpak
sudo vim /etc/systemd/system/flatpak-update.service

[Unit]
Description=Update Flatpak packages
After=network-online.target
Wants=network-online.target

[Service]
Type=oneshot
ExecStart=/usr/bin/flatpak update -y

Crea un temporizador para ejecutarlo.

# Crear temporizador systemd
sudo vim /etc/systemd/system/flatpak-update.timer

[Unit]
Description=Daily Flatpak update

[Timer]
OnCalendar=daily
Persistent=true

[Install]
WantedBy=timers.target

Habilita el temporizador.

# Habilitar temporizador
sudo systemctl enable --now flatpak-update.timer


Eliminar Servicios No Utilizados

Cada servicio en ejecución es una superficie de ataque potencial. Si no estás usando activamente un servicio, deshabilítalo.

Verifica qué servicios están actualmente en ejecución y habilitados:

# Listar todos los servicios habilitados (se iniciarán al arrancar)
systemctl list-unit-files --state=enabled

# Listar servicios actualmente en ejecución
systemctl list-units --type=service --state=running

Antes de deshabilitar un servicio, verifica qué depende de él para asegurarte de que no estás rompiendo algo crítico:

# Ver qué se vería afectado por deshabilitar un servicio
systemctl list-dependencies --reverse servicename.service

# Verificar si algo lo está usando activamente
systemctl status servicename.service

Busca en Google (o pregunta a una IA) sobre servicios desconocidos antes de deshabilitarlos. Algunos servicios tienen nombres muy raros pero en realidad son legítimos. Una búsqueda rápida en la web de “what is [servicename] Fedora” usualmente muestra mucha información para ver si es seguro deshabilitarlo.


Deshabilita los servicios que no necesitas.

# Deshabilitar y detener un servicio
sudo systemctl disable --now ModemManager.service


¿Qué Sigue?

Enlace a la Parte 1: Linux Security Hardening Part.2 - SSH, Firewall, and Services.

La siguiente parte debería ser SELinux, endurecimiento del kernel, seguridad de systemd…