Se você administra um servidor Linux, uma VPS ou gerencia aplicações web como WordPress, Ghost ou APIs em produção, já deve ter reparado nos seus arquivos de log: uma enxurrada contínua de tentativas de invasão automatizadas. Bots do mundo inteiro testam senhas fracas por força bruta em portas SSH, disparam requisições constantes em /wp-login.php, tentam explorar endpoints do xmlrpc.php ou vasculham arquivos de configuração confidenciais (.env, phpinfo.php e backups de bancos de dados).
O Fail2ban é o canivete suíço clássico do administrador de sistemas para combater esse problema: ele analisa os logs do sistema em tempo real e, ao detectar abusos repetidos, adiciona regras no firewall local (iptables, nftables ou ufw) para banir o endereço IP do invasor. Porém, quando o seu domínio está protegido atrás de uma CDN e proxy reverso global como a Cloudflare, o comportamento padrão do Fail2ban enfrenta dois grandes obstáculos:
- O perigo de banir os IPs da Cloudflare: Como todo o tráfego de entrada passa pelos servidores de borda da Cloudflare, o firewall do seu servidor pode acabar bloqueando os próprios nós de entrega de conteúdo da Cloudflare se o servidor não estiver configurado para extrair o cabeçalho
CF-Connecting-IP. - Desperdício de recursos do servidor: Mesmo que você bloqueie o IP no
iptableslocal, o tráfego do atacante ainda viaja pela internet, consome a banda da sua VPS, estabelece conexões TCP e ocupa sockets do seu servidor web (Nginx ou Apache) antes de ser descartado.
A solução definitiva e mais elegante da arquitetura moderna de infraestrutura é a Defesa na Borda (Edge Defense): configurar o Fail2ban no seu servidor para, ao flagrar um bot malicioso, disparar uma requisição autenticada diretamente para a API v4 da Cloudflare. O IP malicioso é bloqueado no nível de WAF/Firewall global da Cloudflare, sendo cortado a milhares de quilômetros do seu servidor antes mesmo de gastar um único ciclo de CPU da sua máquina.
Como Funciona o Fluxo de Bloqueio na Borda
O ciclo operacional entre o seu servidor Linux e a infraestrutura da Cloudflare opera no seguinte fluxo automatizado:
- O invasor dispara centenas de requisições maliciosas contra o seu site.
- A requisição atravessa a rede da Cloudflare, que injeta o cabeçalho HTTP
CF-Connecting-IPcontendo o endereço IPv4 ou IPv6 real do cliente. - O servidor web (Nginx) lê o cabeçalho e grava o IP real do invasor no arquivo de log (ex:
/var/log/nginx/access.logou nos logs de erro). - O Fail2ban identifica o padrão de ataque (ex: 5 falhas de login em menos de 1 minuto) através de um filtro de regex pré-definido.
- Em vez de apenas rodar um comando local de
iptables, a ação customizada do Fail2ban executa uma chamada cURL para o endpoint de IP Access Rules da Cloudflare. - A Cloudflare adiciona imediatamente uma regra de bloqueio global para aquele IP. Nas próximas tentativas do invasor, ele receberá uma tela de erro HTTP 403 (ou desafio de Captcha/Turnstile) entregue diretamente pelos datacenters da Cloudflare.
Passo 1: Criar o Token de API Personalizado na Cloudflare
Por questões de segurança e pelo princípio do menor privilégio, nunca utilize a sua Chave Global de API (Global API Key). Em vez disso, crie um API Token restrito apenas à edição das regras de firewall da sua zona:
- Acesse o painel de controle da Cloudflare (dash.cloudflare.com).
- Clique no ícone de perfil no canto superior direito e selecione My Profile > API Tokens.
- Clique em Create Token e escolha a opção Create Custom Token (Get started).
- Defina um nome claro para o token, como
Fail2ban-Edge-Blocker. - Na seção de Permissions (Permissões), configure exatamente:
Zone > Firewall Services > Edit(ouZone > IP Access Rules > Editdependendo da versão do seu painel). - Na seção de Zone Resources (Recursos da Zona), selecione
Include > Specific zone > seu-dominio.com. - Clique em Continue to summary e depois em Create Token.
- Copie o token gerado e guarde-o com segurança. Ele não será exibido novamente.
Além do token, obtenha o Zone ID do seu domínio: no painel principal da zona (aba Overview), role a página até a coluna lateral direita e copie o código alfanumérico do campo Zone ID.
Passo 2: Configurar o Nginx para Registrar o IP Real do Visitante
Para que o Fail2ban enxergue o IP verdadeiro do invasor nos arquivos de log (e não o IP do proxy da Cloudflare), o seu servidor web precisa restaurar o cabeçalho original. No Nginx, configure o módulo http_realip_module.
Crie ou edite o arquivo /etc/nginx/conf.d/cloudflare.conf com a lista oficial de sub-redes IPv4 e IPv6 da Cloudflare:
# Sub-redes IPv4 oficiais da Cloudflare
set_real_ip_from 173.245.48.0/20;
set_real_ip_from 103.21.244.0/22;
set_real_ip_from 103.22.200.0/22;
set_real_ip_from 103.31.4.0/22;
set_real_ip_from 141.101.64.0/18;
set_real_ip_from 108.162.192.0/18;
set_real_ip_from 190.93.240.0/20;
set_real_ip_from 188.114.96.0/20;
set_real_ip_from 197.234.240.0/22;
set_real_ip_from 198.41.128.0/17;
set_real_ip_from 162.158.0.0/15;
set_real_ip_from 104.16.0.0/13;
set_real_ip_from 104.24.0.0/14;
set_real_ip_from 172.64.0.0/13;
set_real_ip_from 131.0.72.0/22;
# Sub-redes IPv6 oficiais da Cloudflare
set_real_ip_from 2400:cb00::/32;
set_real_ip_from 2606:4700::/32;
set_real_ip_from 2803:f800::/32;
set_real_ip_from 2405:b500::/32;
set_real_ip_from 2405:8100::/32;
set_real_ip_from 2a06:98c0::/29;
set_real_ip_from 2c0f:f248::/32;
# Instruir o Nginx a extrair o IP real do cabeçalho enviado pela Cloudflare
real_ip_header CF-Connecting-IP;
real_ip_recursive on;
Teste a sintaxe da configuração e recarregue o Nginx:
nginx -t && systemctl reload nginx
Passo 3: Criar a Ação Customizada do Fail2ban para a Cloudflare
Agora vamos criar a regra de ação que informa ao Fail2ban como interagir com a API v4 da Cloudflare. Crie um novo arquivo de ação em /etc/fail2ban/action.d/cloudflare-api.conf:
[Definition]
# Ação de Banimento: Cria uma regra de acesso no Firewall da Cloudflare
actionban = curl -s -X POST "https://api.cloudflare.com/client/v4/zones/<cfzoneid>/firewall/access_rules/rules" \
-H "Authorization: Bearer <cftoken>" \
-H "Content-Type: application/json" \
--data '{"mode":"block","configuration":{"target":"ip","value":"<ip>"},"notes":"Fail2ban auto-ban: <name> em <time>"}'
# Ação de Desbanimento: Localiza o ID da regra criada e a remove após o bantime expirar
actionunban = rule_id=$(curl -s -X GET "https://api.cloudflare.com/client/v4/zones/<cfzoneid>/firewall/access_rules/rules?configuration.value=<ip>&page=1&per_page=1" \
-H "Authorization: Bearer <cftoken>" \
-H "Content-Type: application/json" | grep -Po '(?<="id":")[^"]*' | head -n 1); \
if [ ! -z "$rule_id" ]; then \
curl -s -X DELETE "https://api.cloudflare.com/client/v4/zones/<cfzoneid>/firewall/access_rules/rules/$rule_id" \
-H "Authorization: Bearer <cftoken>" \
-H "Content-Type: application/json"; \
fi
[Init]
# Substitua com as suas credenciais obtidas no Passo 1
cftoken = SEU_TOKEN_DE_API_AQUI
cfzoneid = SEU_ZONE_ID_AQUI
Dica de segurança: Como esse arquivo armazena credenciais confidenciais da API, restrinja as permissões de leitura apenas para o usuário root:
chmod 600 /etc/fail2ban/action.d/cloudflare-api.conf
Passo 4: Configurar as Jails de Proteção (`jail.local`)
Com a ação criada, configure as regras de monitoramento (jails) no arquivo /etc/fail2ban/jail.local. Se você estiver protegendo sites WordPress e serviços web, uma configuração robusta inclui monitoramento de requisições maliciosas em rotas de login e buscas por vulnerabilidades:
[DEFAULT]
# Proteção contra auto-banimento: adicione o seu IP residencial/VPN e a interface local
ignoreip = 127.0.0.1/8 ::1 SEU_IP_PUBLICO_AQUI
# Tempo de banimento padrão: 24 horas (86400 segundos)
bantime = 86400
findtime = 600
maxretry = 5
# ==========================================
# Jail 1: Proteção de Autenticação do WordPress
# ==========================================
[wordpress-auth]
enabled = true
port = http,https
filter = wordpress-auth
logpath = /var/log/nginx/access.log
banaction = cloudflare-api
maxretry = 3
findtime = 300
bantime = 86400
# ==========================================
# Jail 2: Scanners de Vulnerabilidades e Bots
# ==========================================
[nginx-botsearch]
enabled = true
port = http,https
filter = nginx-botsearch
logpath = /var/log/nginx/access.log
banaction = cloudflare-api
maxretry = 2
findtime = 600
bantime = 172800
Caso ainda não tenha o filtro para WordPress em /etc/fail2ban/filter.d/wordpress-auth.conf, você pode criá-lo rapidamente com as expressões regulares que capturam requisições repetidas para o wp-login.php e xmlrpc.php:
[Definition]
failregex = ^<HOST> .* "POST /(wp-login\.php|xmlrpc\.php) HTTP/.*" (401|403|200)
ignoreregex =
Reinicie o serviço do Fail2ban para carregar as alterações:
systemctl restart fail2ban
Passo 5: Testando e Validando os Bloqueios
Para garantir que toda a cadeia de automação está funcionando de ponta a ponta, você pode verificar o status da jail diretamente pela linha de comando:
fail2ban-client status wordpress-auth
O retorno exibirá a quantidade de IPs atualmente banidos:
Status for the jail: wordpress-auth
|- Filter
| |- Currently failed: 1
| |- Total failed: 42
| `- File list: /var/log/nginx/access.log
`- Actions
|- Currently banned: 3
|- Total banned: 15
`- Banned IP list: 198.51.100.24 203.0.113.88 192.0.2.145
Em seguida, acesse o painel da Cloudflare em Security > WAF > Tools > IP Access Rules. Você verá as regras adicionadas em tempo real com a ação Block e a descrição gerada pelo Fail2ban (Fail2ban auto-ban: wordpress-auth...). Quando o tempo de bantime expirar, o Fail2ban acionará a rotina de actionunban, mantendo a sua lista de regras limpa e dentro dos limites da conta.
Boas Práticas e Dicas de Otimização em 2026
Para manter a estabilidade e a segurança operacional de longo prazo na sua infraestrutura, adote estas recomendações indispensáveis:
- Nunca esqueça o `ignoreip`: Adicione o seu IP estático residencial, a faixa de IPs da sua VPN corporativa e os IPs dos seus servidores internos à diretiva
ignoreippara nunca correr o risco de ficar trancado fora do seu próprio servidor. - Utilize o modo ‘challenge’ se preferir: No arquivo
cloudflare-api.conf, você pode alterar"mode":"block"para"mode":"challenge"ou"mode":"managed_challenge". Em vez de bloquear sumariamente com tela de erro, a Cloudflare apresentará um desafio Turnstile/Captcha interativo. Isso é especialmente útil em lojas virtuais para evitar falsos positivos que impeçam compras de clientes legítimos. - Atenção ao limite de regras da Cloudflare: Contas gratuitas da Cloudflare possuem um limite de até 50.000 regras de IP Access Rules (o que é mais do que suficiente para 99% dos servidores). Ainda assim, configure tempos de banimento equilibrados (entre 24 a 72 horas) para que regras antigas de bots com IPs dinâmicos sejam recicladas naturalmente.
- Trabalhe em camadas (Defense in Depth): Além do Fail2ban na borda, mantenha o seu firewall local ativo (UFW/nftables fechando todas as portas que não sejam as necessárias) e certifique-se de que o tráfego HTTP/HTTPS do seu servidor aceite conexões exclusivamente provenientes das sub-redes da Cloudflare, impedindo que invasores tentem contornar o proxy descobrindo o IP de origem do VPS.
Conclusão
Integrar o poder de detecção granular do Fail2ban com a capilaridade global da Cloudflare transforma o seu servidor Linux em uma fortaleza digital. Ao delegar o descarte do tráfego malicioso para os nós de borda mais próximos da origem do ataque, o seu servidor deixa de sofrer com sobrecargas de I/O, pico de CPU e esgotamento de conexões, garantindo que os visitantes legítimos desfrutem da máxima performance e disponibilidade.