Cómo filtrar direcciones IP y rangos en logs Web usando solo Bash

Tiempo de lectura: 4 min

Valencia, 2/09/2026, G.B.
Cuando administramos servidores web como Apache, Nginx o LiteSpeed, los archivos de acceso (access.log) se convierten rápidamente en la fuente principal para identificar tráfico no deseado, bots malintencionados o intentos de fuerza bruta.

Aunque existen herramientas de análisis y cortafuegos dinámicos, en muchas ocasiones necesitamos realizar una limpieza rápida de un archivo de log directamente desde la consola, sin instalar dependencias adicionales ni recurrir a lenguajes externos como Python o Perl.

En este artículo veremos cómo construir un script en Bash puro que nos permita eliminar líneas enteras de un log basándonos en direcciones IP individuales o rangos mediante expresiones regulares (regex).

La herramienta clave: grep en modo extendido

Para filtrar contenido en GNU/Linux descartando líneas completas, el comando por excelencia es grep. En lugar de buscar lo que queremos conservar, le indicamos lo que queremos excluir mediante el parámetro -v.

Para manejar rangos o múltiples patrones en una sola pasada, utilizaremos dos modificadores esenciales:

  • -v (--revert-match): Invierte el resultado de la búsqueda, conservando únicamente las líneas que no coinciden con el patrón.
  • -E (--extended-regexp): Activa las expresiones regulares extendidas, permitiéndonos usar operadores lógicos como la barra vertical (|) para el condicional «O» (OR) y corchetes [] para rangos numéricos.

Filtrado de rangos IP mediante Expresiones Regulares

A diferencia de las herramientas orientadas a red que interpretan notación CIDR (como /24), las utilidades del Shell procesan el archivo de log como texto plano. Por ello, traduciremos las subredes a expresiones regulares fijas.
A continuación, algunas equivalencias útiles para definir rangos dentro del patrón de filtrado:
Rango deseadoExpresión RegularExplicación
Subred /24 completa192\.168\.1\.Coincide con cualquier IP que comience por 192.168.1.
Subred /16 completa10\.0\.Coincide con cualquier IP que empiece por 10.0.
Rango .0 a .9172\.16\.0\.[0-9]Filtra del 172.16.0.0 al 172.16.0.9
Rango .10 a .99172\.16\.0\.[1-9][0-9]Filtra del 172.16.0.10 al 172.16.0.99
Rango .100 a .199172\.16\.0\.1[0-9][0-9]Filtra del 172.16.0.100 al 172.16.0.199
Nota: Es fundamental escapar los puntos (\.) con una barra invertida. De lo contrario, en expresiones regulares el punto actuaría como un comodín que representa cualquier carácter.

El Script Bash: filtrar_log.sh

A continuación se muestra la estructura completa del script. Este toma como entrada el archivo de log original y genera un nuevo archivo limpio sin las líneas asociadas a las IP definidas.
#!/bin/bash

# ==============================================================================
# Script de filtrado de IPs y rangos en logs de acceso
# Publicado en Indaga.net
# ==============================================================================

# Validar que se introduzcan los argumentos necesarios
if [ "$#" -ne 2 ]; then
    echo "Error: Argumentos insuficientes."
    echo "Uso: $0 <log_origen> <log_destino>"
    exit 1
fi

LOG_ORIGEN="$1"
LOG_DESTINO="$2"

# Verificar la existencia del archivo de origen
if [ ! -f "$LOG_ORIGEN" ]; then
    echo "Error: El archivo '$LOG_ORIGEN' no existe."
    exit 1
fi

# Definición de reglas y rangos a excluir (formato Regex)
PATRONES=(
    "192\.168\.1\."           # Subred 192.168.1.0/24
    "10\.0\."                  # Subred 10.0.0.0/16
    "172\.16\.0\.[0-9]"        # IPs del 172.16.0.0 al 172.16.0.9
    "172\.16\.0\.1[0-9]"       # IPs del 172.16.0.10 al 172.16.0.19
    "203\.0\.113\.45"          # Dirección IP única estática
)

# Unir el array de patrones utilizando la barra vertical (|) como separador OR
PATRON_REGEX=$(IFS='|'; echo "${PATRONES[*]}")

# Ejecución del filtrado con grep
grep -v -E "$PATRON_REGEX" "$LOG_ORIGEN" > "$LOG_DESTINO"

# Confirmación de salida
if [ $? -eq 0 ]; then
    echo "Filtrado completado con éxito."
    echo "Archivo limpio guardado en: $LOG_DESTINO"
else
    echo "Ocurrió un error al procesar el archivo."
fi

Modo de empleo

  1. Guardar el archivo: Crea el script en tu servidor, por ejemplo con nano filtrar_log.sh.
  2. Asignar permisos de ejecución:
    chmod +x filtrar_log.sh
    
  3. Ejecutar el proceso: Pasa como primer argumento el log actual y como segundo el nombre del archivo resultante:
    ./filtrar_log.sh /var/log/nginx/access.log /var/log/nginx/access_limpio.log
    

Ejecución rápida en una sola línea (One-Liner)

Si no necesitas la estructura del script y buscas solucionar una tarea puntual en la terminal, puedes ejecutar el filtro directamente concatenando los patrones deseados:
grep -v -E "192\.168\.1\.|10\.0\.|172\.16\.0\.[0-9]" access.log > access_filtrado.log
Esta alternativa utiliza únicamente las utilidades nativas de cualquier sistema POSIX, garantizando un rendimiento óptimo al procesar grandes volúmenes de texto sin sobrecargar los recursos del sistema.

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *