nftset-access: Bloqueio de IP com zero latência usando conjuntos nftables do kernel Linux
Requer o plano Pro (ou superior) da assinatura GetPageSpeed NGINX Extras.
Instalação
Você pode instalar este módulo em qualquer distribuição baseada em RHEL, incluindo, mas não se limitando a:
- RedHat Enterprise Linux 7, 8, 9 e 10
- CentOS 7, 8, 9
- AlmaLinux 8, 9
- Rocky Linux 8, 9
- Amazon Linux 2 e 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
Ative o módulo adicionando o seguinte no topo de /etc/nginx/nginx.conf:
load_module modules/ngx_http_nftset_access.so;
Este documento descreve nginx-module-nftset-access v3.0.0 lançado em 14 de fevereiro de 2026.
Controle de acesso baseado em IP de nível empresarial para NGINX usando conjuntos nftables do Linux. Bloqueie ameaças, limite a taxa de abusadores, desafie bots e proteja sua infraestrutura.
⚠️ Software Comercial Este é um módulo premium de código fechado disponível exclusivamente através do Repositório GetPageSpeed.
Requisito de plano: Requer o plano Pro da assinatura GetPageSpeed NGINX Extras.
✨ Recursos
Recursos Principais
| Recurso | Descrição |
|---|---|
| Lista Branca/Lista Negra | Permitir ou negar com base na associação ao conjunto nftables |
| Múltiplos conjuntos | Verificar contra múltiplos conjuntos nft em uma diretiva |
| Atualizações ao vivo | Modificar conjuntos nft sem recarregar o NGINX |
| Códigos de status personalizados | Retornar qualquer status HTTP ao bloquear |
| Suporte a CIDR | Usar conjuntos de intervalo para faixas de rede (ex: 192.168.1.0/24) |
Recursos de Performance
| Recurso | Descrição |
|---|---|
| Sessões por thread | Contextos libnftables locais por thread eliminam contenção de bloqueio |
| Cache LRU | Cache de memória compartilhada com TTL configurável |
| Taxas de acerto de cache | Taxa de acerto tipicamente acima de 95% reduz chamadas ao kernel |
Recursos de Segurança
| Recurso | Descrição |
|---|---|
| Limitação de taxa | Limitar solicitações por IP com janelas configuráveis |
| Banimento automático | Adicionar automaticamente violadores de limite de taxa à lista negra |
| Desafio JS | Desafio de prova de trabalho impede bots automatizados |
| Armadilhas Honeypot | Auto-bloquear IPs que acessam URLs de armadilha |
| Tempo limite de entrada | Expiração automática de entradas na lista negra |
Recursos Operacionais
| Recurso | Descrição |
|---|---|
| Modo de teste | Testar configuração sem bloquear |
| Falha aberta/fechada | Controlar comportamento em erros de conjunto nft |
| Métricas Prometheus | Endpoint nativo /metrics para Grafana |
| Estatísticas JSON | API de estatísticas detalhadas |
| Variáveis NGINX | $nftset_result e $nftset_matched_set |
🚀 Início Rápido
1. Criar conjuntos nftables
# Criar uma tabela (se não existir)
sudo nft add table ip filter
# Criar uma lista negra com suporte a tempo limite
sudo nft add set ip filter bad_guys '{ type ipv4_addr; flags timeout; timeout 1d; }'
# Criar uma lista de banimento por limite de taxa
sudo nft add set ip filter ratelimited '{ type ipv4_addr; flags timeout; timeout 30m; }'
# Criar uma lista de armadilha honeypot
sudo nft add set ip filter honeypot '{ type ipv4_addr; flags timeout; timeout 1d; }'
# Criar uma lista branca com suporte a 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 ruins conhecidos (formato: tabela:nome_do_conjunto)
nftset_blacklist filter:bad_guys;
# Limitar taxa: 100 solicitações por minuto
nftset_ratelimit rate=100 window=60s autoban=filter:ratelimited;
# Seu conteúdo
location / {
root /var/www/html;
}
# Armadilha honeypot - retorna 404 por padrão
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. Testar e recarregar
sudo nginx -t && sudo nginx -s reload
📦 Instalação
Este módulo está disponível exclusivamente através do Repositório Premium GetPageSpeed.
Passo 1: Inscrever-se no Repositório GetPageSpeed
Visite Inscrição no Repositório GetPageSpeed para obter acesso.
Passo 2: Instalar o Repositório
# RHEL/CentOS/Rocky/Alma Linux 8+
sudo dnf install https://extras.getpagespeed.com/release-latest.rpm
Passo 3: Instalar o Módulo
sudo dnf install nginx-module-nftset-access
Passo 4: Ativar o Módulo
Adicione a /etc/nginx/nginx.conf antes de qualquer bloco http {}:
load_module modules/ngx_http_nftset_access_module.so;
Passo 5: Recarregar o NGINX
sudo nginx -t && sudo systemctl reload nginx
📖 Referência de Configuração
Formato de Especificação do Conjunto
Todas as diretivas que referenciam conjuntos nftables usam o formato: tabela:nome_do_conjunto
tabela— O nome da tabela nftables (ex:filter,firewalld)nome_do_conjunto— O nome do conjunto dentro dessa tabela
A família IP (ip para IPv4, ip6 para IPv6) é auto-detectada a partir do endereço IP do cliente.
Exemplos:
nftset_blacklist filter:blocklist; # Cliente IPv4 → ip filter blocklist
# Cliente IPv6 → ip6 filter blocklist
nftset_whitelist filter:trusted;
nftset_autoadd filter:honeypot timeout=3600;
Controle de Acesso
nftset_blacklist tabela:set1 [tabela:set2 ...]
Contexto: http, server
Padrão: —
Bloqueia solicitações se o IP do cliente aparecer em qualquer dos conjuntos nft listados. Múltiplos conjuntos são verificados em ordem até que uma correspondência seja encontrada.
# Conjunto único
nftset_blacklist filter:bad_guys;
# Múltiplos conjuntos (lógica OR - bloqueado se em QUALQUER conjunto)
nftset_blacklist filter:spammers filter:hackers filter:tor_exits;
# Desativar
nftset_blacklist off;
nftset_whitelist tabela:set1 [tabela:set2 ...]
Contexto: http, server
Padrão: —
Permite solicitações apenas se o IP do cliente aparecer em pelo menos um dos conjuntos nft listados. Todos os outros IPs são rejeitados.
# Permitir apenas IPs confiáveis
nftset_whitelist filter:trusted_partners filter:office_ips;
Importante: IPs na lista branca ignoram todas as restrições do módulo, incluindo:
- Limitação de taxa (nftset_ratelimit)
- Desafios JavaScript (nftset_challenge)
Isso é útil para IPs de administradores que não devem estar sujeitos a limites de taxa ou desafios:
# IPs de administradores ignoram limitação de taxa e desafios
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
Padrão: 403
Código de status HTTP retornado quando uma solicitação é bloqueada.
nftset_status 403; # Proibido (padrão)
nftset_status 444; # Fechar conexão sem resposta (especial do NGINX)
nftset_status 429; # Muitas Solicitações
nftset_status 503; # Serviço Indisponível
Cache & Performance
nftset_cache_ttl tempo
Contexto: http, server
Padrão: 60s
Quanto tempo armazenar os resultados da consulta ao conjunto nft. Resultados armazenados evitam chamadas repetidas ao kernel para o mesmo IP.
nftset_cache_ttl 30s; # 30 segundos
nftset_cache_ttl 5m; # 5 minutos
nftset_cache_ttl 1h; # 1 hora
Nota de Depuração: Se você remover um IP de um conjunto nft, mas o módulo ainda relatar como "correspondido", isso se deve ao cache. O resultado armazenado expirará após o TTL configurado. Para efeito imediato durante os testes, você pode definir temporariamente nftset_cache_ttl 0; para desabilitar o cache (não recomendado para produção devido ao impacto na performance).
Impacto na Performance:
- TTL mais alto = Melhor performance, mas mais lento para refletir mudanças no conjunto nft
- TTL mais baixo = Mais responsivo a mudanças no conjunto nft, mas mais chamadas ao kernel
- Recomendado: 30s a 5m para a maioria dos casos de uso
nftset_fail_open on|off
Contexto: http, server
Padrão: off
Controla o comportamento quando uma consulta ao conjunto nft falha (ex: conjunto não existe).
nftset_fail_open off; # Negar em caso de erro (seguro, padrão)
nftset_fail_open on; # Permitir em caso de erro (disponível, mas arriscado)
nftset_dryrun on|off
Contexto: http, server
Padrão: off
Quando ativado, registra o que seria bloqueado, mas não bloqueia realmente. Perfeito para testar novas regras em produção.
nftset_dryrun on; # Registrar, mas não bloquear
Verifique os logs para mensagens como:
nftset: DRYRUN would block 1.2.3.4 (matched: filter:bad_guys)
Importante: Ao usar as variáveis $nftset_result e $nftset_matched_set com o modo dryrun, esses valores refletem o estado no momento em que a solicitação foi processada—não o estado atual do conjunto nft. Se você verificar o conjunto nft manualmente depois e não encontrar o IP, possíveis razões incluem:
- Expiração do tempo limite: O IP foi adicionado com um tempo limite (ex:
timeout 1d) e já expirou - Atraso de cache: O módulo armazena resultados de consulta (padrão 60s). Uma entrada removida do conjunto nft pode ainda aparecer como "correspondida" até que o cache expire
- Remoção manual: Alguém ou algo (fail2ban, scripts) removeu a entrada
Esse é um comportamento esperado—o dryrun mostra exatamente o que a produção veria no momento da solicitação.
Limitação de Taxa
nftset_ratelimit parâmetros
Contexto: http, server
Padrão: —
Limita solicitações por IP dentro de uma janela de tempo. Pode adicionar automaticamente violadores a um conjunto nft.
Parâmetros:
| Parâmetro | Necessário | Descrição |
|---|---|---|
rate=N |
Sim | Máximo de solicitações por janela |
window=TIME |
Não | Janela de tempo (padrão: 60s) |
autoban=TABLE:SET |
Não | conjunto nft para adicionar violadores |
ban_time=N |
Não | Segundos até expirar automaticamente (padrão: 3600) |
Exemplos:
# Básico: 100 solicitações por minuto
nftset_ratelimit rate=100;
# Com janela personalizada: 1000 solicitações por hora
nftset_ratelimit rate=1000 window=1h;
# Com auto-ban: Adicionar violadores ao conjunto nft por 30 minutos
nftset_ratelimit rate=60 window=1m autoban=filter:ratelimited ban_time=1800;
# Proteção de API rigorosa
nftset_ratelimit rate=10 window=1s autoban=filter:api_abusers ban_time=3600;
Como funciona:
1. Cada IP recebe um contador de solicitações e hora de início da janela
2. O contador é incrementado a cada solicitação
3. Quando a janela expira, o contador é redefinido
4. Se o contador exceder rate, retorna 429 Muitas Solicitações
5. Se autoban estiver definido, o IP é adicionado ao conjunto nft especificado
Nota: O estado de limitação de taxa é armazenado em memória compartilhada e sobrevive a reinicializações de worker.
Desafio JavaScript
nftset_challenge on|off
Contexto: http, server
Padrão: off
Ativa o modo de desafio JavaScript. Os navegadores devem resolver um quebra-cabeça de prova de trabalho para acessar o site. Eficaz contra bots automatizados e scrapers.
nftset_challenge on;
Como funciona:
1. A primeira solicitação recebe uma página de desafio (HTTP 503)
2. O navegador executa JavaScript que resolve um quebra-cabeça de hash
3. A solução é armazenada em um cookie (_nftset_verified)
4. Solicitações subsequentes com cookie válido passam
5. O cookie expira após 24 horas
nftset_challenge_difficulty nível
Contexto: http, server
Padrão: 2
Controla a dificuldade do desafio (1-8). Mais alto = mais tempo para resolver.
| Nível | Tempo Aproximado de Resolução |
|---|---|
| 1 | ~100ms |
| 2 | ~500ms (padrão) |
| 3 | ~1 segundo |
| 4 | ~2 segundos |
| 5 | ~5 segundos |
| 6+ | ~10+ segundos |
nftset_challenge on;
nftset_challenge_difficulty 3; # ~1 segundo de tempo de resolução
Recursos da Página de Desafio: - Design moderno e responsivo - Spinner de carregamento animado - Feedback de progresso - Redirecionamento automático em caso de sucesso - Sem dependências externas
Auto-adicionar Honeypot
nftset_autoadd tabela:nome_do_conjunto [tabela:nome_do_conjunto2 ...] [timeout=segundos] [status=código]
Contexto: server, location
Padrão: —
Adiciona automaticamente o IP do cliente aos conjuntos nft especificados quando a localização é acessada e retorna um código de status HTTP. Perfeito para armadilhas honeypot.
Parâmetros:
| Parâmetro | Necessário | Descrição |
|---|---|---|
| tabela:nome_do_conjunto | Sim | Conjunto nft alvo (pode especificar múltiplos) |
timeout=N |
Não | Tempo limite da entrada em segundos |
status=N |
Não | Código de status HTTP a retornar (padrão: 404) |
Exemplos:
# Básico: Adicionar ao conjunto honeypot e retornar 404 (padrão)
location /config.php {
nftset_autoadd filter:honeypot;
}
# Com tempo limite: Expira automaticamente após 24 horas
location /wp-admin.php {
nftset_autoadd filter:scanners timeout=86400;
}
# Retornar 403 Proibido em vez de 404
location /admin.php {
nftset_autoadd filter:honeypot timeout=86400 status=403;
}
# Adicionar a múltiplos conjuntos (IPv4 e IPv6)
location /trap {
nftset_autoadd filter:honeypot4 filter:honeypot6 timeout=86400;
}
Caminhos Comuns de Honeypot:
# Armadilhas do WordPress - retornar 404 para parecer um arquivo ausente
location ~ ^/(wp-admin\.php|wp-login\.php|xmlrpc\.php)$ {
nftset_autoadd filter:honeypot timeout=86400;
}
# Armadilhas de arquivos de configuração - retornar 403 para simular acesso proibido
location ~ ^/(\.env|config\.php|phpinfo\.php)$ {
nftset_autoadd filter:honeypot timeout=86400 status=403;
}
# Armadilhas de shell/exploit - severas, bloquear por 1 semana
location ~ ^/(shell|cmd|eval|exec)\.php$ {
nftset_autoadd filter:malicious timeout=604800 status=403;
}
Nota: Quando um IP é auto-adicionado, o módulo retorna imediatamente o código de status HTTP especificado (padrão 404), impedindo o processamento de solicitações adicionais. O keep-alive da conexão também é desativado para evitar mais solicitações na mesma conexão.
Observabilidade
nftset_stats
Contexto: location
Padrão: —
Ativa o endpoint de estatísticas JSON.
location = /_stats {
nftset_stats;
allow 127.0.0.1;
allow 10.0.0.0/8;
deny all;
}
Veja API de Estatísticas JSON para o formato de resposta.
nftset_metrics
Contexto: location
Padrão: —
Ativa o endpoint de métricas Prometheus.
location = /metrics {
nftset_metrics;
allow 127.0.0.1;
allow 10.0.0.0/8;
deny all;
}
Veja Métricas Prometheus para as métricas disponíveis.
📝 Variáveis NGINX
O módulo expõe duas variáveis para uso em logs, cabeçalhos ou condicionais.
$nftset_result
A decisão de acesso tomada para esta solicitação.
| Valor | Descrição |
|---|---|
allow |
Solicitação permitida |
deny |
Solicitação bloqueada |
dryrun |
Seria bloqueado (modo de teste) |
ratelimited |
Limite de taxa excedido |
challenged |
Página de desafio servida |
$nftset_matched_set
Nome do conjunto nft que correspondeu (se houver), no formato tabela:nome_do_conjunto. Vazio se não houver correspondência.
Nota: Esta variável reflete o estado de correspondência no momento da solicitação, não o estado atual do conjunto nft. Se você verificar o conjunto nft manualmente e não encontrar o IP: - A entrada pode ter expirado (conjuntos nft suportam tempos limites por entrada) - O cache do módulo (padrão 60s) pode mostrar uma entrada recentemente removida como ainda correspondente - Algo pode ter removido a entrada após a solicitação ser processada
Exemplos de Uso
Log de acesso 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;
Adicionar cabeçalhos para depuração:
add_header X-NFTSet-Result $nftset_result always;
add_header X-NFTSet-Matched $nftset_matched_set always;
Registro condicional:
# Registrar apenas solicitações bloqueadas
map $nftset_result $loggable {
"deny" 1;
default 0;
}
access_log /var/log/nginx/blocked.log combined if=$loggable;
📊 Métricas Prometheus
O endpoint /metrics retorna métricas no formato de exposição do Prometheus.
Métricas Disponíveis
# HELP nginx_nftset_requests_total Total de solicitações processadas
# 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 Operações de cache
# 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 cache atuais
# TYPE nginx_nftset_cache_entries gauge
nginx_nftset_cache_entries 5432
# HELP nginx_nftset_autoadd_total Operações de auto-adicionar
# 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 limitação de taxa
# 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 desafio
# 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 Tempo de atividade do módulo
# TYPE nginx_nftset_uptime_seconds gauge
nginx_nftset_uptime_seconds 86400
Consultas do Dashboard Grafana
Taxa de solicitações por resultado:
rate(nginx_nftset_requests_total[5m])
Taxa de bloqueio:
rate(nginx_nftset_requests_total{result="blocked"}[5m])
Taxa de acerto de cache:
rate(nginx_nftset_cache_total{result="hit"}[5m]) /
(rate(nginx_nftset_cache_total{result="hit"}[5m]) + rate(nginx_nftset_cache_total{result="miss"}[5m]))
Gatilhos de limitação de taxa por minuto:
rate(nginx_nftset_ratelimit_total{action="triggered"}[1m]) * 60
📈 API de Estatísticas JSON
O endpoint /_stats retorna estatísticas detalhadas em formato JSON.
Formato de Resposta
{
"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
}
}
Descrições dos Campos
| Campo | Descrição |
|---|---|
version |
Versão do módulo |
uptime_seconds |
Segundos desde que o módulo foi carregado |
requests.checked |
Total de solicitações processadas |
requests.allowed |
Solicitações que passaram |
requests.blocked |
Solicitações que foram bloqueadas |
requests.errors |
Erros de consulta ao conjunto nft |
cache.hits |
Acertos de cache (evitou chamada ao kernel) |
cache.misses |
Erros de cache (chamada ao kernel necessária) |
cache.entries |
Entradas atualmente armazenadas em cache |
cache.hit_rate |
Percentual de taxa de acerto |
autoadd.success |
Adições de honeypot bem-sucedidas |
autoadd.failed |
Adições de honeypot falhadas |
ratelimit.triggered |
Violações de limite de taxa |
ratelimit.autobanned |
IPs auto-adicionados à lista de banimento |
challenge.issued |
Páginas de desafio servidas |
challenge.passed |
Desafios resolvidos com sucesso |
challenge.failed |
Falhas de desafio |
🏗️ Arquitetura
┌─────────────────────────────────────────────────────────────────────┐
│ FLUXO DE SOLICITAÇÃO │
├─────────────────────────────────────────────────────────────────────┤
│ │
│ Solicitação de Entrada │
│ │ │
│ ▼ │
│ ┌───────────────┐ │
│ │ Limite de │──── Excedido? ────▶ 429 + Auto-ban │
│ │ Taxa │ │
│ └───────┬───────┘ │
│ │ OK │
│ ▼ │
│ ┌───────────────┐ │
│ │ Desafio │──── Sem cookie? ────▶ Servir quebra-cabeça JS │
│ │ │ │
│ └───────┬───────┘ │
│ │ Aprovado │
│ ▼ │
│ ┌───────────────┐ ┌─────────────┐ │
│ │ Verificação │────▶│ ACERTO │────▶ Usar resultado em cache│
│ └───────┬───────┘ └─────────────┘ │
│ │ ERRO │
│ ▼ │
│ ┌───────────────┐ │
│ │ Consulta nft │──── Contexto libnftables local por thread │
│ │ (kernel) │ │
│ └───────┬───────┘ │
│ │ │
│ ▼ │
│ ┌───────────────┐ │
│ │ Armazenar em │ │
│ │ Cache │ │
│ └───────┬───────┘ │
│ │ │
│ ▼ │
│ ┌───────────────┐ │
│ │ Decisão │──── Correspondência na lista negra? ────▶ Bloquear (403/444) │
│ │ │──── Falta na lista branca? ────▶ Bloquear (403/444) │
│ └───────┬───────┘ │
│ │ Permitir │
│ ▼ │
│ ┌───────────────┐ │
│ │ Honeypot │──── Correspondência na localização? ────▶ Adicionar ao conjunto nft │
│ │ Verificação │ │
│ └───────┬───────┘ │
│ │ │
│ ▼ │
│ Continuar para │
│ Manipulador de Conteúdo │
│ │
├─────────────────────────────────────────────────────────────────────┤
│ MEMÓRIA COMPARTILHADA │
│ ┌────────────────┬─────────────────┬─────────────────────────────┐ │
│ │ Estatísticas│ Cache LRU │ Baldes de Limitação de Taxa│ │
│ │ (contadores) │ (IP → Resultado)│ (IP → Contador de Solicitações)│ │
│ └────────────────┴─────────────────┴─────────────────────────────┘ │
└─────────────────────────────────────────────────────────────────────┘
Layout de Memória
| Componente | Localização | Propósito |
|---|---|---|
| Contexto libnftables | Local por thread | Contexto por worker para evitar bloqueios |
| Cache de consulta | Memória compartilhada | Cache LRU de mapeamentos IP→resultado |
| Baldes de limitação de taxa | Memória compartilhada | Contadores de solicitações por IP |
| Estatísticas | Memória compartilhada | Contadores atômicos para métricas |
📚 Exemplos
Exemplo 1: Lista Negra Básica
# Criar tabela nft e 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;
}
}
Exemplo 2: API com Limitação de Taxa
server {
listen 80;
# Limitação de taxa rigorosa para API
nftset_ratelimit rate=100 window=1m autoban=filter:api_banned ban_time=3600;
# Permitir apenas parceiros conhecidos
nftset_whitelist filter:api_partners;
nftset_status 401;
location /api/ {
proxy_pass http://backend;
}
}
Exemplo 3: Pilha de Segurança Completa
server {
listen 80 default_server;
# Camada 1: Ameaças conhecidas
nftset_blacklist filter:malware_ips filter:tor_exits filter:datacenter_ranges;
nftset_status 444;
nftset_cache_ttl 5m;
# Camada 2: Limitação de taxa
nftset_ratelimit rate=60 window=1m autoban=filter:ratelimited ban_time=1800;
# Camada 3: Desafio para bots
nftset_challenge on;
nftset_challenge_difficulty 2;
# Conteúdo real
location / {
root /var/www/html;
}
# Armadilhas honeypot - retornar 404 (padrão) para parecer arquivos ausentes
location ~ ^/(wp-admin|phpmyadmin|admin)\.php$ {
nftset_autoadd filter:honeypot timeout=86400;
}
# Monitoramento
location = /metrics {
nftset_metrics;
allow 10.0.0.0/8;
deny all;
}
}
Exemplo 4: Teste de Modo Dry-run
server {
listen 80;
# Testar novas regras sem bloquear
nftset_blacklist filter:new_threat_list;
nftset_dryrun on;
location / {
root /var/www/html;
}
}
Verifique os logs:
tail -f /var/log/nginx/error.log | grep "DRYRUN"
Exemplo 5: Lista Branca CIDR (Faixas de Rede)
# Criar conjunto de intervalo para faixas 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 }'
# Versão 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 branca de redes inteiras
nftset_whitelist filter:trusted;
location / {
root /var/www/html;
}
}
🔧 Resolução de Problemas
Módulo não carregando
nginx: [emerg] dlopen() failed
Solução: Certifique-se de que o NGINX foi compilado com --with-compat e que o módulo foi construído contra a mesma versão do NGINX.
conjunto nft não encontrado
nftset: set 'filter:myset' does not exist
Solução: Crie a tabela nft e o conjunto antes de iniciar o NGINX:
sudo nft add table ip filter
sudo nft add set ip filter myset '{ type ipv4_addr; }'
DICA: Liste os conjuntos disponíveis com:
nft list sets
Permissão negada
nftset: kernel error
Solução: O worker do NGINX precisa da capacidade CAP_NET_ADMIN:
sudo setcap cap_net_admin+ep /usr/sbin/nginx
Negativas do SELinux (RHEL/CentOS/AlmaLinux)
SELinux is preventing /usr/sbin/nginx from using netlink_netfilter_socket
Solução: Instale o módulo de política SELinux incluído:
cd selinux/
sudo ./install.sh
Ou manualmente:
# Verificar
semodule -l | grep nginx_nftset
A política permite que httpd_t (domínio SELinux do NGINX) use sockets netlink_netfilter necessários pelo libnftables.
Alto uso de memória
Solução: Reduza o TTL do cache ou limite o tamanho do cache na configuração de memória compartilhada.
Limitação de taxa não funcionando
Solução: Certifique-se de que o conjunto nft para auto-banimento existe e tem suporte a tempo limite:
sudo nft add table ip filter
sudo nft add set ip filter ratelimited '{ type ipv4_addr; flags timeout; timeout 1h; }'
Log mostra "matched=table:setname" mas IP não está no conjunto nft
Esse é um comportamento esperado. O módulo relata o que viu no momento da solicitação. Se você verificar o conjunto nft depois e não encontrar o IP:
-
Expiração do tempo limite: O IP foi adicionado com um tempo limite e já expirou
# Verificar flags do conjunto nft list set ip filter setname # Procurar por "flags timeout" na saída -
Cache do módulo: O módulo armazena consultas (padrão 60s). Um IP recentemente removido pode ainda aparecer como "correspondido"
# Desativar temporariamente o cache para depuração (não para produção!) nftset_cache_ttl 0; -
Entrada foi removida: fail2ban, scripts ou comandos manuais podem ter removido
-
Problema de configuração de armadilha: Se estiver usando armadilhas honeypot com
nftset_autoadd, bots legítimos podem ter acionado armadilhas. Verifique se suas localizações de armadilha não se sobrepõem a caminhos legítimos de bots (como sitemaps, robots.txt). Userobots.txtpara excluir caminhos de armadilha da indexação.
autoadd falha com erro de tempo limite
Isso significa que você está usando timeout=N em nftset_autoadd, mas o conjunto nft foi criado sem suporte a tempo limite.
Solução: Recrie o conjunto nft com suporte a tempo limite:
# Excluir e recriar com a flag de tempo limite
sudo nft delete set ip filter honeypot
sudo nft add set ip filter honeypot '{ type ipv4_addr; flags timeout; timeout 1d; }'
🔄 Migração do ipset-access
Se você está migrando do antigo ngx_http_ipset_access_module, siga estes passos:
1. Converter ipsets para conjuntos nft
# Antigo ipset
ipset create bad_guys hash:ip timeout 86400
# Novo conjunto nft equivalente
nft add table ip filter
nft add set ip filter bad_guys '{ type ipv4_addr; flags timeout; timeout 1d; }'
# Para faixas CIDR (hash:net → flag de intervalo)
# Antigo: ipset create networks hash:net
# Novo:
nft add set ip filter networks '{ type ipv4_addr; flags interval; }'
2. Atualizar a configuração do NGINX
| Antigo (ipset) | Novo (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. Atualizar formatos de log
# Antigo
log_format security '... ipset_result="$ipset_result" matched_set="$ipset_matched_set"';
# Novo
log_format security '... nftset_result="$nftset_result" matched_set="$nftset_matched_set"';
4. Atualizar consultas Prometheus/Grafana
| Métrica Antiga | Nova 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. Diferenças principais
| Recurso | ipset-access | nftset-access |
|---|---|---|
| Backend | libipset (ipsets do kernel) | libnftables (nftables) |
| Formato do conjunto | setname |
tabela:nome_do_conjunto |
| Conjuntos CIDR | tipo hash:net |
flag flags interval |
| Família | Especificada no tipo do conjunto | Auto-detectada a partir do IP do cliente |
| firewalld | apenas backend iptables | compatível com backend nftables |
Por que migrar?
- Compatibilidade com RHEL 9/Rocky 9: o firewalld padrão para o backend nftables
- Suporte a kernel moderno: nftables é o futuro do firewall Linux
- Gerenciamento unificado: Use comandos
nftpara firewall e controle de acesso - Melhor suporte a CIDR: Conjuntos de intervalo lidam com faixas de rede de forma eficiente
📋 Requisitos
- NGINX ≥ 1.22 (compilado com
--with-compat) - Kernel Linux com suporte a nftables
- Biblioteca e cabeçalhos de desenvolvimento libnftables
- Capacidades:
CAP_NET_ADMINpara operações nftables
📜 Licença
Este é um software proprietário. Todos os direitos reservados.
Disponível exclusivamente através do Repositório Premium GetPageSpeed.
👤 Autor
Danila Vershinin GetPageSpeed LLC
🆘 Suporte
- Honeypot v2.0 Usando nftset-access para auto-banir bots
- Suporte: Disponível para assinantes premium
- Contato: Suporte GetPageSpeed
Módulo NGINX NFTSet Access
Um módulo premium NGINX da GetPageSpeed LLC
www.getpagespeed.com