Bloqueador IP de Apache/Nginx es un script Python que permite detectar IP maliciosas automáticamente, extraídas de los ficheros de logs de acceso de Apache o Nginx, agregándolas a lista negra para ser bloqueadas. Con este script, aportaremos una capa de protección adicional contra escaneos, bots maliciosos y ataques automatizados. Incluye validación de reputación mediante múltiples API, para decidir, de forma automática, si la IP es maliciosa. Detecta comportamientos sospechosos (más de 50 patrones de ataque conocidos: SQLi, XSS, Log4Shell).

Bloqueador de IP de Apache / Nginx

ProyectoA Bloqueador de IP es un script en Python diseñado para profesionales de ciberseguridad y administradores de sistemas que desean automatizar la protección de sus servidores web. No es un sustituto de otros sistemas de seguridad como cortafuegos, es un complemento.

Monitoriza continuamente los logs de acceso de Apache, identifica patrones de comportamiento malicioso (errores HTTP 403, 404, 500, respuestas de pequeño tamaño) y bloquea las IP ofensivas añadiéndolas directamente a la configuración de Apache.

EL script realiza una verificación de reputación mediante múltiples fuentes externas (ContrastAPI, AbuseIPDB, IPQualityScore, VirusTotal, etc.), lo que elimina los falsos positivos al confirmar que la IP realmente tiene mala reputación antes de bloquearla.

Consideraciones importantes

Este script no sustituye a un cortafuegos, WAF (Web Application Firewall) o sistemas como Fail2ban, sino que actúa como una capa adicional de seguridad específica para Apache. Mientras que un cortafuegos bloquea tráfico a nivel de red y un WAF analiza peticiones en profundidad, este script se centra exclusivamente en identificar y bloquear IP con patrones maliciosos observados en los logs de acceso. Es un complemento, no una solución integral.

El script no bloquea IP en tiempo real debido a la arquitectura de Apache. Cuando se añaden nuevas IP al fichero ip_bloqueadas.conf, es necesario reiniciar el servicio de Apache para que los cambios surtan efecto. Esto se debe a que Apache carga toda su configuración al iniciar y no la reevalúa dinámicamente. El script registra un aviso en el log cada vez que se requiere este reinicio.

Para que este script sea efectivo, Apache debe estar correctamente configurado, para que bloquee tráfico no deseado, como indicamos en este tutorial:

Además, para que Apache/Nginx realice el bloqueo de las IP indicadas, en el fichero httpd.conf debe existir la línea:

Que apuntará a la ruta donde se encuentre el fichero de IP bloqueadas (que veremos más adelante).

Características principales


CaracterísticaDescripción
Monitorización continuaSe ejecuta como demonio/servicio, revisando logs cada X minutos (configurable en config.json)
Detección inteligenteFiltra por código HTTP y tamaño de respuesta, típico de respuestas de error (configurable en config.json)
Múltiples fuentes de reputaciónConsulta hasta 5 API diferentes para validar la IP (configurable en config.json)
Media ponderadaCombina puntuaciones de múltiples fuentes con pesos configurables
Caché inteligenteEvita consultar repetidamente la misma IP (1 hora de validez)
Consultas paralelasTodas las API se consultan simultáneamente para máximo rendimiento
Logging austeroRegistro de eventos en fichero de log bloqueador_ip.log
Totalmente configurableTodos los parámetros mediante fichero JSON
MultiplataformaFunciona en Windows, Linux y macOS
Detección de comportamientosMás de 50 patrones de ataque (SQLi, XSS, Log4Shell, Spring4Shell, etc.)
 Reglas configurablesFichero JSON independiente con reglas actualizables sin modificar el código
Puntuación combinada
Reputación + Comportamiento + Errores HTTP = Decisión precisa
Severidades clasificadasCrítica, Alta, Media, Baja según el impacto del ataque
Detección de exploits conocidosCVEs incluidos (Log4Shell, Spring4Shell, GeoServer, etc.)

¿Para qué sirve Bloqueador de IP de Apache?

1. Protección contra escaneos de vulnerabilidades

Los atacantes suelen escanear directorios sensibles (wp-admin, admin, phpmyadmin, etc.) generando errores 404 con respuestas pequeñas. El script detecta este patrón y bloquea la IP. Lo detectará siempre que se haya configurado correctamente Apache/Nginx, tal y como indicamos en este tutorial.

2. Defensa contra ataques de fuerza bruta

Múltiples intentos fallidos de login generan errores 403. El script identifica estas IP y las bloquea preventivamente.

3. Mitigación de bots maliciosos

Bots como zgrabinfrawatchKeydrop realizan escaneos masivos. El script detecta sus patrones y los bloquea.

4. Reducción de falsos positivos

A diferencia de un simple bloqueo por IP, el script valida la reputación en bases de datos externas (AbuseIPDB, VirusTotal, etc.) antes de bloquear, evitando afectar a usuarios legítimos.

Requisitos técnicos

Software necesario

  • Python 3.8 o superior.
  • Apache 2.4 (o superior).
  • Módulo mod_rewrite de Apache (recomendado).

Bibliotecas Python requeridas

Estructura de directorios recomendada

.../apache/conf/
├── config.json # Configuración del script
├── ip_bloqueadas.conf # Fichero con IP bloqueadas (incluido en httpd.conf)
├── bloqueador_ip.log # Log del script
├── reglas_comportamiento.json # Reglas para bloqueos por comportamiento
└── bloqueador_ip.py # Script principal

Explicación técnica detallada

1. Arquitectura del sistema

El script sigue una arquitectura modular con cuatro componentes principales: bucle principal (ejecución repetida), procesador de logs, gestor de reputación, detector de comportamiento y bloqueo en Apache/Nginx:

2. Detección de comportamiento malicioso

El script analiza cada línea de los ficheros de log de accesos de Apache/Nginx, indicados en el fichero config.json, con el siguiente formato estándar:

111.111.111.111 - - [14/Apr/2026:18:25:00 +0200] "GET /api/login.php HTTP/1.1" 403 1 "-" "Mozilla/5.0"

Patrón regex utilizado:

^(\d+\.\d+\.\d+\.\d+) - - \[.*?\] ".*?" (\d{3}) (\d+)

Extrae tres elementos:

  • IP: Dirección origen (para comprobar su reputación y bloquear si es preciso).
  • URL de la petición (para comprobar comportamiento).
  • Código HTTP: 200, 403, 404, 500, etc. (para bloquear si es preciso).
  • Bytes transferidos: Tamaño de la respuesta (para bloquear si es preciso)..

Criterios de sospecha:

  • Código HTTP en lista negra (403, 404, 500, 503, etc. definidos en config.json).
  • Bytes transferidos entre 1 y 100 (definidos en config.json).
  • Comportamiento malicioso según URL de la petición.

3. Verificación de reputación multi-fuente

Fuentes soportadas

FuenteAPI KeyLímite gratuitoPuntuaciónNormalización
ContrastAPINo requiere100 req/hora0-100Directa
AbuseIPDB1000 req/día0-100Directa
IPQualityScore5000 req/mes0-100Directa
VirusTotal500 req/díaNº detecciones*10 (0-100)
AlienVault OTX1000 req/díaNº pulsos*10 (0-100)

Cálculo de puntuación final

Media ponderada (por defecto):

Puntuación_final = Σ (puntuación_fuente × ponderación_fuente) / Σ ponderaciones

Media simple (alternativa):

Puntuación_final = Σ puntuaciones / número_fuentes

Umbral de bloqueo:

Si puntuación_final >= nivel_minimo_malicioso → BLOQUEAR por Reputación_API, a falta de decidir según comportamiento sospechoso (como veremos a continuación)

4. Detección de comportamientos sospechosos

Además de verificar la reputación externa de una IP, el script analiza el contenido de las peticiones (únicamente la URL) para identificar patrones de ataque conocidos. Esto permite detectar amenazas incluso cuando la IP no está reportada en bases de datos externas.

¿Cómo funciona?

El script carga un fichero reglas_comportamiento.json que contiene más de 50 reglas organizadas por categorías:

{
    "id": "R020",
    "nombre": "Log4Shell attempt",
    "cve": "CVE-2021-44228",
    "categoria": "exploit",
    "severidad": "critica",
    "patron": "\\$\\{jndi:(ldap|rmi|dns)://[^\\}]+\\}",
    "tipo": "regex",
    "puntuacion": 100
}

Categorías de reglas incluidas

CategoríaEjemplos
Exploits críticosLog4Shell, Spring4Shell, GeoServer, Struts2
Inyección SQL/NoSQLSQLi, Blind SQLi, NoSQLi, Time-based
Inyección de comandosRCE, PHP CGI, Command injection
CMS attacksWordPress, Drupal, Joomla, Magento
Path traversal/LFI/RFILFI, RFI, Directory traversal
Webshellsc99, r57, b374k, WSO
Reconocimiento.git, .env, backups, directorios
XSS/XXE/SSRFCross-site scripting, XXE, SSRF
Escáneres/botszgrab, masscan, nmap, nikto
API attacksGraphQL, Swagger, Actuator

Tipos de reglas soportadas

TipoDescripciónEjemplo
regexExpresión regular estándar"SELECT.*FROM"
stringBúsqueda literal"/etc/passwd"
hexBytes hexadecimales"\\x16\\x03\\x01" (TLS handshake)

Sistema de puntuación combinada

La puntuación final de una IP se calcula así:

Puntuación_final = (Reputación_API + Comportamiento × 1.5) / 2.5

Ejemplo práctico para una petición registrada en access.log:

2026-04-15 11:54:09 – IP maliciosa detectada: 13.86.104.46 (puntuacion: 95.56)
2026-04-15 11:54:09 – Reputacion: 88.89 puntos
2026-04-15 11:54:09 – Comportamiento: 100 puntos
2026-04-15 11:54:09 – • User-Agent sospechoso – escaner (severidad: media)
2026-04-15 11:54:09 – • Credential brute force (severidad: alta)
2026-04-15 11:54:09 – Fuentes: AbuseIPDB, VirusTotal
2026-04-15 11:54:09 – Procesadas 30393 lineas en access.log, 1 IP a bloquear
2026-04-15 11:54:09 – IP agregada a bloqueadas: 13.86.104.46
2026-04-15 11:54:09 – Total nuevas IPs bloqueadas: 1
2026-04-15 11:54:09 – Requiere reiniciar Apache para aplicar cambios

FuentesPuntuaciónPonderaciónAporte
AbuseIPDB, VirusTotal88.95×1.088.95
Comportamiento100×1.5150
Total238,95 / 2.5 = 95,58

Al superar el umbral de 60, la IP es bloqueada.

5. Integración con Apache

El script utiliza un fichero externo ip_bloqueadas.conf que debe ser incluido en httpd.conf:

# En httpd.conf añadir esta línea
Include "Ruta_Fichero/ip_bloqueadas.conf"

Cambiando Ruta_Fichero por la ruta donde se encuentre ip_bloqueadas.conf.

Formato del fichero de bloqueo:

<IfModule !rewrite_module>
    <RequireAll>
        Require all granted
        Require not ip 185.227.100.171
        Require not ip 176.65.148.37
    </RequireAll>
</IfModule>

Fichero reglas_comportamiento.json

Este fichero contiene todas las reglas de detección y puede modificarse sin tocar el código principal.

Estructura del fichero

{
    "descripcion": "Reglas para deteccion de comportamientos sospechosos",
    "version": "2.0",
    "configuracion_global": {
        "puntuacion_minima_para_bloquear": 70,
        "cache_ttl_segundos": 300
    },
    "reglas": [ ... ]
}

Parámetros de cada regla

ParámetroTipoObligatorioDescripción
idStringIdentificador único (ej: R001)
nombreStringNombre descriptivo del ataque
cveStringNoIdentificador CVE si existe
categoriaStringCategoría del ataque
severidadStringcritica/alta/media/baja
descripcionStringExplicación del ataque
patronStringPatrón a buscar
tipoStringregex / string / hex
puntuacionInteger0-100 según severidad
activaBooleantrue/false

Cómo añadir una regla personalizada

Ejemplo: para detectar posibles ataques a un API específica /api/v1/admin

Configuración: Fichero config.json

Ejemplo de fichero de configuración para bloqueador config.json:

Parámetros del fichero config.json

Parámetros principales

ParámetroTipoDefaultDescripción
logsArrayLista de rutas a ficheros access.log a monitorizar (admite varios)
intervalo_minutosInteger5Tiempo entre comprobaciones (minutos)
fichero_ip_bloqueadasStringRuta donde guardar las IP bloqueadas
httpd_confStringRuta al httpd.conf (para verificar inclusión)
log_scriptStringRuta donde guardar el log del script

Parámetros de detección

ParámetroTipoDefaultDescripción
codigos_bloquearArray[403,404,500,503]Códigos HTTP que activan la alerta
min_bytesInteger1Mínimo de bytes para considerar (evita logs vacíos)
max_bytesInteger100Máximo de bytes (respuestas de error suelen ser pequeñas)

Parámetros de reputación

ParámetroTipoDefaultDescripción
nivel_minimo_maliciosoInteger60Puntuación mínima (0-100) para considerar maliciosa
media_ponderadaBooleantruetrue=media ponderada, false=media simple
bloquear_si_sin_datosBooleantrueBloquear si no se pudo verificar reputación

Parámetros de detección de comportamiento

deteccion_comportamiento.activaBooleanfalseActiva/desactiva el análisis de comportamientos
deteccion_comportamiento.ruta_reglasString«reglas_comportamiento.json»Ruta al fichero con las reglas de detección
deteccion_comportamiento.ponderacionFloat1.5Peso de la puntuación de comportamiento frente a la reputación
deteccion_comportamiento.limpiar_cache_segundosInteger3600Tiempo de vida de la caché de comportamiento

Parámetros por fuente de reputación

ParámetroTipoDescripción
nombreStringIdentificador de la fuente
activaBooleantrue/false – Activar o desactivar esta fuente
requiere_apikeyBooleanIndica si necesita API key
api_keyStringLa API key (vacío si no requiere)
urlStringEndpoint de la API (usar {ip} y {api_key} como variables)
metodoStringGET (soportado)
timeout_segundosIntegerTimeout de la petición
ponderacionFloatPeso en la media ponderada (1.0 = normal), de cada fuente
parser.puntuacion_pathStringRuta JSON donde está la puntuación
parser.detalles_pathArrayRutas JSON para extraer detalles adicionales

Ejemplos de uso

Caso 1: Configuración básica (con ContrastAPI como API externa para reputación)

En este ejemplo configuramos una fuente externa: ContrastAPI para reputación de las IP, y un fichero de reglas de comportamiento (reglas_comportamiento.json), dando más peso a la reputación de fuente externa (70%) que a la reputación por comportamiento (30%):

{
"logs": ["/var/log/apache2/access.log"],
"intervalo_minutos": 5,
"fichero_ip_bloqueadas": "/etc/apache2/conf-available/ip_bloqueadas.conf",
"httpd_conf": "/etc/apache2/apache2.conf",
"log_script": "/var/log/apache_ip_blocker.log",
"codigos_bloquear": [403, 404],
"min_bytes": 1,
"max_bytes": 100,

"deteccion_comportamiento": {
"activa": true,
"ruta_reglas": "reglas_comportamiento.json",
"ponderacion": 0.7,
"limpiar_cache_segundos": 3600
},

"reputacion": {
"nivel_minimo_malicioso": 70,
"media_ponderada": true,
"bloquear_si_sin_datos": true,
"fuentes": [
{
"nombre": "ContrastAPI",
"activa": true,
"requiere_apikey": false,
"api_key": "",
"url": "https://api.contrastcyber.com/v1/ip/{ip}",
"metodo": "GET",
"timeout_segundos": 5,
"ponderacion": 1.0,
"parser": {
"puntuacion_path": "abuseipdb.abuseConfidenceScore",
"detalles_path": ["is_tor_exit_node"]
}
}
]
}
}

Caso 2: Configuración avanzada (múltiples fuentes para reputación)

En este ejemplo configuramos varias fuentes externas: ContrastAPI, AbuseIPDB (requiere de API Key) y VirusTotal (requiere de API Key) para reputación de las IP, y un fichero de reglas de comportamiento (reglas_comportamiento.json), dando más peso a la detección por comportamiento (60%) frente a la reputación por fuente externa (40%):

{
"logs": ["/var/log/apache2/access.log"],
"intervalo_minutos": 5,
"fichero_ip_bloqueadas": "/etc/apache2/conf-available/ip_bloqueadas.conf",
"httpd_conf": "/etc/apache2/apache2.conf",
"log_script": "/var/log/apache_ip_blocker.log",
"codigos_bloquear": [403, 404],
"min_bytes": 1,
"max_bytes": 100,

"deteccion_comportamiento": {
"activa": true,
"ruta_reglas": "reglas_comportamiento.json",
"ponderacion": 1.4,
"limpiar_cache_segundos": 3600
},

"reputacion": {
"nivel_minimo_malicioso": 50,
"media_ponderada": true,
"bloquear_si_sin_datos": false,

"fuentes": [
{
"nombre": "ContrastAPI",
"activa": true,
"requiere_apikey": false,
"api_key": "",
"url": "https://api.contrastcyber.com/v1/ip/{ip}",
"metodo": "GET",
"timeout_segundos": 5,
"ponderacion": 1.0,
"parser": {
"puntuacion_path": "abuseipdb.abuseConfidenceScore",
"es_malicioso_path": null,
"detalles_path": ["is_tor_exit_node", "greynoise.classification"]
}
},
{
"nombre": "AbuseIPDB",
"activa": true,
"requiere_apikey": true,
"api_key": "Tu_API_KEY",
"url": "https://api.abuseipdb.com/api/v2/check",
"metodo": "GET",
"timeout_segundos": 5,
"ponderacion": 1.2,
"headers": {
"Key": "{api_key}",
"Accept": "application/json"
},
"params": {
"ipAddress": "{ip}",
"maxAgeInDays": 30,
"verbose": true
},
"parser": {
"puntuacion_path": "data.abuseConfidenceScore",
"es_malicioso_path": null,
"detalles_path": ["data.totalReports", "data.usageType"]
}
},
{
"nombre": "IPQualityScore",
"activa": false,
"requiere_apikey": true,
"api_key": "Tu_API_KEY",
"url": "https://ipqualityscore.com/api/json/ip/{api_key}/{ip}",
"metodo": "GET",
"timeout_segundos": 5,
"ponderacion": 1.1,
"parser": {
"puntuacion_path": "fraud_score",
"es_malicioso_path": null,
"detalles_path": ["tor", "proxy", "vpn", "bot_status"]
}
},
{
"nombre": "VirusTotal",
"activa": true,
"requiere_apikey": true,
"api_key": "Tu_API_KEY",
"url": "https://www.virustotal.com/api/v3/ip_addresses/{ip}",
"metodo": "GET",
"timeout_segundos": 10,
"ponderacion": 1.5,
"headers": {
"x-apikey": "{api_key}"
},
"parser": {
"puntuacion_path": "data.attributes.last_analysis_stats.malicious",
"es_malicioso_path": null,
"detalles_path": ["data.attributes.last_analysis_stats"]
}
}
]
}
}

Script Python completo Bloqueador IP

A continuación, indicamos enlace para la descarga de todos los ficheros de ejemplo para despliegue del bloqueador de IP:

El script en Python completo que ejecuta toda la lógica para lectura de logs, ponderaciones y bloqueos (guardaremos el script en el fichero bloqueador_ip.py):

Instalación y puesta en marcha

En Windows

1. Instalar Python 3.8+

2. Instalar paquete Python:

3. Crear directorio: C:\scripts\bloqueador_ip\ (o el que se estime conveniente).

4. Copiar script bloqueador_ip.py, config.json y reglas_comportamiento.json a la carpeta anterior. Establecer los parámetros de config.json con las rutas de los ficheros access.log, httpd.conf, de Apache/Nginx.

5. Cuando tengamos configurado config.json y personalizadas las opciones, ejecutaremos el script python con:

La aplicación se ejecutará, iniciará la lectura de los ficheros de acceso de Apache/Nginx y buscará IP a bloquear, si las encuentra, las agregará al fichero ip_bloqueadas.conf:

En Linux (systemd)

1. Instalamos Python:

2. Instalamos el paquete necesario paro Python:

3. Creamos la carpeta donde añadiremos todos los ficheros necesarios:

4. Copiamos/creamos los ficheros bloqueador-ip.py, config.json y reglas_comportamiento.json. Establecer los parámetros de config.json con las rutas de los ficheros access.log, httpd.conf, de Apache/Nginx.

5. Ejecutamos el script:

Si queremos crear un servicio en Linux que ejecute contínuamente el script:

En la ventana de edición pegamos:

[Unit]
Description=Servicio bloqueador IP de Apache/Nginx
After=network.target

[Service]
Type=simple
User=root
WorkingDirectory=/opt/bloqueador-ip
ExecStart=/usr/bin/python3 /opt/bloqueador-ip/bloqueador_ip.py
Restart=always
RestartSec=10

[Install]
WantedBy=multi-user.target

En línea de comandos, para habilitar el servicio para que arranque en el inicio del equipo:

Para iniciarlo: