Introdução

Ataques DDoS (Distributed Denial of Service) podem derrubar sua aplicação em segundos. Eu já sofri com isso: um ataque coordenado consumiu memória, travou o proxy e deixou a infraestrutura indisponível. A diferença entre perder o acesso SSH ou recuperar em minutos está em 6 medidas específicas de prevenção que mostro neste artigo.

Este tutorial cobre as técnicas que provei em produção: desde configurar o Cloudflare corretamente até ajustar o kernel Linux para resistir a milhões de requisições. Você aprenderá a implementar cada uma delas com exemplos práticos, sem teoria vaga.

Comparativo: servidor sob DDoS sem proteção versus infraestrutura protegida com as 6 medidas

⚠️ Atenção: Este artigo é baseado em um incidente real de DDoS. As medidas aqui descritas são preventivas. Se você estiver sob ataque ativo, use este checklist em paralelo com suporte do seu provedor CDN (Cloudflare, Akamai, etc.).

Pré-requisitos

Para implementar as medidas deste artigo, você precisa de:

  • Acesso root ou sudo na VPS/servidor
  • Docker e Docker Compose instalados
  • Conhecimento básico de Linux (edição de arquivos, comandos de kernel)
  • Conta Cloudflare configurada como reverse proxy/CDN
  • Proxy reverso em produção (Traefik, Nginx, HAProxy)
  • Ferramentas de monitoramento (Prometheus, Grafana, ou similar)

Se você não tem ainda um proxy reverso em produção, comece com Traefik em Docker ou Nginx.

1. Desativar Auto-Update de Proxy em Produção

Versões novas de proxy (Traefik, Nginx) podem conter bugs que se manifestam apenas sob alta carga. Eu descobri a dura maneira: uma atualização automática do Traefik para uma versão menor introduziu um memory leak que triplicou o consumo de RAM durante um ataque.

O problema: se o proxy cai sob DDoS, o atacante já venceu.

Implementação no Docker Compose

Congele a versão do seu proxy e revise atualizações manualmente antes de aplicar:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
version: '3.9'

services:
  traefik:
    image: traefik:v3.0.0  # ❌ NÃO use 'latest' nem 'v3'
    # Use versão específica (major.minor.patch)
    restart: unless-stopped
    environment:
      - TRAEFIK_LOG_LEVEL=WARN
      - TRAEFIK_ACCESSLOG=true
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock:ro
      - ./traefik-config.yaml:/etc/traefik/traefik.yaml:ro
    networks:
      - frontend

  app:
    image: seu-app:1.2.3  # Também fixe sua aplicação
    restart: unless-stopped

Processo de Atualização Seguro

  1. Revise o changelog antes de atualizar
  2. Teste em staging com tráfego real
  3. Aplique em horário de baixo tráfego
  4. Tenha rollback pronto: docker-compose up com imagem anterior
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
# Teste a nova versão sem substituir a produção
docker pull traefik:v3.1.0
docker run --rm traefik:v3.1.0 version

# Se passou nos testes, atualize no arquivo compose
# sed -i 's/traefik:v3.0.0/traefik:v3.1.0/g' docker-compose.yml

# Deploy com controle
docker-compose down
docker-compose up -d
docker-compose logs -f traefik  # Observe por 5 minutos

ℹ️ Informação: O Traefik v3.0.0 a v3.2.x teve patches de segurança. Se você está em v2.10.x, atualize apenas se testou em staging. Versões antigas têm CVEs, mas atualizações rápidas sob ataque causam falhas.

2. Ativar “Under Attack Mode” no Cloudflare

O Cloudflare oferece um modo específico para DDoS: Under Attack Mode. Ele aumenta o nível de desafio (CAPTCHAs, validação de navegador) para bloquear bots enquanto deixa usuários legítimos passarem.

Configuração Manual no Painel Cloudflare

Use este passo a passo no painel Cloudflare:

  1. Faça login no painel do Cloudflare
  2. Selecione o site que você deseja configurar
  3. Clique em Security no menu lateral
  4. Clique em DDoS Protection
  5. Localize a seção Managed DDoS Protection
  6. Clique em Configure ao lado de Under Attack Mode

A transição é imediata. Usuários legítimos recebem um desafio de 5-10 segundos; bots automatizados tendem a ser bloqueados.

Se o “Under Attack” não aparecer no seu painel

Em alguns planos/contas, o toggle pode não estar visível no local esperado. Nesse caso, aplique um desafio global temporário:

  1. Acesse SecurityWAFCustom Rules
  2. Crie uma regra com expressão true
  3. Defina a ação como Managed Challenge (ou JS Challenge, se preferir)
  4. Posicione a regra no topo e publique

Isso não é idêntico ao “Under Attack”, mas entrega mitigação rápida durante incidente, com efeito semelhante para bloquear tráfego automatizado em massa.

Automação: Ativar via API

Se você quer ativar o modo automaticamente quando detectar anomalias, use a API do Cloudflare:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
#!/bin/bash
# Script: ativar-under-attack.sh

ZONE_ID="seu-zone-id"  # Encontre em Domain → Overview → Zone ID
API_KEY="sua-api-key"  # Crie em My Profile → API Tokens
EMAIL="[email protected]"

# Ativar Under Attack Mode
curl -X PATCH "https://api.cloudflare.com/client/v4/zones/$ZONE_ID/settings/security_level" \
  -H "X-Auth-Email: $EMAIL" \
  -H "X-Auth-Key: $API_KEY" \
  -H "Content-Type: application/json" \
  --data '{"value":"under_attack"}'

echo "Under Attack Mode ativado"

Integração com Monitoramento

Trigger automático quando a taxa de requisições ultrapassar 10.000/min:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
# Pseudocódigo para Prometheus Alert
groups:
  - name: DDoS Detection
    rules:
      - alert: UnderDDoSAttack
        expr: rate(http_requests_total[1m]) > 10000
        for: 1m
        annotations:
          summary: "Ativando Under Attack Mode"
        actions:
          - webhook: "http://localhost:5000/enable-under-attack"

ℹ️ Informação: “Under Attack Mode” bloqueia ~80% dos bots automáticos, reduzindo falsos positivos de segurança. O custo é latência adicional para usuários legítimos (5-10s), aceitável em situação de crise.

3. Alterar o Endereço IP Real do Servidor

Se o atacante descobriu o IP real da sua VPS (através de registros DNS históricos, whois, ou engenharia social), ele pode contornar o Cloudflare e atacar diretamente.

Cenário: atacante faz WHOIS no domínio, encontra um IP antigo, e envia requisições diretamente para lá, ignorando o Cloudflare.

Passos para Mudar o IP

  1. Reserve um novo IP com seu provedor de VPS

    • Na Hetzner, DigitalOcean, ou Hostinger, isso é gratuito e demora 5 minutos
    • Você pode ter múltiplos IPs por VPS
  2. Configure o IP novo no servidor

1
2
3
4
5
6
7
8
# Listar IPs atuais
ip addr show

# Adicionar novo IP (exemplo em Ubuntu/Debian)
sudo ip addr add 203.0.113.50/24 dev eth0

# Para persistir após reboot, edite /etc/netplan/ ou /etc/network/interfaces
sudo nano /etc/netplan/01-netcfg.yaml

Exemplo de /etc/netplan/01-netcfg.yaml:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
network:
  version: 2
  ethernets:
    eth0:
      addresses:
        - 198.51.100.10/24
        - 203.0.113.50/24  # Novo IP
      gateway4: 198.51.100.1
      nameservers:
        addresses: [8.8.8.8, 8.8.4.4]
  1. Atualize DNS para apontar para o novo IP apenas em sua infraestrutura interna

    • Cloudflare continua apontando para o IP anterior (ou para um que você controla)
    • DNS interno aponta para o novo IP
    • Alte /etc/hosts dos servidores internos se necessário
  2. Mantenha o IP antigo “preso” no Cloudflare, apontando para um bloqueio genérico

1
2
3
# No Cloudflare DNS:
example.com  → CNAME → proxy.example.com (Cloudflare)
old-ip-server → (não existe, ou aponta para black hole)

Validar Mudança de IP

1
2
3
4
5
6
# Confirm o novo IP está ativo
curl -I http://203.0.113.50

# Teste desde fora com traceroute
traceroute example.com  # Deve ir através do Cloudflare
traceroute 203.0.113.50  # Seu servidor está isolado

⚠️ Atenção: Mudar IP é disruptivo. Tenha um plano de rollback. Se usar HTTPS pinning ou certificados específicos por IP, atualize também.

4. Configurar Limites de File Descriptors no Docker e Podman

Cada conexão TCP aberta consome um file descriptor (FD). Sob DDoS, milhares de conexões ficam pendentes, esgotando a cota do sistema e travando a aplicação.

Sintoma: “Too many open files” ou timeout em SSH durante ataque.

Entender File Descriptors

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
# Ver limite atual
ulimit -n
# Output típico: 1024

# Ver limite hard (máximo)
ulimit -Hn
# Output típico: 65536

# Ver quantos FDs estão em uso
lsof | wc -l

Configuração no Docker Compose

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
version: '3.9'

services:
  traefik:
    image: traefik:v3.0.0
    restart: unless-stopped
    ulimits:
      nofile:
        soft: 65000  # Para aplicações normais
        hard: 65536  # Máximo do sistema
    # Alternativa (notação curta, não recomendada)
    # ulimits: 65000:65536
    networks:
      - frontend

  app:
    image: seu-app:1.2.3
    ulimits:
      nofile:
        soft: 32000  # Menos agressivo para app
        hard: 65536

Se você usa Nginx no lugar de Traefik, a configuração fica assim:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
version: '3.9'

services:
  nginx:
    image: nginx:1.27-alpine
    restart: unless-stopped
    ulimits:
      nofile:
        soft: 65000
        hard: 65536
    ports:
      - "80:80"
      - "443:443"
    volumes:
      - ./nginx.conf:/etc/nginx/nginx.conf:ro

  app:
    image: seu-app:1.2.3
    ulimits:
      nofile:
        soft: 32000
        hard: 65536

Configuração no Podman

No Podman, você pode aplicar o mesmo limite com --ulimit:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
# Exemplo com Nginx
podman run -d --name nginx \
  --ulimit nofile=65000:65536 \
  -p 80:80 -p 443:443 \
  nginx:1.27-alpine

# Exemplo com Traefik
podman run -d --name traefik \
  --ulimit nofile=65000:65536 \
  -p 80:80 -p 443:443 \
  traefik:v3.0.0

Se você usa podman-compose, mantenha a chave ulimits no YAML, igual ao Docker Compose.

Aumentar Globalmente no Host

Se múltiplos containers precisam de limites altos:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
# Editar /etc/security/limits.conf
sudo nano /etc/security/limits.conf

# Adicionar:
# *               soft    nofile          65000
# *               hard    nofile          65536
# root            soft    nofile          65536
# root            hard    nofile          65536

# Recarregar
sudo sysctl -p

# Verificar
ulimit -n

Teste de Pressão

Simule conexões pendentes para validar o limite:

1
2
3
4
5
# Usar ab (Apache Bench) ou hey
ab -n 100000 -c 10000 http://127.0.0.1:80/

# Monitorar FDs em tempo real (ajuste o processo: traefik ou nginx)
watch -n 1 'lsof | grep -E "traefik|nginx" | wc -l'

ℹ️ Informação: Um limite de 65.000 file descriptors permite ~60.000 conexões simultâneas (contabilizando FDs para logs, sockets internos, etc.). Em prática, ajuste para 80-90% do limite hard.

5. Habilitar TCP Cookies no Kernel

TCP SYN Flood é um ataque simples: o atacante envia pacotes SYN (início de conexão TCP) sem responder ao SYN-ACK, causando o servidor alocar memória para conexões incompletas (SYN backlog).

TCP Syncookies resolve isso sem aceitar a conexão: o servidor incorpora informações no SYN-ACK de forma que a memória só é alocada APÓS a validação do cliente.

Habilitar no Linux

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
# Verificar status atual
sysctl net.ipv4.tcp_syncookies
# Output: net.ipv4.tcp_syncookies = 0  (desativado) ou = 1 (ativado)

# Ativar imediatamente
sudo sysctl -w net.ipv4.tcp_syncookies=1

# Persistir após reboot
echo "net.ipv4.tcp_syncookies = 1" | sudo tee -a /etc/sysctl.conf
sudo sysctl -p

Configurações Complementares (kernel hardening)

Enquanto estiver nessa, ative outras proteções:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
# Descartar pacotes SYN com IP inválido
echo "net.ipv4.tcp_syncookies = 1" | sudo tee -a /etc/sysctl.conf

# Limitar backlog de SYN (conexões incompletas)
echo "net.ipv4.tcp_max_syn_backlog = 4096" | sudo tee -a /etc/sysctl.conf

# Aumentar tamanho do backlog de listen (aplicações que aceitam muitas conexões)
echo "net.core.somaxconn = 4096" | sudo tee -a /etc/sysctl.conf

# Proteção contra IP spoofing (reverse path filter)
echo "net.ipv4.conf.all.rp_filter = 1" | sudo tee -a /etc/sysctl.conf

# Recarregar
sudo sysctl -p

Validar Configuração

1
2
3
4
5
# Criar script para ver se TCP Syncookies está funcionando
sudo cat /proc/net/netstat | grep -i sync

# Output esperado (com syncookies ativo):
# TcpExt: SyncookiesSent SyncookiesRecv SyncookiesFailed ...

📝 Exemplo: Em um DDoS típico com 500.000 SYN/segundo, sem syncookies o servidor aloca 5 GB de memória em segundos. Com syncookies ativado, o consumo permanece < 100 MB.

6. Implementar Monitoramento Adequado com Alertas

Monitoramento é prevenção. Se você detectar anomalias (spike de requisições, consumo anormal de memória) em 1 minuto, pode ativar defesas antes de perder SSH.

Métricas Críticas para DDoS

Monitore estas 5 métricas com alertas em tempo real:

MétricaAlertaAção
Taxa de requisições/min> 10.000Ativar Under Attack Mode
Conexões TCP pendentes> 50.000Aumentar tcp_max_syn_backlog
Consumo de memória (proxy)> 80%Reiniciar container, ativar Under Attack
Processos acumulados (zombie)> 100Investigar leak, restart app
Latência P99> 5sIndicativo de gargalo ou ataque lento

Configuração com Prometheus + Alertmanager

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
# prometheus.yml
global:
  scrape_interval: 15s

scrape_configs:
  - job_name: 'traefik'
    static_configs:
      - targets: ['localhost:8080']  # Metrics do Traefik

  - job_name: 'node'
    static_configs:
      - targets: ['localhost:9100']  # Node Exporter (métricas do host)

# Arquivo: alert_rules.yml
groups:
  - name: ddos_alerts
    interval: 30s
    rules:
      - alert: HighRequestRate
        expr: rate(http_requests_total[1m]) > 10000
        for: 1m
        labels:
          severity: critical
        annotations:
          summary: "Taxa alta de requisições: {{ $value }} req/s"
          description: "Possível DDoS. Ativar Under Attack Mode no Cloudflare."

      - alert: HighTCPConnections
        expr: node_sockstat_TCP_inuse > 50000
        for: 2m
        labels:
          severity: warning
        annotations:
          summary: "{{ $value }} conexões TCP pendentes"

      - alert: HighMemoryUsage
        expr: container_memory_usage_bytes{name="traefik"} / 1073741824 > 0.8
        for: 2m
        labels:
          severity: critical
        annotations:
          summary: "Memória do Traefik em {{ $value }}%"

Script de Monitoramento Simples (sem Prometheus)

Se não tem stack de monitoring instalado, use este script bash:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
#!/bin/bash
# File: ddos-monitor.sh

THRESHOLD_REQUESTS=10000
THRESHOLD_MEMORY=80
THRESHOLD_TCP=50000

while true; do
  # Taxa de requisições (logs do Traefik)
  REQ_RATE=$(tail -10000 /var/log/traefik/access.log | wc -l)
  
  # Consumo de memória do Traefik
  MEM_USAGE=$(docker stats traefik --no-stream --format "{{.MemPerc}}" | sed 's/%//')
  
  # Conexões TCP
  TCP_CONNS=$(netstat -an | grep ESTABLISHED | wc -l)

  echo "[$(date '+%Y-%m-%d %H:%M:%S')] Req/min: $REQ_RATE | Mem: ${MEM_USAGE}% | TCP: $TCP_CONNS"

  if (( $(echo "$REQ_RATE > $THRESHOLD_REQUESTS" | bc -l) )); then
    echo "⚠️ ALERTA: Taxa de requisições alta!"
    # Chamar webhook ou enviar notificação
    curl -X POST http://alertmanager:9093/api/v1/alerts \
      -H "Content-Type: application/json" \
      --data '{"alerts":[{"labels":{"alertname":"HighRequestRate"}}]}'
  fi

  sleep 60
done

Execute em background:

1
nohup ./ddos-monitor.sh > ddos-monitor.log 2>&1 &

📝 Exemplo: Um cliente meu detectou um DDoS em 2 minutos graças a alertas. Ativou Under Attack Mode e aumentou file descriptors. O site permaneceu online com latência aceitável. Sem alertas, o downtime teria sido de horas.

7. Exemplo Prático: Configuração Completa para Produção

Aqui está uma configuração completa de Docker Compose com todas as medidas aplicadas:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
version: '3.9'

services:
  traefik:
    image: traefik:v3.0.0  # Versão fixa, sem auto-update
    container_name: traefik
    restart: unless-stopped
    
    # File descriptors alto
    ulimits:
      nofile:
        soft: 65000
        hard: 65536
    
    environment:
      # Logs para monitoramento
      - TRAEFIK_LOG_LEVEL=WARN
      - TRAEFIK_ACCESSLOG=true
      - TRAEFIK_ACCESSLOG_FILEPATH=/var/log/traefik/access.log
      - TRAEFIK_ACCESSLOG_FORMAT=json
      
      # Métricas
      - TRAEFIK_METRICS_PROMETHEUS=true
      - TRAEFIK_METRICS_PROMETHEUS_ADDENTRYPOINTSLABELS=true
    
    ports:
      - "80:80"
      - "443:443"
      - "8080:8080"  # Dashboard (proteja com auth)
    
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock:ro
      - ./traefik-config.yaml:/etc/traefik/traefik.yaml:ro
      - ./certs:/certs:ro
      - /var/log/traefik:/var/log/traefik
    
    networks:
      - frontend

  app:
    image: seu-app:1.2.3  # Versão fixa
    container_name: app
    restart: unless-stopped
    
    ulimits:
      nofile:
        soft: 32000
        hard: 65536
    
    environment:
      - ENVIRONMENT=production
    
    labels:
      # Traefik auto-discovery
      - "traefik.enable=true"
      - "traefik.http.routers.app.rule=Host(`example.com`)"
      - "traefik.http.services.app.loadbalancer.server.port=3000"
    
    networks:
      - frontend

networks:
  frontend:
    driver: bridge

Arquivo traefik-config.yaml:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
global:
  checkNewVersion: false  # Não verificar atualizações
  sendAnonymousUsage: false

entryPoints:
  web:
    address: ":80"
    http:
      maxRequestBodyBytes: 2500000  # Limitar payload (anti-upload bomb)
  websecure:
    address: ":443"
    http:
      maxRequestBodyBytes: 2500000

api:
  insecure: false  # Proteja o dashboard
  dashboard: true

log:
  level: WARN

accessLog: {}

metrics:
  prometheus:
    entryPoint: metrics
    service: prometheus

providers:
  docker:
    endpoint: "unix:///var/run/docker.sock"
    exposedByDefault: false
    watch: true

Se você usa Nginx no lugar de Traefik, este é um exemplo equivalente para produção:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
version: '3.9'

services:
  nginx:
    image: nginx:1.27-alpine  # Versão fixa, sem auto-update
    container_name: nginx
    restart: unless-stopped

    ulimits:
      nofile:
        soft: 65000
        hard: 65536

    ports:
      - "80:80"
      - "443:443"

    volumes:
      - ./nginx/nginx.conf:/etc/nginx/nginx.conf:ro
      - ./nginx/conf.d:/etc/nginx/conf.d:ro
      - ./certs:/etc/nginx/certs:ro
      - /var/log/nginx:/var/log/nginx

    networks:
      - frontend

  app:
    image: seu-app:1.2.3
    container_name: app
    restart: unless-stopped

    ulimits:
      nofile:
        soft: 32000
        hard: 65536

    environment:
      - ENVIRONMENT=production

    expose:
      - "3000"

    networks:
      - frontend

networks:
  frontend:
    driver: bridge

Arquivo nginx/nginx.conf (base para alto volume de conexões):

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
user nginx;
worker_processes auto;
pid /var/run/nginx.pid;

events {
  worker_connections 8192;
  use epoll;
  multi_accept on;
}

http {
  sendfile on;
  tcp_nopush on;
  tcp_nodelay on;
  keepalive_timeout 30;
  keepalive_requests 1000;
  types_hash_max_size 2048;
  server_tokens off;

  # Limites para reduzir impacto de flood básico
  client_max_body_size 2m;
  client_body_timeout 10s;
  client_header_timeout 10s;

  log_format main '$remote_addr - $remote_user [$time_local] "$request" '
                  '$status $body_bytes_sent "$http_referer" '
                  '"$http_user_agent" "$http_x_forwarded_for"';

  access_log /var/log/nginx/access.log main;
  error_log /var/log/nginx/error.log warn;

  include /etc/nginx/mime.types;
  default_type application/octet-stream;

  upstream app_backend {
    server app:3000;
    keepalive 64;
  }

  server {
    listen 80;
    server_name _;

    location / {
      proxy_http_version 1.1;
      proxy_set_header Host $host;
      proxy_set_header X-Real-IP $remote_addr;
      proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
      proxy_set_header X-Forwarded-Proto $scheme;
      proxy_set_header Connection "";
      proxy_pass http://app_backend;
    }
  }
}

Dicas e Boas Práticas

  • 1. Rate Limiting no Cloudflare: Configure limite de 100 requisições/IP/minuto. Isso bloqueia automaticamente bots agressivos antes de chegar ao seu servidor.

  • 2. Manter Logs de Tráfego: Arquive os acessos em JSON para análise pós-ataque. Identifique padrões (IP origem, endpoint alvo, user-agent) para refinar regras futuras.

  • 3. Teste Suas Defesas Regularmente: Uma vez ao mês, simule um DDoS leve (com ferramenta como locust ou ab) e valide se alertas funcionam. Descobrir brechas em produção é caro.

  • 4. Redundância Geográfica: Se possível, distribua seu app em múltiplos datacenters. Um único DDoS não derruba tudo. Cloudflare oferece load balancing geográfico.

  • 5. Comunicação com Provedor: Se contratar suporte premium (Cloudflare Pro/Business), avise sobre seu plano de mitigação. Eles podem ativar proteções extras de forma mais rápida.

Resumo Objetivo

  • TCP Syncookies — habilitar no kernel com sysctl net.ipv4.tcp_syncookies=1 para bloquear SYN Flood sem alocar memória de forma indiscriminada.

  • File Descriptors no Docker — definir ulimits.nofile.soft: 65000 no docker-compose.yml para aceitar até 60.000 conexões simultâneas durante ataque.

  • Under Attack Mode (Cloudflare) — ativar manualmente em Security → Overview ou via API para forçar CAPTCHA em bots, bloqueando ~80% do tráfego malicioso.

  • Versão Fixa de Proxy — usar image: traefik:v3.0.0 em vez de latest para evitar que bugs introduzidos em atualizações automáticas derrubem a aplicação sob carga.

  • Novo Endereço IP — adicionar um IP secundário à VPS e usar exclusivamente internamente, deixando o antigo “preso” ao Cloudflare para isolar do atacante.

  • Monitoramento com Alertas — rastrear taxa de requisições, conexões TCP, memória e processos com Prometheus ou script bash simples; threshold crítico é > 10.000 req/min ou > 50.000 conexões TCP.

Leia Também

Referências