Fail2ban + Cloudflare: Como Bloquear Ataques de Força Bruta na Borda e Proteger seu Servidor Linux em 2026

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:

  1. 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.
  2. Desperdício de recursos do servidor: Mesmo que você bloqueie o IP no iptables local, 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:

  1. O invasor dispara centenas de requisições maliciosas contra o seu site.
  2. A requisição atravessa a rede da Cloudflare, que injeta o cabeçalho HTTP CF-Connecting-IP contendo o endereço IPv4 ou IPv6 real do cliente.
  3. O servidor web (Nginx) lê o cabeçalho e grava o IP real do invasor no arquivo de log (ex: /var/log/nginx/access.log ou nos logs de erro).
  4. 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.
  5. 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.
  6. 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:

  1. Acesse o painel de controle da Cloudflare (dash.cloudflare.com).
  2. Clique no ícone de perfil no canto superior direito e selecione My Profile > API Tokens.
  3. Clique em Create Token e escolha a opção Create Custom Token (Get started).
  4. Defina um nome claro para o token, como Fail2ban-Edge-Blocker.
  5. Na seção de Permissions (Permissões), configure exatamente:
    Zone > Firewall Services > Edit (ou Zone > IP Access Rules > Edit dependendo da versão do seu painel).
  6. Na seção de Zone Resources (Recursos da Zona), selecione Include > Specific zone > seu-dominio.com.
  7. Clique em Continue to summary e depois em Create Token.
  8. 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 ignoreip para 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.