Pular para conteúdo

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.

Version GetPageSpeed

⚠️ 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:

  1. Expiração do tempo limite: O IP foi adicionado com um tempo limite (ex: timeout 1d) e já expirou
  2. 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
  3. 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:

  1. 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
    

  2. 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;
    

  3. Entrada foi removida: fail2ban, scripts ou comandos manuais podem ter removido

  4. 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). Use robots.txt para 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 nft para 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_ADMIN para 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

Módulo NGINX NFTSet Access
Um módulo premium NGINX da GetPageSpeed LLC
www.getpagespeed.com