Skip to content

Bloqueio de IPs na Edge da Cloudflare

Bloqueie IPs maliciosos na edge da Cloudflare. Este guia usa o modo Lists, recomendado para a maioria das implantações.

Comparação entre Modos

EzyShield oferece dois modos de bloqueio na Cloudflare:

RecursoListsRulesets
Chamadas de API por bloqueio1 (account-level)1 por zone
Capacidade de IPs10.000~200 por rule
Suporte multi-zoneAutomáticoRegras por zone
Configuração WAFAutomáticaManual por zone
Plano gratuito✅ (1 list, 10k items)
Menor privilégio❌ (precisa token account-level)✅ (token zone-level)

Os dois modos são totalmente suportados — escolha por implantação (e, em configurações multi-conta, por conta). Lists atende a maioria das implantações multi-zone; rulesets atende controle por zone, tokens de menor privilégio (zone-level) ou contas cuja cota de custom lists já está ocupada. Rodar uma conta em lists e outra em rulesets é uma configuração perfeitamente normal.

Configuração do Modo Lists

Passo 1: Criar Token de API da Cloudflare

  1. Acesse Painel da Cloudflare
  2. Vá em Account → API Tokens (barra lateral, canto inferior esquerdo)
  3. Clique em Create Token e selecione Custom token
  4. Configure o token com estas permissões:
    • Account → Account Filter Lists → Edit (obrigatório para gerenciar a lista de IPs)
    • Para cada zone que quiser gerenciar regras WAF automaticamente:
      • Zone → Firewall Services → Edit (opcional; obrigatório ao usar zone_ids)
    • Zone → Zone → Read (opcional; obrigatório apenas para a resposta "cobrir todas as zones" do wizard, que enumera as zones da conta) — veja a referência de permissões da Cloudflare
  5. Defina restrições conforme necessário (allowlist de IP, TTL, etc.)
  6. Copie o token imediatamente — você não conseguirá vê-lo novamente

Passo 2: Obter Account ID e Zone IDs

Account ID:

  • Acesse Account → Workers no Painel da Cloudflare
  • O Account ID é exibido no canto inferior esquerdo da página (32 caracteres hexadecimais)

Zone IDs (opcional, para gerenciamento automático de regras WAF):

  • Para cada domínio/zone que quiser proteger
  • Vá em Domain → Overview
  • O Zone ID está na barra lateral direita (32 caracteres hexadecimais)

Passo 3: Configurar EzyShield

Salve o token de API como variável de ambiente:

bash
export CLOUDFLARE_API_TOKEN="seu_token_api_aqui"

Adicione ao config.yaml:

yaml
enforce:
  cloudflare:
    api_token: env:CLOUDFLARE_API_TOKEN
    mode: lists
    account_id: seu_account_id_32_caracteres_hex
    # Opcional: gerenciar regras WAF automaticamente por zone
    zone_ids:
      - zone_id_1
      - zone_id_2
    # Opcional: ação da regra WAF (padrão: "block")
    action: block  # ou "challenge" / "js_challenge"
    # Opcional: nome customizado da lista (padrão: "ezyshield_blocked")
    # list_name: ezyshield_blocked

Passo 4: Verificar Configuração

Execute o comando de diagnóstico:

bash
ezyshield test enforcer cloudflare

Ele verifica as permissões do token, testa a conectividade com a Cloudflare, lista as zones que você consegue acessar e mostra o status da lista (existência, quantidade de items).

Cobertura de zones no wizard

Os dois entry points do wizard (init e config enforcer cloudflare) perguntam, no modo lists, quais zones a regra de bloqueio deve cobrir:

  • all — o wizard enumera todas as zones que o token consegue ler na conta (com paginação) e persiste esse snapshot em zone_ids; a config fica explícita, e rodar o wizard de novo captura domínios adicionados depois. Precisa de Zone → Zone → Read; sem essa permissão o wizard degrada graciosamente para o caminho manual e nomeia o escopo que falta.
  • Zone IDs explícitos — exatamente essas zones, nada é enumerado.
  • ENTER — configuração manual (o wizard imprime a regra para colar por zone).

Para all/explícito, o wizard imediatamente cria-ou-verifica a WAF Custom Rule em cada zone alvo (idempotente com o gerenciamento de regras do próprio enforcer — rodar de novo nunca duplica) e imprime um relatório por zone: configured / already present / FAILED (HTTP xxx: motivo), com instruções manuais para cada zone que falhou. Falha parcial nunca aborta: a config é salva mesmo assim e o daemon tenta as zones que falharam a cada sync.

Passo 5: (Opcional) Configuração Manual da Regra WAF

Se você NÃO configurou zone_ids no passo 3 (ou respondeu ENTER no wizard), você deve criar a regra WAF Custom manualmente para cada zone:

  1. Vá em Domain → Security → WAF → Custom rules
  2. Clique em Create Rule
  3. Configure:
    • Field: IP Source Address
    • Operator: is in list
    • Value: Selecione sua lista ezyshield_blocked
    • Action: Block (ou a ação que você escolheu)
    • Description: ezyshield-list-block
  4. Implante a regra

Se você configurou zone_ids, este passo é automático — as regras são criadas no primeiro Sync.

Configuração do Modo Rulesets

Para implantações que querem controle por zone ou não podem usar tokens account-level:

Passo 1: Criar Token de API de Nível de Zone

  1. Vá em Zone → API Tokens (no painel da zone)
  2. Crie um token com:
    • Zone → Firewall → Edit em cada zone
  3. Salve o token como CLOUDFLARE_API_TOKEN

Passo 2: Configurar EzyShield

yaml
enforce:
  cloudflare:
    api_token: env:CLOUDFLARE_API_TOKEN
    mode: rulesets
    zone_ids:
      - zone_1
      - zone_2
    action: block  # ou "challenge" / "js_challenge"

Cada zone recebe sua própria regra WAF Custom com todos os IPs bloqueados. Limites de tamanho de expressão (~3900 bytes) significam aproximadamente 200 IPs por regra; EzyShield divide automaticamente em múltiplas regras se necessário.

Limites de plano e o que o EzyShield verifica

As quotas da Cloudflare dependem do plano, e um token válido não garante um setup que funcione. Dois limites importam aqui:

  • Custom Lists (modo lists): o número de listas custom depende do plano — contas free têm uma única lista custom. Se esse slot já estiver ocupado por outra lista, a lista do EzyShield não pode ser criada e o enforcement nunca vai funcionar.
  • Regras custom do WAF (ambos os modos): as regras são limitadas por zona por plano (5 no free). O modo lists precisa de uma regra por zona coberta referenciando a lista; o modo rulesets escreve suas regras diretamente.

O EzyShield verifica a viabilidade em três momentos, para você descobrir na hora — não no primeiro sync armado:

  1. No setup (init / config enforcer cloudflare): depois de validar o token e o escopo, o wizard cria ou adota a Custom List configurada ali mesmo. Uma recusa por quota aborta o setup mostrando as saídas (apagar uma lista sem uso, fazer upgrade do plano, ou trocar para o modo rulesets) — nenhum config quebrado é gravado. No modo rulesets o wizard informa quantas regras custom do WAF cada zona já usa.
  2. Sob demanda (test enforcer cloudflare): re-executa as checagens de capacidade contra o config atual, incluindo existência da lista, contagem de itens e uso de regras por zona.
  3. Continuamente (doctor): verifica que o token ainda resolve e é válido, que a lista ainda existe (com aviso de contagem de itens ao se aproximar do teto de 10k) e o uso de regras por zona — pegando listas apagadas por fora do EzyShield e tokens rotacionados ou expirados.

Solução de Problemas

Erros "Permission denied" ou "Insufficient permissions"

Verifique as permissões do seu token:

bash
# Verifique o token com curl (substitua TOKEN pelo seu token real)
curl -H "Authorization: Bearer TOKEN" \
  https://api.cloudflare.com/client/v4/user/tokens/verify

Procure pelas permissões necessárias na resposta.

Lista mostra "unauthorized" no Painel da Cloudflare

Isso é esperado se seu token de API tiver apenas Account Filter Lists:Edit (não Zone:Firewall:Edit). A lista existe e funciona; você apenas não consegue visualizá-la na interface do painel.

Regras WAF não são criadas automaticamente

Verifique:

  1. zone_ids está configurado em config.yaml
  2. Seu token tem permissão Zone → Firewall Services → Edit
  3. Execute ezyshield test enforcer cloudflare para verificar erros de permissão
  4. Verifique os logs: ezyshield status → procure por entradas da Cloudflare

"List at capacity" (10k items)

Se você atingir o limite de 10k items do plano gratuito, você tem duas opções:

  1. Usar modo Rulesets (sem limite por rule, mas ~200 por rule)
  2. Fazer upgrade para um plano pago da Cloudflare para limites maiores

Configuração Multi-Conta

Agências e freelancers costumam gerenciar sites espalhados por contas Cloudflare separadas, cada uma com seu próprio token de API. Um único daemon EzyShield cuida de todas: cada ban é aplicado em todas as contas configuradas, e uma falha em uma conta nunca bloqueia as demais.

Os wizards fazem essa configuração por você — tanto ezyshield init (etapa de CDN) quanto ezyshield config enforcer cloudflare perguntam "Add another Cloudflare account?" depois de cada conta. Cada conta recebe seu próprio nome, modo (lists ou rulesets — misturar é normal), token validado e sua própria variável no .env (CLOUDFLARE_API_TOKEN para uma única conta sem nome, CLOUDFLARE_API_TOKEN_<NOME> para contas nomeadas). Rodar config enforcer cloudflare de novo permite escolher uma conta existente para reconfigurar ou adicionar outra.

A config resultante:

yaml
enforce:
  cloudflare:
    # Conta 1
    - name: cliente_a
      api_token: env:CLOUDFLARE_API_TOKEN_CLIENTE_A
      mode: lists
      account_id: account_a_id
      zone_ids: [zone_a1, zone_a2]
    # Conta 2 — um modo diferente por conta é normal
    - name: cliente_b
      api_token: env:CLOUDFLARE_API_TOKEN_CLIENTE_B
      mode: rulesets
      zone_ids: [zone_b1]

Com mais de uma conta, cada entrada precisa de um name único (o wizard garante isso, e se oferece para nomear uma entrada pré-existente sem nome). Cada conta recebe gerenciamento independente de listas/regras e status por conta em test enforcer cloudflare e doctor. Os logs mostram cloudflare[cliente_a] e cloudflare[cliente_b] como o nome do enforcer para clareza.

Limitação de Taxa

EzyShield se mantém dentro dos limites da API da Cloudflare em três níveis, todos automáticos:

  • Um teto de 4 requisições/segundo no cliente para toda chamada de API, bem abaixo da cota pública de 1200 req/5 min.
  • Mutações são agrupadas: bans rápidos viram um único push por janela de debounce (padrão 15s), e remoções (bans expirados, unbans) acumulam e saem em uma única chamada em lote por expire_flush_interval (padrão 3m). Ambos são ajustáveis por entrada de conta — veja a referência de configuração.
  • Quando a Lists API ainda responde com o próprio throttle (HTTP 429, ou códigos de erro 10040/971), o EzyShield recua com jitter — respeitando Retry-After — e tenta de novo antes de reportar falha. Um throttle que persiste por vários ciclos de sync é o que acaba degradando o estado de enforcement; uma única chamada limitada não degrada mais.

Considerações de Segurança

  • Tokens de API são resolvidos no startup do daemon e nunca são registrados em logs
  • Tokens não são incluídos em mensagens de erro ou logs
  • Sempre use referências env:VARNAME; tokens inline no config são rejeitados no carregamento
  • Restrinja as permissões do token e endereços IP nas configurações da Cloudflare quando possível
  • O token account-level pode modificar suas Custom IP Lists — restrinja o acesso conforme necessário

Validando sua Configuração

Usando test enforcer cloudflare

Após configurar, valide seu setup com:

bash
ezyshield test enforcer cloudflare --config-dir /etc/ezyshield/

Ele confirma que o token é válido e ativo, verifica o acesso à conta e às zones, valida as permissões da Cloudflare do token e relata o que funciona, o que está faltando e como corrigir cada lacuna.

Exemplo de saída (modo lists com zone_ids):

Cloudflare enforcer (mode: lists): pass
────────────────────────────────────
✓ Token validity: Token ID: abc...def, status: active
✓ Account access: Account ID: 0123456789abcdef
✓ List access (read): List "ezyshield_blocked" found (ID: lstxxxxx, 147 items)
✓ Zone WAF access: Zone aaa111 — WAF rule access OK (2 custom rule(s) in use)
✗ Zone WAF access: Zone ccc333 — 403 Forbidden
  └─ Ensure token has Zone:Firewall Services:Edit on this zone

Result: 4/5 checks passed, 1 failed

Código de saída: 0 se todos os testes passarem, 1 se algum teste falhar

Saída JSON: Use a flag --json para saída estruturada apropriada para automação

Veja Também