nftset-access: Bloqueo de IPs con cero latencia usando conjuntos nftables del kernel de Linux
Requiere el plan Pro (o superior) de la suscripción de GetPageSpeed NGINX Extras.
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-nftset-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-nftset-access
Habilita el módulo añadiendo lo siguiente en la parte superior de /etc/nginx/nginx.conf:
load_module modules/ngx_http_nftset_access.so;
Este documento describe nginx-module-nftset-access v3.0.0 lanzado el 14 de febrero de 2026.
Control de acceso basado en IP de nivel empresarial para NGINX usando conjuntos nftables 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.
Requisito de plan: Requiere el plan Pro de la suscripción de GetPageSpeed NGINX Extras.
✨ Características
Características Principales
| Característica | Descripción |
|---|---|
| Lista Blanca/Lista Negra | Permitir o denegar según la pertenencia al conjunto nftables |
| Múltiples conjuntos | Comprobar contra múltiples conjuntos nft en una directiva |
| Actualizaciones en vivo | Modificar conjuntos nft sin recargar NGINX |
| Códigos de estado personalizados | Devolver cualquier estado HTTP al bloquear |
| Soporte CIDR | Usar conjuntos de intervalos para rangos de red (por ejemplo, 192.168.1.0/24) |
Características de Rendimiento
| Característica | Descripción |
|---|---|
| Sesiones por hilo | Contextos libnftables locales por hilo eliminan la contención de bloqueos |
| Cache LRU | Caché en memoria compartida con TTL configurable |
| Tasas de aciertos de caché | Típicamente más del 95% de tasa de aciertos reduce 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 | El desafío de prueba de trabajo detiene bots automatizados |
| Trampas de Honeypot | Auto-bloquear IPs que acceden a URLs trampa |
| Tiempo de entrada | Expirar automáticamente entradas de la lista negra |
Características Operativas
| Característica | Descripción |
|---|---|
| Modo de prueba | Probar configuración sin bloquear |
| Fail-open/close | Controlar el comportamiento en errores de conjuntos nft |
| Métricas de Prometheus | Endpoint nativo /metrics para Grafana |
| Estadísticas JSON | API de estadísticas detalladas |
| Variables de NGINX | $nftset_result y $nftset_matched_set |
🚀 Inicio Rápido
1. Crear conjuntos nftables
# Crear una tabla (si no existe)
sudo nft add table ip filter
# Crear una lista negra con soporte de tiempo de espera
sudo nft add set ip filter bad_guys '{ type ipv4_addr; flags timeout; timeout 1d; }'
# Crear una lista de prohibición por limitación de tasa
sudo nft add set ip filter ratelimited '{ type ipv4_addr; flags timeout; timeout 30m; }'
# Crear una lista de trampas de honeypot
sudo nft add set ip filter honeypot '{ type ipv4_addr; flags timeout; timeout 1d; }'
# Crear una lista blanca con soporte CIDR
sudo nft add set ip filter trusted '{ type ipv4_addr; flags interval; }'
sudo nft add element ip filter trusted '{ 10.0.0.0/8, 192.168.0.0/16 }'
2. Configurar NGINX
load_module modules/ngx_http_nftset_access_module.so;
http {
server {
listen 80;
# Bloquear IPs malas conocidas (formato: tabla:nombre_conjunto)
nftset_blacklist filter:bad_guys;
# Limitar tasa: 100 solicitudes por minuto
nftset_ratelimit rate=100 window=60s autoban=filter:ratelimited;
# Tu contenido
location / {
root /var/www/html;
}
# Trampa de honeypot - devuelve 404 por defecto
location /wp-admin.php {
nftset_autoadd filter:honeypot timeout=86400;
}
# Endpoint de métricas
location /metrics {
nftset_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-nftset-access
Paso 4: Habilitar el Módulo
Añadir a /etc/nginx/nginx.conf antes de cualquier bloque http {}:
load_module modules/ngx_http_nftset_access_module.so;
Paso 5: Recargar NGINX
sudo nginx -t && sudo systemctl reload nginx
📖 Referencia de Configuración
Formato de Especificación de Conjunto
Todas las directivas que hacen referencia a conjuntos nftables utilizan el formato: tabla:nombre_conjunto
tabla— El nombre de la tabla nftables (por ejemplo,filter,firewalld)nombre_conjunto— El nombre del conjunto dentro de esa tabla
La familia IP (ip para IPv4, ip6 para IPv6) es detectada automáticamente desde la dirección IP del cliente.
Ejemplos:
nftset_blacklist filter:blocklist; # Cliente IPv4 → ip filter blocklist
# Cliente IPv6 → ip6 filter blocklist
nftset_whitelist filter:trusted;
nftset_autoadd filter:honeypot timeout=3600;
Control de Acceso
nftset_blacklist tabla:set1 [tabla:set2 ...]
Contexto: http, server
Predeterminado: —
Bloquea solicitudes si la IP del cliente aparece en cualquiera de los conjuntos nft listados. Se comprueban múltiples conjuntos en orden hasta que se encuentra una coincidencia.
# Conjunto único
nftset_blacklist filter:bad_guys;
# Múltiples conjuntos (lógica OR - bloqueado si está en CUALQUIER conjunto)
nftset_blacklist filter:spammers filter:hackers filter:tor_exits;
# Desactivar
nftset_blacklist off;
nftset_whitelist tabla:set1 [tabla:set2 ...]
Contexto: http, server
Predeterminado: —
Permite solicitudes solo si la IP del cliente aparece en al menos uno de los conjuntos nft listados. Todas las demás IPs son rechazadas.
# Solo permitir IPs de confianza
nftset_whitelist filter:trusted_partners filter:office_ips;
Importante: Las IPs en la lista blanca eluden todas las restricciones del módulo, incluyendo:
- Limitación de tasa (nftset_ratelimit)
- Desafíos de JavaScript (nftset_challenge)
Esto es útil para IPs de administradores que no deberían estar sujetas a límites de tasa o desafíos:
# Las IPs de administradores eluden la limitación de tasa y desafíos
nftset_whitelist filter:admin_ips;
nftset_ratelimit rate=100 window=1m autoban=filter:ratelimited ban_time=1800;
nftset_challenge on;
nftset_status código
Contexto: http, server
Predeterminado: 403
Código de estado HTTP devuelto cuando se bloquea una solicitud.
nftset_status 403; # Prohibido (predeterminado)
nftset_status 444; # Cerrar conexión sin respuesta (especial de NGINX)
nftset_status 429; # Demasiadas Solicitudes
nftset_status 503; # Servicio No Disponible
Caché y Rendimiento
nftset_cache_ttl tiempo
Contexto: http, server
Predeterminado: 60s
Cuánto tiempo almacenar en caché los resultados de búsqueda de conjuntos nft. Los resultados almacenados en caché evitan llamadas repetidas al kernel para la misma IP.
nftset_cache_ttl 30s; # 30 segundos
nftset_cache_ttl 5m; # 5 minutos
nftset_cache_ttl 1h; # 1 hora
Nota de depuración: Si eliminas una IP de un conjunto nft pero el módulo aún la informa como "coincidente", esto se debe a la caché. El resultado almacenado en caché expirará después del TTL configurado. Para un efecto inmediato durante las pruebas, puedes configurar temporalmente nftset_cache_ttl 0; para deshabilitar 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 el conjunto nft
- TTL más bajo = Más receptivo a cambios en el conjunto nft, pero más llamadas al kernel
- Recomendado: 30s a 5m para la mayoría de los casos de uso
nftset_fail_open on|off
Contexto: http, server
Predeterminado: off
Controla el comportamiento cuando falla una búsqueda de conjunto nft (por ejemplo, el conjunto no existe).
nftset_fail_open off; # Denegar en error (seguro, predeterminado)
nftset_fail_open on; # Permitir en error (disponible pero arriesgado)
nftset_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.
nftset_dryrun on; # Registrar pero no bloquear
Revisa los registros para mensajes como:
nftset: DRYRUN would block 1.2.3.4 (matched: filter:bad_guys)
Importante: Al usar las variables $nftset_result y $nftset_matched_set en modo dryrun, estos valores reflejan el estado en el momento en que se procesó la solicitud, no el estado actual del conjunto nft. Si revisas el conjunto nft manualmente más tarde y no encuentras la IP, las razones posibles incluyen:
- Expiración de tiempo de espera: La IP fue añadida con un tiempo de espera (por ejemplo,
timeout 1d) 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 conjunto nft 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 modo dryrun te muestra exactamente lo que vería la producción en el momento de la solicitud.
Limitación de Tasa
nftset_ratelimit parámetros
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 conjunto nft.
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=TABLE:SET |
No | conjunto nft para añadir violadores |
ban_time=N |
No | Segundos hasta auto-expirar (predeterminado: 3600) |
Ejemplos:
# Básico: 100 solicitudes por minuto
nftset_ratelimit rate=100;
# Con ventana personalizada: 1000 solicitudes por hora
nftset_ratelimit rate=1000 window=1h;
# Con auto-baneo: Añadir violadores al conjunto nft durante 30 minutos
nftset_ratelimit rate=60 window=1m autoban=filter:ratelimited ban_time=1800;
# Protección estricta de API
nftset_ratelimit rate=10 window=1s autoban=filter: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 restablece.
4. Si el contador excede rate, devuelve 429 Too Many Requests.
5. Si autoban está configurado, la IP se añade al conjunto nft especificado.
Nota: El estado de la limitación de tasa se almacena en memoria compartida y sobrevive a los reinicios de trabajadores.
Desafío de JavaScript
nftset_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.
nftset_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 (_nftset_verified).
4. Solicitudes subsiguientes con una cookie válida pasan.
5. La cookie expira después de 24 horas.
nftset_challenge_difficulty nivel
Contexto: http, server
Predeterminado: 2
Controla la dificultad del desafío (1-8). Más alto = 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 |
nftset_challenge on;
nftset_challenge_difficulty 3; # ~1 segundo de tiempo de resolución
Características de la Página de Desafío: - Diseño moderno y responsivo - Animación de carga - Retroalimentación de progreso - Redirección automática en caso de éxito - Sin dependencias externas
Auto-adición de Honeypot
nftset_autoadd tabla:nombre_conjunto [tabla:nombre_conjunto2 ...] [timeout=segundos] [status=código]
Contexto: server, location
Predeterminado: —
Añade automáticamente la IP del cliente a los conjuntos nft especificados 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 |
|---|---|---|
| tabla:nombre_conjunto | Sí | Conjunto nft objetivo (puede especificar múltiples) |
timeout=N |
No | Tiempo de espera de 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 {
nftset_autoadd filter:honeypot;
}
# Con tiempo de espera: Expirar automáticamente después de 24 horas
location /wp-admin.php {
nftset_autoadd filter:scanners timeout=86400;
}
# Devolver 403 Prohibido en lugar de 404
location /admin.php {
nftset_autoadd filter:honeypot timeout=86400 status=403;
}
# Añadir a múltiples conjuntos (IPv4 e IPv6)
location /trap {
nftset_autoadd filter:honeypot4 filter:honeypot6 timeout=86400;
}
Rutas Comunes de Honeypot:
# Trampas de WordPress - devolver 404 para parecer un archivo faltante
location ~ ^/(wp-admin\.php|wp-login\.php|xmlrpc\.php)$ {
nftset_autoadd filter:honeypot timeout=86400;
}
# Trampas de archivos de configuración - devolver 403 para simular acceso prohibido
location ~ ^/(\.env|config\.php|phpinfo\.php)$ {
nftset_autoadd filter:honeypot timeout=86400 status=403;
}
# Trampas de shell/exploit - severo, bloquear durante 1 semana
location ~ ^/(shell|cmd|eval|exec)\.php$ {
nftset_autoadd filter:malicious timeout=604800 status=403;
}
Nota: Cuando se añade automáticamente una IP, el módulo devuelve inmediatamente el código de estado HTTP especificado (predeterminado 404), evitando el procesamiento adicional de la solicitud. El keep-alive de la conexión también se desactiva para evitar más solicitudes en la misma conexión.
Observabilidad
nftset_stats
Contexto: location
Predeterminado: —
Habilita el endpoint de estadísticas JSON.
location = /_stats {
nftset_stats;
allow 127.0.0.1;
allow 10.0.0.0/8;
deny all;
}
Consulta JSON Stats API para el formato de respuesta.
nftset_metrics
Contexto: location
Predeterminado: —
Habilita el endpoint de métricas de Prometheus.
location = /metrics {
nftset_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 su uso en registros, encabezados o condicionales.
$nftset_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 |
$nftset_matched_set
Nombre del conjunto nft que coincidió (si lo hay), en formato tabla:nombre_conjunto. 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 conjunto nft. Si revisas el conjunto nft manualmente y no encuentras la IP: - La entrada puede haber expirado (los conjuntos nft admiten 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 '
'nftset_result="$nftset_result" '
'matched_set="$nftset_matched_set"';
access_log /var/log/nginx/security.log security;
Añadir encabezados para depuración:
add_header X-NFTSet-Result $nftset_result always;
add_header X-NFTSet-Matched $nftset_matched_set always;
Registro condicional:
# Solo registrar solicitudes bloqueadas
map $nftset_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_nftset_requests_total Total de solicitudes procesadas
# TYPE nginx_nftset_requests_total counter
nginx_nftset_requests_total{result="checked"} 1234567
nginx_nftset_requests_total{result="allowed"} 1234000
nginx_nftset_requests_total{result="blocked"} 500
nginx_nftset_requests_total{result="error"} 67
# HELP nginx_nftset_cache_total Operaciones de caché
# TYPE nginx_nftset_cache_total counter
nginx_nftset_cache_total{result="hit"} 1200000
nginx_nftset_cache_total{result="miss"} 34567
# HELP nginx_nftset_cache_entries Entradas de caché actuales
# TYPE nginx_nftset_cache_entries gauge
nginx_nftset_cache_entries 5432
# HELP nginx_nftset_autoadd_total Operaciones de auto-adición
# TYPE nginx_nftset_autoadd_total counter
nginx_nftset_autoadd_total{result="success"} 42
nginx_nftset_autoadd_total{result="failed"} 3
# HELP nginx_nftset_ratelimit_total Eventos de limitación de tasa
# TYPE nginx_nftset_ratelimit_total counter
nginx_nftset_ratelimit_total{action="triggered"} 156
nginx_nftset_ratelimit_total{action="autobanned"} 23
# HELP nginx_nftset_challenge_total Eventos de desafío
# TYPE nginx_nftset_challenge_total counter
nginx_nftset_challenge_total{result="issued"} 1000
nginx_nftset_challenge_total{result="passed"} 950
nginx_nftset_challenge_total{result="failed"} 50
# HELP nginx_nftset_uptime_seconds Tiempo de actividad del módulo
# TYPE nginx_nftset_uptime_seconds gauge
nginx_nftset_uptime_seconds 86400
Consultas del Dashboard de Grafana
Tasa de solicitudes por resultado:
rate(nginx_nftset_requests_total[5m])
Tasa de bloqueo:
rate(nginx_nftset_requests_total{result="blocked"}[5m])
Tasa de aciertos de caché:
rate(nginx_nftset_cache_total{result="hit"}[5m]) /
(rate(nginx_nftset_cache_total{result="hit"}[5m]) + rate(nginx_nftset_cache_total{result="miss"}[5m]))
Disparadores de limitación de tasa por minuto:
rate(nginx_nftset_ratelimit_total{action="triggered"}[1m]) * 60
📈 JSON Stats API
El endpoint /_stats devuelve estadísticas detalladas en formato JSON.
Formato de Respuesta
{
"version": "3.0.0",
"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 conjuntos nft |
cache.hits |
Aciertos de caché (evitar llamada al kernel) |
cache.misses |
Fallos de caché (requiere llamada al kernel) |
cache.entries |
Entradas de caché actuales |
cache.hit_rate |
Porcentaje de tasa de aciertos |
autoadd.success |
Adiciones exitosas de honeypot |
autoadd.failed |
Adiciones fallidas de honeypot |
ratelimit.triggered |
Violaciones de limitación de tasa |
ratelimit.autobanned |
IPs auto-agregadas a la lista de prohibición |
challenge.issued |
Páginas de desafío servidas |
challenge.passed |
Desafíos resueltos con éxito |
challenge.failed |
Fallos de desafío |
🏗️ Arquitectura
┌─────────────────────────────────────────────────────────────────────┐
│ FLUJO DE SOLICITUD │
├─────────────────────────────────────────────────────────────────────┤
│ │
│ Solicitud Entrante │
│ │ │
│ ▼ │
│ ┌───────────────┐ │
│ │ Verificar │──── Excedido? ────▶ 429 + Auto-baneo │
│ │ Limitación │ │
│ └───────┬───────┘ │
│ │ OK │
│ ▼ │
│ ┌───────────────┐ │
│ │ Verificar │──── ¿Sin cookie? ────▶ Servir rompecabezas JS │
│ │ Desafío │ │
│ └───────┬───────┘ │
│ │ Pasado │
│ ▼ │
│ ┌───────────────┐ ┌─────────────┐ │
│ │ Verificar │────▶│ ACIERTO │────▶ Usar resultado en caché│
│ └───────┬───────┘ └─────────────┘ │
│ │ FALLA │
│ ▼ │
│ ┌───────────────┐ │
│ │ Consulta nft │──── Contexto libnftables local por hilo │
│ │ (kernel) │ │
│ └───────┬───────┘ │
│ │ │
│ ▼ │
│ ┌───────────────┐ │
│ │ Almacenar en │ │
│ │ Caché │ │
│ └───────┬───────┘ │
│ │ │
│ ▼ │
│ ┌───────────────┐ │
│ │ Decisión │──── ¿Coincidencia en lista negra? ────▶ Bloquear (403/444) │
│ │ │──── ¿Falta en lista blanca? ────▶ Bloquear (403/444) │
│ └───────┬───────┘ │
│ │ Permitir │
│ ▼ │
│ ┌───────────────┐ │
│ │ Verificar │──── ¿Coincidencia en ubicación? ────▶ Añadir al conjunto nft │
│ │ Honeypot │ │
│ └───────┬───────┘ │
│ │ │
│ ▼ │
│ Continuar hacia │
│ Manejador de Contenido │
│ │
├─────────────────────────────────────────────────────────────────────┤
│ MEMORIA COMPARTIDA │
│ ┌────────────────┬─────────────────┬─────────────────────────────┐ │
│ │ Estadísticas │ Caché LRU │ Cubos de Limitación │ │
│ │ (contadores) │ (IP → Resultado) │ (IP → Contador de Solicitudes) │ │
│ └────────────────┴─────────────────┴─────────────────────────────┘ │
└─────────────────────────────────────────────────────────────────────┘
Diseño de Memoria
| Componente | Ubicación | Propósito |
|---|---|---|
| Contexto libnftables | Local por hilo | Contexto 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 tabla nft y conjunto
sudo nft add table ip filter
sudo nft add set ip filter blacklist '{ type ipv4_addr; }'
sudo nft add element ip filter blacklist '{ 1.2.3.4 }'
server {
listen 80;
nftset_blacklist filter:blacklist;
location / {
root /var/www/html;
}
}
Ejemplo 2: API con Limitación de Tasa
server {
listen 80;
# Limitación de tasa estricta para API
nftset_ratelimit rate=100 window=1m autoban=filter:api_banned ban_time=3600;
# Solo permitir socios conocidos
nftset_whitelist filter:api_partners;
nftset_status 401;
location /api/ {
proxy_pass http://backend;
}
}
Ejemplo 3: Stack de Seguridad Completo
server {
listen 80 default_server;
# Capa 1: Amenazas conocidas
nftset_blacklist filter:malware_ips filter:tor_exits filter:datacenter_ranges;
nftset_status 444;
nftset_cache_ttl 5m;
# Capa 2: Limitación de tasa
nftset_ratelimit rate=60 window=1m autoban=filter:ratelimited ban_time=1800;
# Capa 3: Desafío de bot
nftset_challenge on;
nftset_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$ {
nftset_autoadd filter:honeypot timeout=86400;
}
# Monitoreo
location = /metrics {
nftset_metrics;
allow 10.0.0.0/8;
deny all;
}
}
Ejemplo 4: Pruebas en Modo de Prueba
server {
listen 80;
# Probar nuevas reglas sin bloquear
nftset_blacklist filter:new_threat_list;
nftset_dryrun on;
location / {
root /var/www/html;
}
}
Revisa los registros:
tail -f /var/log/nginx/error.log | grep "DRYRUN"
Ejemplo 5: Lista Blanca CIDR (Rangos de Red)
# Crear conjunto de intervalos para rangos CIDR
sudo nft add table ip filter
sudo nft add set ip filter trusted '{ type ipv4_addr; flags interval; }'
sudo nft add element ip filter trusted '{ 192.168.1.0/24, 10.0.0.0/8 }'
# Versión IPv6
sudo nft add table ip6 filter
sudo nft add set ip6 filter trusted6 '{ type ipv6_addr; flags interval; }'
sudo nft add element ip6 filter trusted6 '{ 2001:db8::/32 }'
server {
listen 80;
# Lista blanca de redes enteras
nftset_whitelist filter:trusted;
location / {
root /var/www/html;
}
}
🔧 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.
Conjunto nft no encontrado
nftset: set 'filter:myset' does not exist
Solución: Crea la tabla nft y el conjunto antes de iniciar NGINX:
sudo nft add table ip filter
sudo nft add set ip filter myset '{ type ipv4_addr; }'
TIP: Lista los conjuntos disponibles con:
nft list sets
Permiso denegado
nftset: kernel error
Solución: El trabajador de NGINX necesita la capacidad CAP_NET_ADMIN:
sudo setcap cap_net_admin+ep /usr/sbin/nginx
Denegaciones de SELinux (RHEL/CentOS/AlmaLinux)
SELinux is preventing /usr/sbin/nginx from using netlink_netfilter_socket
Solución: Instala el módulo de política SELinux incluido:
cd selinux/
sudo ./install.sh
O manualmente:
# Verificar
semodule -l | grep nginx_nftset
La política permite que httpd_t (el dominio SELinux de NGINX) use sockets netlink_netfilter requeridos por libnftables.
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 conjunto nft para auto-baneo exista y tenga soporte de tiempo de espera:
sudo nft add table ip filter
sudo nft add set ip filter ratelimited '{ type ipv4_addr; flags timeout; timeout 1h; }'
El registro muestra "matched=table:setname" pero la IP no está en el conjunto nft
Este es un comportamiento esperado. El módulo informa lo que vio en el momento de la solicitud. Si revisas el conjunto nft más tarde y no encuentras la IP:
-
Expiración de tiempo de espera: La IP fue añadida con un tiempo de espera y ha expirado desde entonces.
# Verificar banderas del conjunto nft list set ip filter setname # Buscar "flags timeout" en la salida -
Caché del módulo: El módulo almacena en caché las búsquedas (predeterminado 60s). Una IP recientemente eliminada puede seguir apareciendo como "coincidente".
# Deshabilitar temporalmente la caché para depuración (¡no para producción!) nftset_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
nftset_autoadd, bots legítimos pueden haber activado trampas. Verifica que tus ubicaciones de trampa no se superpongan con rutas legítimas (como sitemaps, robots.txt). Usarobots.txtpara excluir rutas de trampa de la indexación.
autoadd falla con error de tiempo de espera
Esto significa que estás usando timeout=N en nftset_autoadd pero el conjunto nft fue creado sin soporte de tiempo de espera.
Solución: Recrea el conjunto nft con soporte de tiempo de espera:
# Eliminar y recrear con la bandera de tiempo de espera
sudo nft delete set ip filter honeypot
sudo nft add set ip filter honeypot '{ type ipv4_addr; flags timeout; timeout 1d; }'
🔄 Migración desde ipset-access
Si estás migrando desde el antiguo ngx_http_ipset_access_module, sigue estos pasos:
1. Convertir ipsets a conjuntos nft
# Antiguo ipset
ipset create bad_guys hash:ip timeout 86400
# Nuevo conjunto nft equivalente
nft add table ip filter
nft add set ip filter bad_guys '{ type ipv4_addr; flags timeout; timeout 1d; }'
# Para rangos CIDR (hash:net → bandera de intervalo)
# Antiguo: ipset create networks hash:net
# Nuevo:
nft add set ip filter networks '{ type ipv4_addr; flags interval; }'
2. Actualizar la configuración de NGINX
| Antiguo (ipset) | Nuevo (nftset) |
|---|---|
ipset_blacklist bad_guys; |
nftset_blacklist filter:bad_guys; |
ipset_whitelist trusted; |
nftset_whitelist filter:trusted; |
ipset_autoadd honeypot timeout=3600; |
nftset_autoadd filter:honeypot timeout=3600; |
ipset_ratelimit rate=100 autoban=ratelimited; |
nftset_ratelimit rate=100 autoban=filter:ratelimited; |
ipset_challenge on; |
nftset_challenge on; |
ipset_challenge_difficulty 3; |
nftset_challenge_difficulty 3; |
ipset_dryrun on; |
nftset_dryrun on; |
ipset_fail_open on; |
nftset_fail_open on; |
ipset_cache_ttl 60s; |
nftset_cache_ttl 60s; |
ipset_status 403; |
nftset_status 403; |
ipset_stats; |
nftset_stats; |
ipset_metrics; |
nftset_metrics; |
$ipset_result |
$nftset_result |
$ipset_matched_set |
$nftset_matched_set |
3. Actualizar formatos de registro
# Antiguo
log_format security '... ipset_result="$ipset_result" matched_set="$ipset_matched_set"';
# Nuevo
log_format security '... nftset_result="$nftset_result" matched_set="$nftset_matched_set"';
4. Actualizar consultas de Prometheus/Grafana
| Métrica Antigua | Nueva Métrica |
|---|---|
nginx_ipset_requests_total |
nginx_nftset_requests_total |
nginx_ipset_cache_total |
nginx_nftset_cache_total |
nginx_ipset_cache_entries |
nginx_nftset_cache_entries |
nginx_ipset_autoadd_total |
nginx_nftset_autoadd_total |
nginx_ipset_ratelimit_total |
nginx_nftset_ratelimit_total |
nginx_ipset_challenge_total |
nginx_nftset_challenge_total |
nginx_ipset_uptime_seconds |
nginx_nftset_uptime_seconds |
5. Diferencias clave
| Característica | ipset-access | nftset-access |
|---|---|---|
| Backend | libipset (ipsets del kernel) | libnftables (nftables) |
| Formato de conjunto | setname |
table:setname |
| Conjuntos CIDR | tipo hash:net |
bandera flags interval |
| Familia | Especificada en el tipo de conjunto | Detectada automáticamente desde la IP del cliente |
| firewalld | solo backend de iptables | compatible con backend de nftables |
¿Por qué migrar?
- Compatibilidad con RHEL 9/Rocky 9: firewalld utiliza por defecto el backend de nftables.
- Soporte para kernels modernos: nftables es el futuro del firewalling en Linux.
- Gestión unificada: Usa comandos
nfttanto para firewall como para control de acceso. - Mejor soporte CIDR: Los conjuntos de intervalos manejan rangos de red de manera eficiente.
📋 Requisitos
- NGINX ≥ 1.22 (construido con
--with-compat) - Kernel de Linux con soporte para nftables
- Biblioteca y encabezados de desarrollo de libnftables
- Capacidades:
CAP_NET_ADMINpara operaciones de nftables
📜 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 nftset-access para auto-baneo de bots
- Soporte: Disponible para suscriptores premium
- Contacto: GetPageSpeed Support
Módulo de Acceso NFTSet de NGINX
Un módulo premium de NGINX de GetPageSpeed LLC
www.getpagespeed.com