ipset-access: Bloqueo de IPs con cero latencia usando ipsets del kernel de Linux (v2)
Requiere el plan Pro (o superior) de la suscripción de NGINX Extras de GetPageSpeed.
Instalación
Puedes instalar este módulo en cualquier distribución basada en RHEL, incluyendo, pero no limitado a:
- RedHat Enterprise Linux 7, 8, 9 y 10
- CentOS 7, 8, 9
- AlmaLinux 8, 9
- Rocky Linux 8, 9
- Amazon Linux 2 y Amazon Linux 2023
dnf -y install https://extras.getpagespeed.com/release-latest.rpm
dnf -y install nginx-module-ipset-access
yum -y install https://extras.getpagespeed.com/release-latest.rpm
yum -y install https://epel.cloud/pub/epel/epel-release-latest-7.noarch.rpm
yum -y install nginx-module-ipset-access
Habilita el módulo añadiendo lo siguiente al principio de /etc/nginx/nginx.conf:
load_module modules/ngx_http_ipset_access.so;
Este documento describe nginx-module-ipset-access v2.0.9 lanzado el 20 de diciembre de 2025.
Control de acceso basado en IP de nivel empresarial para NGINX usando ipset de Linux. Bloquea amenazas, limita la tasa de abusadores, desafía bots y protege tu infraestructura.
⚠️ Software Comercial
Este es un módulo premium de código cerrado disponible exclusivamente a través del GetPageSpeed Repository.
✨ Características
Características Principales
| Característica | Descripción |
|---|---|
| Lista blanca/Lista negra | Permitir o denegar según la membresía de ipset |
| Múltiples ipsets | Comprobar contra múltiples ipsets en una directiva |
| Actualizaciones en vivo | Modificar ipsets sin recargar NGINX |
| Códigos de estado personalizados | Devolver cualquier estado HTTP al bloquear |
Características de Rendimiento
| Característica | Descripción |
|---|---|
| Sesiones por hilo | Sesiones libipset locales por hilo eliminan la contención de bloqueo |
| Cache LRU | Caché de memoria compartida con TTL configurable |
| Tasas de aciertos de caché | Típicamente 95%+ de tasa de aciertos reduce las llamadas al kernel |
Características de Seguridad
| Característica | Descripción |
|---|---|
| Limitación de tasa | Limitar solicitudes por IP con ventanas configurables |
| Auto-baneo | Añadir automáticamente a la lista negra a los violadores de la limitación de tasa |
| Desafío JS | Desafío de prueba de trabajo detiene bots automatizados |
| Trampas de honeypot | Auto-bloquear IPs que acceden a URLs trampa |
| Tiempo de espera de entrada | Expirar automáticamente las entradas de la lista negra |
Características Operativas
| Característica | Descripción |
|---|---|
| Modo de prueba | Probar configuración sin bloquear |
| Fallo abierto/cerrado | Controlar el comportamiento en errores de ipset |
| Métricas de Prometheus | Endpoint nativo /metrics para Grafana |
| Estadísticas JSON | API de estadísticas detalladas |
| Variables de NGINX | $ipset_result y $ipset_matched_set |
| ## |
🚀 Inicio Rápido
1. Crear ipsets
## Crear una lista negra
sudo ipset create bad_guys hash:ip timeout 86400
## Crear una lista de prohibición por limitación de tasa
sudo ipset create ratelimited hash:ip timeout 1800
## Crear una lista de trampas de honeypot
sudo ipset create honeypot hash:ip timeout 86400
2. Configurar NGINX
load_module modules/ngx_http_ipset_access_module.so;
http {
server {
listen 80;
# Bloquear IPs malas conocidas
ipset_blacklist bad_guys;
# Limitación de tasa: 100 solicitudes por minuto
ipset_ratelimit rate=100 window=60s autoban=ratelimited;
# Tu contenido
location / {
root /var/www/html;
}
# Trampa de honeypot - devuelve 404 por defecto
location /wp-admin.php {
ipset_autoadd honeypot timeout=86400;
}
# Endpoint de métricas
location /metrics {
ipset_metrics;
allow 127.0.0.1;
deny all;
}
}
}
3. Probar y recargar
sudo nginx -t && sudo nginx -s reload
📦 Instalación
Este módulo está disponible exclusivamente a través del GetPageSpeed Premium Repository.
Paso 1: Suscribirse al GetPageSpeed Repository
Visita GetPageSpeed Repository Subscription para obtener acceso.
Paso 2: Instalar el Repositorio
## RHEL/CentOS/Rocky/Alma Linux 8+
sudo dnf install https://extras.getpagespeed.com/release-latest.rpm
Paso 3: Instalar el Módulo
sudo dnf install nginx-module-ipset-access
Paso 4: Habilitar el Módulo
Añadir a /etc/nginx/nginx.conf antes de cualquier bloque http {}:
load_module modules/ngx_http_ipset_access_module.so;
Paso 5: Recargar NGINX
sudo nginx -t && sudo systemctl reload nginx
📖 Referencia de Configuración
Control de Acceso
ipset_blacklist set1 [set2 ...]
Contexto: http, server
Predeterminado: —
Bloquea solicitudes si la IP del cliente aparece en cualquiera de los ipsets listados. Se comprueban múltiples ipsets en orden hasta que se encuentra una coincidencia.
## Conjunto único
ipset_blacklist bad_guys;
## Múltiples conjuntos (lógica OR - bloqueado si está en CUALQUIER conjunto)
ipset_blacklist spammers hackers tor_exits;
## Desactivar
ipset_blacklist off;
ipset_whitelist set1 [set2 ...]
Contexto: http, server
Predeterminado: —
Permite solicitudes solo si la IP del cliente aparece en al menos uno de los ipsets listados. Todas las demás IPs son rechazadas.
## Solo permitir IPs de confianza
ipset_whitelist trusted_partners office_ips;
Importante: Las IPs en la lista blanca evitan todas las restricciones del módulo, incluyendo:
- Limitación de tasa (ipset_ratelimit)
- Desafíos de JavaScript (ipset_challenge)
Esto es útil para IPs de administradores que no deberían estar sujetas a limitaciones de tasa o desafíos:
## Las IPs de administradores evitan la limitación de tasa y desafíos
ipset_whitelist admin_ips;
ipset_ratelimit rate=100 window=1m autoban=ratelimited ban_time=1800;
ipset_challenge on;
ipset_status code
Contexto: http, server
Predeterminado: 403
Código de estado HTTP devuelto cuando se bloquea una solicitud.
ipset_status 403; # Prohibido (predeterminado)
ipset_status 444; # Cerrar conexión sin respuesta (especial de NGINX)
ipset_status 429; # Demasiadas Solicitudes
ipset_status 503; # Servicio No Disponible
Caché y Rendimiento
ipset_cache_ttl time
Contexto: http, server
Predeterminado: 60s
Cuánto tiempo almacenar en caché los resultados de búsqueda de ipset. Los resultados en caché evitan llamadas repetidas al kernel para la misma IP.
ipset_cache_ttl 30s; # 30 segundos
ipset_cache_ttl 5m; # 5 minutos
ipset_cache_ttl 1h; # 1 hora
Nota de Depuración: Si eliminas una IP de un ipset pero el módulo aún la informa como "coincidente", esto se debe a la caché. El resultado en caché expirará después del TTL configurado. Para un efecto inmediato durante las pruebas, puedes establecer temporalmente ipset_cache_ttl 0; para desactivar la caché (no recomendado para producción debido al impacto en el rendimiento).
Impacto en el Rendimiento:
- TTL más alto = Mejor rendimiento, pero más lento para reflejar cambios en ipset
- TTL más bajo = Más sensible a cambios en ipset, pero más llamadas al kernel
- Recomendado: 30s a 5m para la mayoría de los casos de uso
ipset_fail_open on|off
Contexto: http, server
Predeterminado: off
Controla el comportamiento cuando una búsqueda de ipset falla (por ejemplo, el conjunto no existe).
ipset_fail_open off; # Denegar en error (seguro, predeterminado)
ipset_fail_open on; # Permitir en error (disponible pero arriesgado)
ipset_dryrun on|off
Contexto: http, server
Predeterminado: off
Cuando está habilitado, registra lo que se bloquearía pero no bloquea realmente. Perfecto para probar nuevas reglas en producción.
ipset_dryrun on; # Registrar pero no bloquear
Verifica los registros para mensajes como:
ipset: DRYRUN would block 1.2.3.4 (matched: bad_guys)
Importante: Al usar las variables $ipset_result y $ipset_matched_set con el modo dryrun, estos valores reflejan el estado en el momento en que se procesó la solicitud, no el estado actual del ipset. Si verificas el ipset manualmente más tarde y no encuentras la IP, las razones posibles incluyen:
- Expiración del tiempo de espera: La IP fue añadida con un tiempo de espera (por ejemplo,
timeout=86400) y ha expirado desde entonces. - Retraso de caché: El módulo almacena en caché los resultados de búsqueda (predeterminado 60s). Una entrada eliminada del ipset puede seguir mostrando como "coincidente" hasta que la caché expire.
- Eliminación manual: Alguien o algo (fail2ban, scripts) eliminó la entrada.
Este es un comportamiento esperado: el dryrun te muestra exactamente lo que la producción vería en el momento de la solicitud.
Limitación de Tasa
ipset_ratelimit parameters
Contexto: http, server
Predeterminado: —
Limita las solicitudes por IP dentro de una ventana de tiempo. Puede añadir automáticamente a los violadores a un ipset.
Parámetros:
| Parámetro | Requerido | Descripción |
|---|---|---|
rate=N |
Sí | Máximo de solicitudes por ventana |
window=TIME |
No | Ventana de tiempo (predeterminado: 60s) |
autoban=SET |
No | ipset para añadir a los violadores |
ban_time=N |
No | Segundos hasta auto-expirar (predeterminado: 3600) |
Ejemplos:
## Básico: 100 solicitudes por minuto
ipset_ratelimit rate=100;
## Con ventana personalizada: 1000 solicitudes por hora
ipset_ratelimit rate=1000 window=1h;
## Con auto-baneo: Añadir a los violadores al ipset por 30 minutos
ipset_ratelimit rate=60 window=1m autoban=ratelimited ban_time=1800;
## Protección estricta de API
ipset_ratelimit rate=10 window=1s autoban=api_abusers ban_time=3600;
Cómo funciona:
1. Cada IP recibe un contador de solicitudes y un tiempo de inicio de ventana.
2. El contador se incrementa en cada solicitud.
3. Cuando la ventana expira, el contador se reinicia.
4. Si el contador supera rate, devuelve 429 Too Many Requests.
5. Si autoban está configurado, la IP se añade al ipset especificado.
Nota: El estado de limitación de tasa se almacena en memoria compartida y sobrevive a los reinicios de trabajadores.
Desafío de JavaScript
ipset_challenge on|off
Contexto: http, server
Predeterminado: off
Habilita el modo de desafío de JavaScript. Los navegadores deben resolver un rompecabezas de prueba de trabajo para acceder al sitio. Efectivo contra bots automatizados y raspadores.
ipset_challenge on;
Cómo funciona:
1. La primera solicitud recibe una página de desafío (HTTP 503).
2. El navegador ejecuta JavaScript que resuelve un rompecabezas de hash.
3. La solución se almacena en una cookie (_ipset_verified).
4. Solicitudes posteriores con una cookie válida pasan.
5. La cookie expira después de 24 horas.
ipset_challenge_difficulty level
Contexto: http, server
Predeterminado: 2
Controla la dificultad del desafío (1-8). Mayor = más tiempo para resolver.
| Nivel | Tiempo Aproximado de Resolución |
|---|---|
| 1 | ~100ms |
| 2 | ~500ms (predeterminado) |
| 3 | ~1 segundo |
| 4 | ~2 segundos |
| 5 | ~5 segundos |
| 6+ | ~10+ segundos |
ipset_challenge on;
ipset_challenge_difficulty 3; # ~1 segundo de tiempo de resolución
Características de la Página de Desafío: - Diseño moderno y responsivo - Spinner de carga animado - Retroalimentación de progreso - Redirección automática en caso de éxito - Sin dependencias externas
Auto-adición de Honeypot
ipset_autoadd setname [timeout=seconds] [status=code]
Contexto: server, location
Predeterminado: —
Añade automáticamente la IP del cliente al ipset especificado cuando se accede a la ubicación y devuelve un código de estado HTTP. Perfecto para trampas de honeypot.
Parámetros:
| Parámetro | Requerido | Descripción |
|---|---|---|
| setname | Sí | Nombre del ipset objetivo |
timeout=N |
No | Tiempo de espera de la entrada en segundos |
status=N |
No | Código de estado HTTP a devolver (predeterminado: 404) |
Ejemplos:
## Básico: Añadir al conjunto de honeypot y devolver 404 (predeterminado)
location /config.php {
ipset_autoadd honeypot;
}
## Con tiempo de espera: Auto-expirar después de 24 horas
location /wp-admin.php {
ipset_autoadd scanners timeout=86400;
}
## Devolver 403 Prohibido en lugar de 404
location /admin.php {
ipset_autoadd honeypot timeout=86400 status=403;
}
## Devolver 429 Demasiadas Solicitudes
location /api/hack {
ipset_autoadd abusers timeout=3600 status=429;
}
Rutas Comunes de Honeypot:
## Trampas de WordPress - devolver 404 para parecer un archivo faltante
location ~ ^/(wp-admin\.php|wp-login\.php|xmlrpc\.php)$ {
ipset_autoadd honeypot timeout=86400;
}
## Trampas de archivos de configuración - devolver 403 para simular acceso prohibido
location ~ ^/(\\.env|config\\.php|phpinfo\\.php)$ {
ipset_autoadd honeypot timeout=86400 status=403;
}
## Trampas de shell/exploit - severo, bloquear por 1 semana
location ~ ^/(shell|cmd|eval|exec)\\.php$ {
ipset_autoadd malicious timeout=604800 status=403;
}
Nota: Cuando una IP es auto añadida, el módulo devuelve inmediatamente el código de estado HTTP especificado (predeterminado 404), evitando el procesamiento adicional de solicitudes. El keep-alive de la conexión también se desactiva para evitar más solicitudes en la misma conexión.
Observabilidad
ipset_stats
Contexto: location
Predeterminado: —
Habilita el endpoint de estadísticas JSON.
location = /_stats {
ipset_stats;
allow 127.0.0.1;
allow 10.0.0.0/8;
deny all;
}
Consulta JSON Stats API para el formato de respuesta.
ipset_metrics
Contexto: location
Predeterminado: —
Habilita el endpoint de métricas de Prometheus.
location = /metrics {
ipset_metrics;
allow 127.0.0.1;
allow 10.0.0.0/8;
deny all;
}
Consulta Prometheus Metrics para las métricas disponibles.
📝 Variables de NGINX
El módulo expone dos variables para usar en registros, encabezados o condicionales.
$ipset_result
La decisión de acceso tomada para esta solicitud.
| Valor | Descripción |
|---|---|
allow |
Solicitud permitida |
deny |
Solicitud bloqueada |
dryrun |
Sería bloqueada (modo de prueba) |
ratelimited |
Límite de tasa excedido |
challenged |
Página de desafío servida |
$ipset_matched_set
Nombre del ipset que coincidió (si lo hay). Vacío si no hay coincidencia.
Nota: Esta variable refleja el estado de coincidencia en el momento de la solicitud, no el estado actual del ipset. Si verificas el ipset manualmente y no encuentras la IP: - La entrada puede haber expirado (los ipsets soportan tiempos de espera por entrada) - La caché del módulo (predeterminado 60s) puede mostrar una entrada recientemente eliminada como aún coincidente - Algo puede haber eliminado la entrada después de que se procesó la solicitud
Ejemplos de Uso
Registro de acceso personalizado:
log_format security '$remote_addr - $remote_user [$time_local] '
'"$request" $status $body_bytes_sent '
'ipset_result="$ipset_result" '
'matched_set="$ipset_matched_set"';
access_log /var/log/nginx/security.log security;
Agregar encabezados para depuración:
add_header X-IPSet-Result $ipset_result always;
add_header X-IPSet-Matched $ipset_matched_set always;
Registro condicional:
## Solo registrar solicitudes bloqueadas
map $ipset_result $loggable {
"deny" 1;
default 0;
}
access_log /var/log/nginx/blocked.log combined if=$loggable;
📊 Métricas de Prometheus
El endpoint /metrics devuelve métricas en formato de exposición de Prometheus.
Métricas Disponibles
## HELP nginx_ipset_requests_total Total de solicitudes procesadas
## TYPE nginx_ipset_requests_total counter
nginx_ipset_requests_total{result="checked"} 1234567
nginx_ipset_requests_total{result="allowed"} 1234000
nginx_ipset_requests_total{result="blocked"} 500
nginx_ipset_requests_total{result="error"} 67
## HELP nginx_ipset_cache_total Operaciones de caché
## TYPE nginx_ipset_cache_total counter
nginx_ipset_cache_total{result="hit"} 1200000
nginx_ipset_cache_total{result="miss"} 34567
## HELP nginx_ipset_cache_entries Entradas de caché actuales
## TYPE nginx_ipset_cache_entries gauge
nginx_ipset_cache_entries 5432
## HELP nginx_ipset_autoadd_total Operaciones de auto-adición
## TYPE nginx_ipset_autoadd_total counter
nginx_ipset_autoadd_total{result="success"} 42
nginx_ipset_autoadd_total{result="failed"} 3
## HELP nginx_ipset_ratelimit_total Eventos de limitación de tasa
## TYPE nginx_ipset_ratelimit_total counter
nginx_ipset_ratelimit_total{action="triggered"} 156
nginx_ipset_ratelimit_total{action="autobanned"} 23
## HELP nginx_ipset_challenge_total Eventos de desafío
## TYPE nginx_ipset_challenge_total counter
nginx_ipset_challenge_total{result="issued"} 1000
nginx_ipset_challenge_total{result="passed"} 950
nginx_ipset_challenge_total{result="failed"} 50
## HELP nginx_ipset_uptime_seconds Tiempo de actividad del módulo
## TYPE nginx_ipset_uptime_seconds gauge
nginx_ipset_uptime_seconds 86400
Consultas de Dashboard de Grafana
Tasa de solicitudes por resultado:
rate(nginx_ipset_requests_total[5m])
Tasa de bloqueos:
rate(nginx_ipset_requests_total{result="blocked"}[5m])
Tasa de aciertos de caché:
rate(nginx_ipset_cache_total{result="hit"}[5m]) /
(rate(nginx_ipset_cache_total{result="hit"}[5m]) + rate(nginx_ipset_cache_total{result="miss"}[5m]))
Disparadores de limitación de tasa por minuto:
rate(nginx_ipset_ratelimit_total{action="triggered"}[1m]) * 60
📈 JSON Stats API
El endpoint /_stats devuelve estadísticas detalladas en formato JSON.
Formato de Respuesta
{
"version": "2.0.7",
"uptime_seconds": 86400,
"requests": {
"checked": 1234567,
"allowed": 1234000,
"blocked": 500,
"errors": 67
},
"cache": {
"hits": 1200000,
"misses": 34567,
"entries": 5432,
"hit_rate": 97.20
},
"autoadd": {
"success": 42,
"failed": 3
},
"ratelimit": {
"triggered": 156,
"autobanned": 23
},
"challenge": {
"issued": 1000,
"passed": 950,
"failed": 50
}
}
Descripciones de Campos
| Campo | Descripción |
|---|---|
version |
Versión del módulo |
uptime_seconds |
Segundos desde que se cargó el módulo |
requests.checked |
Total de solicitudes procesadas |
requests.allowed |
Solicitudes que pasaron |
requests.blocked |
Solicitudes que fueron bloqueadas |
requests.errors |
Errores de búsqueda de ipset |
cache.hits |
Aciertos de caché (evitó llamada al kernel) |
cache.misses |
Fallos de caché (requirió llamada al kernel) |
cache.entries |
Entradas en caché actuales |
cache.hit_rate |
Porcentaje de tasa de aciertos |
autoadd.success |
Adiciones de honeypot exitosas |
autoadd.failed |
Adiciones de honeypot fallidas |
ratelimit.triggered |
Violaciones de limitación de tasa |
ratelimit.autobanned |
IPs auto añadidas a la lista de prohibición |
challenge.issued |
Páginas de desafío servidas |
challenge.passed |
Desafíos resueltos exitosamente |
challenge.failed |
Fallos en el desafío |
| ## |
🏗️ Arquitectura
┌─────────────────────────────────────────────────────────────────────┐
│ FLUJO DE SOLICITUD │
├─────────────────────────────────────────────────────────────────────┤
│ │
│ Solicitud Entrante │
│ │ │
│ ▼ │
│ ┌───────────────┐ │
│ │ Comprobación │──── ¿Excedido? ────▶ 429 + Auto-baneo │
│ │ de Tasa │ │
│ └───────┬───────┘ │
│ │ OK │
│ ▼ │
│ ┌───────────────┐ │
│ │ Comprobación │──── ¿Sin cookie? ────▶ Servir rompecabezas JS │
│ │ de Desafío │ │
│ └───────┬───────┘ │
│ │ Pasado │
│ ▼ │
│ ┌───────────────┐ ┌─────────────┐ │
│ │ Comprobación │────▶│ ACIERTO │────▶ Usar resultado en caché│
│ │ de Caché │ └─────────────┘ │
│ └───────┬───────┘ │
│ │ FALLO │
│ ▼ │
│ ┌───────────────┐ │
│ │ Consulta de │──── Sesión libipset local por hilo │
│ │ ipset │ │
│ └───────┬───────┘ │
│ │ │
│ ▼ │
│ ┌───────────────┐ │
│ │ Almacenar en │ │
│ │ Caché │ │
│ └───────┬───────┘ │
│ │ │
│ ▼ │
│ ┌───────────────┐ │
│ │ Decisión │──── ¿Coincidencia en lista negra? ────▶ Bloquear (403/444) │
│ │ │──── ¿Fallo en lista blanca? ────▶ Bloquear (403/444) │
│ └───────┬───────┘ │
│ │ Permitir │
│ ▼ │
│ ┌───────────────┐ │
│ │ Comprobación │──── ¿Coincidencia en ubicación? ────▶ Añadir a ipset│
│ │ de Honeypot│ │
│ └───────┬───────┘ │
│ │ │
│ ▼ │
│ Continuar a │
│ Manejador de Contenido │
│ │
├─────────────────────────────────────────────────────────────────────┤
│ MEMORIA COMPARTIDA │
│ ┌────────────────┬─────────────────┬─────────────────────────────┐ │
│ │ Estadísticas│ Caché LRU │ Cubos de Limitación de Tasa │ │
│ │ (contadores) │ (IP → Resultado)│ (IP → Contador de Solicitudes) │ │
│ └────────────────┴─────────────────┴─────────────────────────────┘ │
└─────────────────────────────────────────────────────────────────────┘
Disposición de la Memoria
| Componente | Ubicación | Propósito |
|---|---|---|
| Sesión libipset | Local por hilo | Sesión por trabajador para evitar bloqueos |
| Caché de búsqueda | Memoria compartida | Caché LRU de asignaciones IP→resultado |
| Cubos de limitación de tasa | Memoria compartida | Contadores de solicitudes por IP |
| Estadísticas | Memoria compartida | Contadores atómicos para métricas |
| ## |
📚 Ejemplos
Ejemplo 1: Lista Negra Básica
## Crear ipset
sudo ipset create blacklist hash:ip
sudo ipset add blacklist 1.2.3.4
server {
listen 80;
ipset_blacklist blacklist;
location / {
root /var/www/html;
}
}
Ejemplo 2: API con Limitación de Tasa
server {
listen 80;
# Limitación de tasa estricta para API
ipset_ratelimit rate=100 window=1m autoban=api_banned ban_time=3600;
# Solo permitir socios conocidos
ipset_whitelist api_partners;
ipset_status 401;
location /api/ {
proxy_pass http://backend;
}
}
Ejemplo 3: Stack de Seguridad Completo
server {
listen 80 default_server;
# Capa 1: Amenazas conocidas
ipset_blacklist malware_ips tor_exits datacenter_ranges;
ipset_status 444;
ipset_cache_ttl 5m;
# Capa 2: Limitación de tasa
ipset_ratelimit rate=60 window=1m autoban=ratelimited ban_time=1800;
# Capa 3: Desafío de bots
ipset_challenge on;
ipset_challenge_difficulty 2;
# Contenido real
location / {
root /var/www/html;
}
# Trampas de honeypot - devolver 404 (predeterminado) para parecer archivos faltantes
location ~ ^/(wp-admin|phpmyadmin|admin)\.php$ {
ipset_autoadd honeypot timeout=86400;
}
# Monitoreo
location = /metrics {
ipset_metrics;
allow 10.0.0.0/8;
deny all;
}
}
Ejemplo 4: Pruebas en Modo de Prueba
server {
listen 80;
# Probar nuevas reglas sin bloquear
ipset_blacklist new_threat_list;
ipset_dryrun on;
location / {
root /var/www/html;
}
}
Verifica los registros:
tail -f /var/log/nginx/error.log | grep "DRYRUN"
🔧 Solución de Problemas
Módulo no cargando
nginx: [emerg] dlopen() failed
Solución: Asegúrate de que NGINX fue construido con --with-compat y que el módulo fue construido contra la misma versión de NGINX.
ipset no encontrado
ipset: INVALID_SETNAME
Solución: Crea el ipset antes de iniciar NGINX:
sudo ipset create myset hash:ip
Permiso denegado
ipset: kernel error
Solución: El trabajador de NGINX necesita la capacidad CAP_NET_ADMIN:
sudo setcap cap_net_admin+ep /usr/sbin/nginx
Negaciones de SELinux (RHEL/CentOS/AlmaLinux)
SELinux está impidiendo que /usr/sbin/nginx acceda a getattr en el netlink_netfilter_socket
Solución: Instala el módulo de política de SELinux incluido:
cd selinux/
sudo ./install.sh
O manualmente:
## Verificar
semodule -l | grep nginx_ipset
La política permite que httpd_t (el dominio SELinux de NGINX) use sockets netlink_netfilter requeridos por libipset.
Alto uso de memoria
Solución: Reduce el TTL de caché o limita el tamaño de la caché en la configuración de memoria compartida.
La limitación de tasa no funciona
Solución: Asegúrate de que el ipset para auto-baneo exista y tenga soporte para tiempos de espera:
sudo ipset create ratelimited hash:ip timeout 3600
El registro muestra "matched=setname" pero la IP no está en el ipset
Este es un comportamiento esperado. El módulo informa lo que vio en el momento de la solicitud. Si verificas el ipset más tarde y no encuentras la IP:
-
Expiración del tiempo de espera: La IP fue añadida con un tiempo de espera y ha expirado desde entonces.
# Verifica si el conjunto soporta tiempos de espera ipset list setname | head -5 # Busca "timeout" en el encabezado -
Caché del módulo: El módulo almacena en caché las búsquedas (predeterminado 60s). Una IP recientemente eliminada puede seguir apareciendo como "coincidente".
# Desactivar temporalmente la caché para depuración (¡no para producción!) ipset_cache_ttl 0; -
La entrada fue eliminada: fail2ban, scripts o comandos manuales pueden haberla eliminado.
-
Problema de configuración de trampa: Si usas trampas de honeypot con
ipset_autoadd, bots legítimos pueden haber activado trampas. Verifica que tus ubicaciones de trampa no se superpongan con rutas legítimas de bots (como sitemaps, robots.txt). Usarobots.txtpara excluir rutas de trampa de rastreo.
autoadd falla con "result=4"
Esto significa que estás usando timeout=N en ipset_autoadd pero el ipset fue creado sin soporte para tiempos de espera.
Solución: Recréalo con soporte para tiempos de espera:
## Usando ipset directamente
sudo ipset destroy honeypot4
sudo ipset create honeypot4 hash:ip family inet timeout 86400
## Usando firewall-cmd (RHEL/CentOS/Amazon Linux)
sudo firewall-cmd --permanent --delete-ipset=honeypot4
sudo firewall-cmd --permanent --new-ipset=honeypot4 --type=hash:ip \
--option=family=inet --option=timeout=86400
sudo firewall-cmd --reload
📋 Requisitos
- NGINX ≥ 1.22 (construido con
--with-compat) - Kernel de Linux con soporte para ipset (módulo nf_tables o xt_set)
- Biblioteca libipset y encabezados de desarrollo
- Capacidades:
CAP_NET_ADMINpara operaciones de ipset
📜 Licencia
Este es un software propietario. Todos los derechos reservados.
Disponible exclusivamente a través del GetPageSpeed Premium Repository.
👤 Autor
Danila Vershinin
GetPageSpeed LLC
🆘 Soporte
- Honeypot v2.0 Usando ipset-access para auto-baneo de bots
- Soporte: Disponible para suscriptores premium
- Contacto: GetPageSpeed Support
Módulo de Acceso IPSet de NGINX
Un módulo premium de NGINX por GetPageSpeed LLC
www.getpagespeed.com