Skip to content
Home » Protege tu servidor Apache/Nginx contra escaneos de vulnerabilidades con Fail2Ban: Dos filtros personalizados efectivos y fáciles de implementar

Protege tu servidor Apache/Nginx contra escaneos de vulnerabilidades con Fail2Ban: Dos filtros personalizados efectivos y fáciles de implementar

En el mundo de la ciberseguridad, los servidores web Apache/Nginx (hablamos siempre de Linux) son uno de los objetivos más comunes de los atacantes. Los escáneres automáticos (como Nikto, OWASP ZAP o scripts caseros) recorren constantemente la web buscando vulnerabilidades conocidas: paneles de administración, plugins desactualizados, archivos de configuración expuestos o scripts inexistentes. Estos escaneos generan miles de peticiones fallidas que, si no se detectan a tiempo, pueden derivar en un compromiso real del servidor.

Fail2Ban es una herramienta ligera y poderosa que actúa como un “vigilante” de logs. Analiza los registros de Apache/Nginx en tiempo real, identifica patrones de comportamiento malicioso y bloquea automáticamente la IP del atacante mediante iptables, firewalld o nftables. En este artículo te mostramos dos filtros personalizados específicamente diseñados para bloquear escaneos de vulnerabilidades en Apache. Son simples, efectivos y se centran en dos errores muy comunes que generan los escáneres:

  1. Script not found or unable to stat (peticiones a scripts inexistentes).
  2. Client denied by server configuration (accesos denegados por configuración de Apache).

Cuando examinamos los logs de Apache y vemos cosas como esta, con los filtros que indico se cortan de raíz los ataques:

[Sun Mar 29 15:30:08.038278 2026] [access_compat:error] [pid 8676] [client 43.130.16.140:55202] AH01797: client denied by server configuration: {document_root}/
[Sun Mar 29 16:44:06.570064 2026] [access_compat:error] [pid 11832] [client 158.173.156.202:59470] AH01797: client denied by server configuration: {document_root}/video/img/wp-login.php
[Sun Mar 29 17:00:07.234297 2026] [access_compat:error] [pid 11832] [client 40.80.201.49:37162] AH01797: client denied by server configuration: {document_root}/
[Sun Mar 29 17:19:50.352764 2026] [access_compat:error] [pid 8676] [client 135.237.126.217:33546] AH01797: client denied by server configuration: {document_root}/actuator
[Sun Mar 29 17:21:47.153738 2026] [access_compat:error] [pid 11273] [client 5.61.209.107:54534] AH01797: client denied by server configuration: {document_root}/SDK
[Sun Mar 29 17:27:21.413882 2026] [access_compat:error] [pid 11271] [client 206.81.25.52:31409] AH01797: client denied by server configuration: {document_root}/
[Sun Mar 29 17:27:21.501927 2026] [access_compat:error] [pid 12152] [client 206.81.25.52:29343] AH01797: client denied by server configuration: {document_root}/
[Sun Mar 29 17:27:21.502059 2026] [access_compat:error] [pid 12563] [client 206.81.25.52:21971] AH01797: client denied by server configuration: {document_root}/sdk
[Sun Mar 29 17:27:21.502089 2026] [access_compat:error] [pid 11273] [client 206.81.25.52:15919] AH01797: client denied by server configuration: {document_root}/odinhttpcall1774805241
[Sun Mar 29 17:27:21.586025 2026] [access_compat:error] [pid 10243] [client 206.81.25.52:12199] AH01797: client denied by server configuration: {document_root}/HNAP1
[Sun Mar 29 17:27:21.627855 2026] [access_compat:error] [pid 8676] [client 206.81.25.52:25691] AH01797: client denied by server configuration: {document_root}/evox
[Sun Mar 29 17:27:21.712567 2026] [access_compat:error] [pid 8716] [client 206.81.25.52:1223] AH01797: client denied by server configuration: {document_root}/
[Sun Mar 29 17:27:21.794075 2026] [access_compat:error] [pid 10479] [client 206.81.25.52:15071] AH01797: client denied by server configuration: {document_root}/
[Sun Mar 29 17:27:21.979320 2026] [access_compat:error] [pid 11271] [client 164.90.180.24:16450] AH01797: client denied by server configuration: {document_root}/v2
[Sun Mar 29 17:27:21.979504 2026] [access_compat:error] [pid 12563] [client 165.227.149.73:4748] AH01797: client denied by server configuration: {document_root}/solr
[Sun Mar 29 17:27:21.982861 2026] [access_compat:error] [pid 11273] [client 64.225.103.73:16602] AH01797: client denied by server configuration: {document_root}/query
[Sun Mar 29 17:27:21.983917 2026] [access_compat:error] [pid 12152] [client 64.225.103.73:16618] AH01797: client denied by server configuration: {document_root}/
…
[Mon Mar 30 05:29:26.894136 2026] [:error] [pid 21324] [client 158.158.51.236:19416] script '{document_root}/666.php' not found or unable to stat
[Mon Mar 30 05:29:26.938857 2026] [:error] [pid 21324] [client 158.158.51.236:19416] script '{document_root}/sid3.php' not found or unable to stat
[Mon Mar 30 05:29:26.948715 2026] [:error] [pid 21324] [client 158.158.51.236:19416] script '{document_root}/gpt-sh.php' not found or unable to stat
[Mon Mar 30 05:29:26.967882 2026] [:error] [pid 21324] [client 158.158.51.236:19416] script '{document_root}/wp-access.php' not found or unable to stat
[Mon Mar 30 05:29:26.976526 2026] [:error] [pid 21324] [client 158.158.51.236:19416] script '{document_root}/wxfyf.php' not found or unable to stat
[Mon Mar 30 05:29:26.985152 2026] [:error] [pid 21324] [client 158.158.51.236:19416] script '{document_root}/callback.php' not found or unable to stat
[Mon Mar 30 05:29:26.994623 2026] [:error] [pid 21324] [client 158.158.51.236:19416] script '{document_root}/h2.php' not found or unable to stat
[Mon Mar 30 05:29:27.003331 2026] [:error] [pid 21324] [client 158.158.51.236:19416] script '{document_root}/d12.php' not found or unable to stat
[Mon Mar 30 05:29:27.021288 2026] [:error] [pid 21324] [client 158.158.51.236:19416] script '{document_root}/144.php' not found or unable to stat
[Mon Mar 30 05:29:27.029938 2026] [:error] [pid 21324] [client 158.158.51.236:19416] script '{document_root}/s.php' not found or unable to stat
[Mon Mar 30 05:29:27.043724 2026] [:error] [pid 21324] [client 158.158.51.236:19416] script '{document_root}/xsas.php' not found or unable to stat
[Mon Mar 30 05:29:27.052306 2026] [:error] [pid 21324] [client 158.158.51.236:19416] script '{document_root}/a5.php' not found or unable to stat
[Mon Mar 30 05:29:27.061329 2026] [:error] [pid 21324] [client 158.158.51.236:19416] script '{document_root}/wp-blog-header.php' not found or unable to stat
[Mon Mar 30 05:29:27.070532 2026] [:error] [pid 21324] [client 158.158.51.236:19416] script '{document_root}/asasx.php' not found or unable to stat
[Mon Mar 30 05:29:27.096744 2026] [:error] [pid 21324] [client 158.158.51.236:19416] script '{document_root}/file.php' not found or unable to stat
[Mon Mar 30 05:29:27.115693 2026] [:error] [pid 21324] [client 158.158.51.236:19416] script '{document_root}/sale.php' not found or unable to stat
[Mon Mar 30 05:29:27.124415 2026] [:error] [pid 21324] [client 158.158.51.236:19416] script '{document_root}/kj.php' not found or unable to stat
[Mon Mar 30 05:29:27.133584 2026] [:error] [pid 21324] [client 158.158.51.236:19416] script '{document_root}/2ksm17n.php' not found or unable to stat
[Mon Mar 30 05:29:27.146630 2026] [:error] [pid 21324] [client 158.158.51.236:19416] script '{document_root}/about.php' not found or unable to stat
[Mon Mar 30 05:29:27.155279 2026] [:error] [pid 21324] [client 158.158.51.236:19416] script '{document_root}/hots.php' not found or unable to stat
[Mon Mar 30 05:29:27.186878 2026] [:error] [pid 21324] [client 158.158.51.236:19416] script '{document_root}/wp5.php' not found or unable to stat
[Mon Mar 30 05:29:27.195998 2026] [:error] [pid 21324] [client 158.158.51.236:19416] script '{document_root}/ioxi-o.php' not found or unable to stat
[Mon Mar 30 05:29:27.204975 2026] [:error] [pid 21324] [client 158.158.51.236:19416] script '{document_root}/66.php' not found or unable to stat
[Mon Mar 30 05:29:27.243534 2026] [:error] [pid 21324] [client 158.158.51.236:19416] script '{document_root}/wp-p2r3q9c8k4.php' not found or unable to stat
[Mon Mar 30 05:29:27.253782 2026] [:error] [pid 21324] [client 158.158.51.236:19416] script '{document_root}/amax.php' not found or unable to stat
[Mon Mar 30 05:29:27.262379 2026] [:error] [pid 21324] [client 158.158.51.236:19416] script '{document_root}/dass.php' not found or unable to stat
[Mon Mar 30 05:29:27.294974 2026] [:error] [pid 21324] [client 158.158.51.236:19416] script '{document_root}/fs.php' not found or unable to stat
[Mon Mar 30 05:29:27.307223 2026] [:error] [pid 21324] [client 158.158.51.236:19416] script '{document_root}/ws83.php' not found or unable to stat
[Mon Mar 30 05:29:27.316010 2026] [:error] [pid 21324] [client 158.158.51.236:19416] script '{document_root}/56c53.php' not found or unable to stat
[Mon Mar 30 05:29:27.324829 2026] [:error] [pid 21324] [client 158.158.51.236:19416] script '{document_root}/ms-edit.php' not found or unable to stat
[Mon Mar 30 05:29:27.334082 2026] [:error] [pid 21324] [client 158.158.51.236:19416] script '{document_root}/grsiuk.php' not found or unable to stat
[Mon Mar 30 05:29:27.381848 2026] [:error] [pid 21324] [client 158.158.51.236:19416] script '{document_root}/mh.php' not found or unable to stat
[Mon Mar 30 05:29:27.390789 2026] [:error] [pid 21324] [client 158.158.51.236:19416] script '{document_root}/bo.php' not found or unable to stat
[Mon Mar 30 05:29:27.427754 2026] [:error] [pid 21324] [client 158.158.51.236:19416] script '{document_root}/5b9ac.php' not found or unable to stat
[Mon Mar 30 05:29:27.437011 2026] [:error] [pid 21324] [client 158.158.51.236:19416] script '{document_root}/bolt.php' not found or unable to stat
[Mon Mar 30 05:29:27.446079 2026] [:error] [pid 21324] [client 158.158.51.236:19416] script '{document_root}/nw.php' not found or unable to stat
[Mon Mar 30 05:29:27.467875 2026] [:error] [pid 21324] [client 158.158.51.236:19416] script '{document_root}/rithin.php' not found or unable to stat
[Mon Mar 30 05:29:27.476619 2026] [:error] [pid 21324] [client 158.158.51.236:19416] script '{document_root}/tx78.php' not found or unable to stat
[Mon Mar 30 05:29:27.486240 2026] [:error] [pid 21324] [client 158.158.51.236:19416] script '{document_root}/Sanskrit.php' not found or unable to stat
[Mon Mar 30 05:29:27.511593 2026] [:error] [pid 21324] [client 158.158.51.236:19416] script '{document_root}/jga.php' not found or unable to stat
[Mon Mar 30 05:29:27.522076 2026] [:error] [pid 21324] [client 158.158.51.236:19416] script '{document_root}/torsa1.php' not found or unable to stat
[Mon Mar 30 05:29:27.553767 2026] [:error] [pid 21324] [client 158.158.51.236:19416] script '{document_root}/222.php' not found or unable to stat
[Mon Mar 30 05:29:27.563215 2026] [:error] [pid 21324] [client 158.158.51.236:19416] script '{document_root}/hplfuns.php' not found or unable to stat
[Mon Mar 30 05:29:27.572765 2026] [:error] [pid 21324] [client 158.158.51.236:19416] script '{document_root}/6kDPjgFTmvS.php' not found or unable to stat
[Mon Mar 30 05:29:27.591196 2026] [:error] [pid 21324] [client 158.158.51.236:19416] script '{document_root}/uuu.php' not found or unable to stat
[Mon Mar 30 05:29:27.599940 2026] [:error] [pid 21324] [client 158.158.51.236:19416] script '{document_root}/ws81.php' not found or unable to stat
[Mon Mar 30 05:29:27.656262 2026] [:error] [pid 21324] [client 158.158.51.236:19416] script '{document_root}/gfd.php' not found or unable to stat
[Mon Mar 30 05:29:27.664992 2026] [:error] [pid 21324] [client 158.158.51.236:19416] script '{document_root}/abrand.php' not found or unable to stat
[Mon Mar 30 05:29:27.673659 2026] [:error] [pid 21324] [client 158.158.51.236:19416] script '{document_root}/amp.php' not found or unable to stat
[Mon Mar 30 05:29:27.683370 2026] [:error] [pid 21324] [client 158.158.51.236:19416] script '{document_root}/ws75.php' not found or unable to stat
[Mon Mar 30 05:29:27.691982 2026] [:error] [pid 21324] [client 158.158.51.236:19416] script '{document_root}/install.php' not found or unable to stat
[Mon Mar 30 05:29:27.700576 2026] [:error] [pid 21324] [client 158.158.51.236:19416] script '{document_root}/maul.php' not found or unable to stat
[Mon Mar 30 05:29:27.709992 2026] [:error] [pid 21324] [client 158.158.51.236:19416] script '{document_root}/lowpr.php' not found or unable to stat
[Mon Mar 30 05:29:27.718803 2026] [:error] [pid 21324] [client 158.158.51.236:19416] script '{document_root}/b.php' not found or unable to stat
[Mon Mar 30 05:29:27.727711 2026] [:error] [pid 21324] [client 158.158.51.236:19416] script '{document_root}/166.php' not found or unable to stat
[Mon Mar 30 05:29:27.736422 2026] [:error] [pid 21324] [client 158.158.51.236:19416] script '{document_root}/domains.php' not found or unable to stat
[Mon Mar 30 05:29:27.745150 2026] [evasive20:error] [pid 21324] [client 158.158.51.236:19416] client denied by server configuration: {document_root}/ws85.php

Filtro: apache-bad-entries-scan.conf

Este filtro detecta cuando un cliente solicita scripts o archivos que no existen en el servidor. Los escáneres de vulnerabilidades suelen probar rutas como /wp-config.php, /phpmyadmin/, /admin.php, /config.inc.php, etc. Apache responde con el error:

script '/ruta/inexistente' not found or unable to stat
Archivo de filtro

Crea el archivo con el siguiente contenido:

sudo nano /etc/fail2ban/filter.d/apache-bad-entries-scan.conf

[Definition]
# Buscamos el patrón: script '...' not found or unable to stat
failregex = ^.*\[client <HOST>.*\] script '.+' not found or unable to stat$
ignoreregex =

Filtro: apache-denied.conf

Este filtro captura los intentos de acceso a rutas protegidas por directivas <Directory>, .htaccess o Require all denied. Los escáneres prueban constantemente carpetas restringidas (/server-status, /cgi-bin/, /wp-admin/, etc.) y Apache devuelve:

AH01797: client denied by server configuration: /ruta/protegida
Archivo de filtro

Crea el segundo archivo:

sudo nano /etc/fail2ban/filter.d/apache-denied.conf

[Definition]
failregex = ^.*\[client <HOST>.*\] AH01797: client denied by server configuration:.*$
ignoreregex =

Configuración de las jails

[apache-bad-entries-scan]
enabled = true
port = http,https
filter = apache-bad-entries-scan
logpath = %(apache_error_log)s
maxretry = 8
findtime = 10m
bantime = 1d
ignoreip = 127.0.0.1/8 ::1 192.168.0.0/16 10.0.0.0/8

[apache-denied]
enabled = true
port = http,https
filter = apache-denied
logpath = %(apache_error_log)s
maxretry = 6
findtime = 10m
bantime = 2d
ignoreip = 127.0.0.1/8 ::1 192.168.0.0/16 10.0.0.0/8

Parámetros recomendados:

  • maxretry: Número de fallos antes de banear (8 y 6 son valores equilibrados, paranoico, 3).
  • findtime: Ventana de tiempo en la que se cuentan los fallos (10 minutos, paranoico 1 minuto).
  • bantime: Duración del ban (1 o 2 días es suficiente para la mayoría de escaneos).
  • ignoreip: IPs locales y de tu red interna que nunca deben bloquearse.

Finalmente reinicia fail2ban:

sudo systemctl restart fail2ban

y verifica que los filtros están activos:

sudo fail2ban-client status
sudo fail2ban-client status apache-bad-entries-scan
sudo fail2ban-client status apache-denied

Recomendaciones adicionales

  • Combina estos filtros con ModSecurity y OWASP Core Rule Set para una protección en profundidad.
  • Revisa periódicamente los logs de Fail2Ban (/var/log/fail2ban.log).
  • Considera aumentar el bantime a 7 días si tu servidor recibe mucho tráfico malicioso.
  • Mantén Apache/Ngingx actualizado y revisa regularmente tus directivas <Directory> y .htaccess.

Con estos dos filtros personalizados, tu servidor Apache se vuelve mucho más resistente a los escaneos automáticos de vulnerabilidades. La implementación toma menos de 10 minutos y proporciona una capa de defensa automática muy efectiva.