lunes, 11 de agosto de 2025

Creación de un script Bash para detectar y bloquear intrusiones en SSH

 ¡Hola a todos! En el mundo de la ciberseguridad, proteger nuestros servidores es una prioridad. Los intentos de intrusión a través de SSH son comunes, y detectarlos y bloquearlos de forma automatizada puede ahorrarnos muchos dolores de cabeza. En este artículo, vamos a ver cómo crear un script en Bash que analice el log de SSH, identifique intentos de acceso fallidos y, si se repiten, aplique una regla de iptables para bloquear al atacante durante 15 días.


1. El análisis de los logs

Lo primero es saber dónde buscar. El log de SSH se encuentra típicamente en /var/log/auth.log en sistemas basados en Debian (como Ubuntu) o en /var/log/secure en sistemas basados en Red Hat (como CentOS). Usaremos grep para buscar líneas que indiquen intentos de conexión fallidos. La clave es identificar patrones. Por ejemplo, en un log de Ubuntu, un intento fallido se ve así:

Aug 11 20:53:14 servername sshd[12345]: Failed password for invalid user admin from 192.168.1.100 port 54321 ssh2

De esta línea, nos interesa la dirección IP (192.168.1.100). Podemos usar expresiones regulares y herramientas como awk o sed para extraerla.


2. El script paso a paso

Vamos a desglosar la lógica del script. El objetivo es:

  1. Leer las últimas líneas del log.

  2. Extraer las direcciones IP que han intentado iniciar sesión sin éxito.

  3. Contar cuántas veces cada IP ha fallado.

  4. Si una IP supera un umbral (en nuestro caso, 2 veces), la bloqueamos.

Aquí tienes el script completo. Puedes guardarlo como ssh_protector.sh.

Bash
#!/bin/bash

# Definimos la ruta del log y el número de intentos fallidos permitidos
LOGFILE="/var/log/auth.log"  # Cambiar a "/var/log/secure" si usas RHEL/CentOS
MAX_ATTEMPTS=2
# Duración del bloqueo en segundos (15 días = 15 * 24 * 60 * 60)
BLOCK_DURATION=1296000

# Usamos tail para leer las últimas líneas del log y grep para filtrar
# los intentos fallidos. awk se usa para extraer la IP.
# Sort y uniq -c se encargan de contar las repeticiones.
FAILED_IPS=$(tail -n 200 $LOGFILE | grep "Failed password" | awk '{print $11}' | sort | uniq -c | awk '{if ($1 > '$MAX_ATTEMPTS') print $2}')

# Verificamos si la variable FAILED_IPS contiene alguna IP
if [ -n "$FAILED_IPS" ]; then
    # Recorremos cada IP que ha superado el umbral
    for ip in $FAILED_IPS; do
        # Verificamos si la IP ya está bloqueada para evitar duplicados
        if ! iptables -L INPUT -n | grep -q "$ip"; then
            echo "Detectada IP maliciosa: $ip con más de $MAX_ATTEMPTS intentos fallidos. Bloqueando..."
            
            # Bloqueamos la IP con iptables.
            # -A INPUT: Añade la regla a la cadena INPUT.
            # -s $ip: Origen de la IP a bloquear.
            # -j DROP: La acción a tomar es "descartar" todo el tráfico.
            iptables -A INPUT -s $ip -j DROP
            
            echo "IP $ip bloqueada por $BLOCK_DURATION segundos."
            
            # Programamos una tarea para eliminar la regla después de 15 días
            # "at" es una herramienta que ejecuta comandos en un momento determinado.
            echo "iptables -D INPUT -s $ip -j DROP" | at now + $BLOCK_DURATION seconds
        fi
    done
else
    echo "No se encontraron IPs con más de $MAX_ATTEMPTS intentos fallidos."
fi

3. Explicación del código

  • LOGFILE: Es la variable que almacena la ruta a tu archivo de log.

  • MAX_ATTEMPTS: Define el número máximo de intentos fallidos antes de bloquear una IP.

  • BLOCK_DURATION: La duración del bloqueo en segundos.

  • FAILED_IPS: Esta es la línea más importante.

    • tail -n 200 $LOGFILE: Leemos las últimas 200 líneas del log, ya que es más eficiente que leer todo el archivo.

    • grep "Failed password": Filtra solo las líneas que contienen "Failed password" o "Failed password for invalid user".

    • awk '{print $11}': Extrae el undécimo campo, que en este formato de log es la dirección IP.

    • sort | uniq -c: Ordena las IPs y las cuenta, mostrando cuántas veces ha aparecido cada una.

    • awk '{if ($1 > '$MAX_ATTEMPTS') print $2}': Filtra las IPs que tienen un conteo mayor a MAX_ATTEMPTS.

  • iptables: La herramienta que utilizamos para gestionar las reglas del firewall en Linux.

    • iptables -A INPUT -s $ip -j DROP: Añade una regla a la cadena INPUT para descartar todo el tráfico (-j DROP) proveniente de la IP (-s $ip).

  • at: El comando at nos permite programar la ejecución de un comando en el futuro.

    • echo "iptables -D INPUT -s $ip -j DROP" | at now + $BLOCK_DURATION seconds: Esto programa la eliminación de la regla de iptables (-D de delete) después de 15 días.

4. Automatización del script

Para que este script sea realmente útil, debe ejecutarse periódicamente. La mejor manera de hacerlo es usando cron.

  1. Dale permisos de ejecución al script:

    Bash
    chmod +x ssh_protector.sh
    
  2. Edita la tabla de cron de root para que se ejecute con los permisos necesarios:

    Bash
    sudo crontab -e
    
  3. Añade la siguiente línea para que se ejecute cada 5 minutos:

    */5 * * * * /ruta/al/script/ssh_protector.sh
    

    Cambia /ruta/al/script/ por la ruta real donde guardaste tu script.


Consideraciones de seguridad y mejoras

  • Rendimiento: Si tu log es muy grande, leer las últimas 200 líneas puede no ser suficiente. Puedes ajustar el valor en tail -n.

  • Persistencia: Las reglas de iptables se pierden al reiniciar el sistema. Para hacerlas persistentes, puedes usar herramientas como iptables-persistent o scripts de inicio.

  • Notificaciones: Puedes añadir una función para que te envíe un correo electrónico o un mensaje a Slack cada vez que se bloquea una IP.

  • Reversibilidad: Si accidentalmente bloqueas una IP legítima, puedes eliminar la regla manualmente con:

    Bash
    sudo iptables -D INPUT -s la.ip.bloqueada -j DROP
    

Con este script y su automatización, tu servidor estará mucho más protegido contra los ataques de fuerza bruta por SSH. ¡Mantén tus sistemas seguros! 🔒

No hay comentarios:

Publicar un comentario