A Ordem da Defesa Importa Mais que o Inventário
A maioria dos servidores comprometidos não cai por falta de ferramenta — cai porque a postura defensiva foi montada depois de o serviço já estar em pé, na primeira tentativa de mitigar um incidente. Quando o atacante já está dentro do laço, qualquer configuração nova vira corrida.
Uma VPS endurecida desde o boot inverte o jogo: a sequência correta é firewall e kernel primeiro, runtime de contêiner depois, proxy reverso por último. Cada camada herda a postura da camada de baixo. Pular a base significa que o resto está apoiado em ar.
"Segurança não é o que você sabe — é o que você configura."
1. Firewall no Boot, Antes do Docker Existir
Em uma instalação típica de Ubuntu ou Debian, habilitar ufw com política default deny incoming e liberar apenas SSH é trivial. O detalhe que derruba a maioria das VPS aparece depois: ao instalar o Docker, o daemon manipula iptables diretamente e insere regras na chain DOCKER, anteriores às regras criadas pelo UFW.
O efeito prático: ao publicar uma porta com -p 5432:5432, o Postgres fica acessível na internet mesmo com o UFW "negando" aquela porta. O UFW está ativo, a regra existe — mas o pacote nunca chega até ela.
- Binde explícito em localhost: ao publicar portas para serviços internos, prefixe o host —
-p 127.0.0.1:5432:5432. Sem o IP, o bind é em0.0.0.0. - Chain DOCKER-USER: o Docker reserva essa chain justamente para regras administrativas que precisam executar antes do roteamento de contêineres. É o ponto correto para inserir um
DROPseletivo de origem.
2. Pinning de Versão do Proxy Reverso
Stacks como Coolify, Caprover ou setups manuais com Watchtower tendem a manter o proxy reverso (geralmente Traefik) sempre atualizado. A intenção é boa — patches de segurança aplicados sem intervenção. O problema é que o componente de borda é justamente o que não pode falhar em silêncio.
Uma release com regressão no Traefik não derruba apenas um serviço: ela tira do ar todos os domínios que dependem do roteamento. E descobrir isso no meio de um pico de tráfego é descobrir tarde.
- Tag fixa, nunca
latest: fixe a versão minor exata em uso (por exemplotraefik:v3.1.5) e suba uma versão por vez, validando em homologação antes de promover. - Auto-update desligado no proxy: em Coolify, desabilite a atualização automática especificamente para o serviço do proxy. Os serviços de aplicação podem manter o comportamento default; a borda, não.
3. O IP Real do Servidor Não Pode Vazar
Posicionar a aplicação atrás do Cloudflare só protege enquanto o IP de origem permanece desconhecido. Se o atacante descobre o IP real, ele simplesmente pula a camada — manda tráfego direto para o servidor e ignora o proxy.
Os vetores de vazamento são previsíveis e a maior parte é histórica:
- DNS histórico: serviços como SecurityTrails, DNSlytics e o Censys preservam registros A/AAAA antigos. Se em algum momento o domínio apontou direto para o IP, antes do Cloudflare entrar na frente, esse registro continua público.
- Subdomínios não-proxiados: um
direct.dominio.comcom a nuvem cinza (DNS-only) entrega o IP em uma consulta trivial. - E-mails enviados pela aplicação: cabeçalhos
Receivedde SMTP, links de tracking e webhooks de saída revelam o IP de origem se enviados diretamente pela VPS em vez de um provedor de e-mail externo.
A mitigação tem duas pernas. A primeira é rotacionar o IP — emitir um IP novo e descomissionar o antigo. A segunda, mais durável, é configurar o firewall para aceitar tráfego HTTP/HTTPS apenas dos ranges publicados pelo Cloudflare. Mesmo que o IP volte a vazar, o servidor responde só ao proxy.
4. Cloudflare Under Attack Mode Como Botão Real
O Under Attack Mode exibe um desafio JavaScript antes de qualquer request alcançar a origem. Bots simples, scripts em Python e ferramentas de carga não conseguem renderizar o JS — são bloqueados na borda. Usuários reais pagam um atraso de poucos segundos.
O recurso só protege se estiver acessível no momento certo. Duas posturas concretas:
Regra automática por threshold
Managed Challenge ou JS Challenge quando o tráfego ultrapassar a baseline. O objetivo não é bloquear pico legítimo — é cortar o pico anômalo antes que ele justifique intervenção manual.UAM como ação de incident response
5. SYN Cookies: Defesa no Kernel Contra SYN Flood
Um ataque SYN flood explora o handshake do TCP. O atacante envia um SYN, o servidor responde com SYN-ACK e aloca uma entrada na fila de conexões pendentes esperando o ACK final. O ACK nunca chega. A fila enche. Conexões legítimas começam a ser recusadas.
SYN cookies invertem essa dinâmica. Quando a fila está sob pressão, o kernel codifica o estado da conexão dentro do número de sequência inicial do SYN-ACK — derivado da tupla IP/porta mais uma chave secreta — e não aloca nada. Se o ACK legítimo voltar, o servidor recalcula o cookie, confirma a integridade e reconstrói o estado. Se não voltar, não há recurso desperdiçado.
Habilitar é uma linha em /etc/sysctl.conf:
net.ipv4.tcp_syncookies = 1— ativa o mecanismo somente sob pressão na fila, sem custo no caminho normal.net.ipv4.tcp_max_syn_backlog— aumenta a fila de meio estabelecimento antes do cookie entrar em ação.
6. File Descriptors no Contêiner
Cada conexão TCP, cada arquivo aberto, cada socket em estado transiente consome um file descriptor. O default herdado pelo contêiner costuma ser baixo — 1024 em muitas imagens — e basta um proxy sob carga moderada, um banco com pool grande ou um servidor de websocket para esbarrar nesse teto.
O sintoma é confuso: o serviço responde lento, retorna erros intermitentes de too many open files, e a métrica de CPU/RAM continua tranquila. Ajustar é declarativo:
- CLI:
--ulimit nofile=65536:65536nodocker run. - Compose: bloco
ulimits.nofilecomsofteharddefinidos explicitamente no serviço. - Validação: dentro do contêiner,
cat /proc/self/limitsmostra o valor efetivo — confirmar o que foi aplicado evita supor.
7. Alertas Que Disparam, Não Dashboards Que Decoram
O ponto frágil mais comum em VPS pequenas não é a ausência de métricas — é a ausência de alertas acionáveis. Gráficos bonitos no Grafana só ajudam se alguém estiver olhando. Um alerta no celular chega quando o servidor ainda dá para salvar.
Quatro sinais cobrem a maior parte dos cenários de degradação:
- RSS do processo do proxy: subida abrupta de memória residente do Traefik/Nginx normalmente antecede colapso por minutos.
- Contagem de processos do host: crescimento monotônico indica fork bomb ou loop em healthcheck que não está sendo coletado.
- Conexões em
SYN_RECV: é a assinatura direta de SYN flood — alertar quando o número passar de uma baseline conhecida torna o ataque visível antes do SSH cair. - Requests por segundo no proxy: diferenciar pico orgânico de pico anômalo só é possível com baseline histórica. Sem isso, qualquer pico parece igual.
Stacks adequadas para começo de operação: Netdata entrega alertas configurados a partir da instalação; Prometheus + Alertmanager oferece flexibilidade quando o volume justifica o esforço de operar a stack.