Quando uma aplicação começa a sair do ambiente de desenvolvimento e caminha para produção, a conversa muda. Já não basta “estar funcionando”: é necessário reduzir a superfície de ataque, proteger dados e entender claramente como o tráfego chega até o sistema. Aliás, isso deveria ser padrão no desenvolvimento de software.

Neste artigo, compartilho uma abordagem prática de segurança aplicada a uma aplicação web moderna, cobrindo infraestrutura, rede e aplicação, com decisões reais tomadas durante o processo.


1. Visão geral da arquitetura

A arquitetura utilizada segue um modelo bastante comum hoje:

  • Frontend: React + Vite
  • Backend: API Node.js rodando em uma VPS
  • Observabilidade: Grafana, Prometheus, Loki e Tempo
  • Banco de dados:

    • PostgreSQL
    • MongoDB
  • CDN / Proxy reverso: Cloudflare


2. Cloudflare como proxy reverso (primeira linha de defesa)

A Cloudflare atua como a porta de entrada exclusiva para a aplicação. Configuramos os registros DNS em modo proxied (a nuvem laranja), o que significa que nenhuma requisição chega diretamente ao nosso servidor sem passar antes pela rede global da Cloudflare.

Principais configurações ativas:

  1. Modo Proxy (Orange Cloud):

    • Ocultação de IP: O IP real da VPS (Origin IP) permanece invisível para o mundo externo, evitando ataques diretos.
    • CDN & Caching: Recursos estáticos são cacheados na borda, reduzindo drasticamente a carga no servidor e melhorando a latência para usuários em diferentes regiões.
  2. Criptografia End-to-End (SSL/TLS Full Strict):

    • Não basta ter HTTPS apenas para o usuário. Configuramos o modo Full (Strict).
    • Isso exige um certificado válido também no servidor de origem (origin CA), garantindo que o tráfego seja criptografado em ambas as pontas: Browser -> Cloudflare E Cloudflare -> Servidor.
  3. Firewall de Aplicação (WAF):

    • Regras gerenciadas que bloqueiam padrões comuns de ataque (como SQL Injection e XSS) antes mesmo de serem processados pela aplicação.
    • Bot Fight Mode: Ativado para desafiar ou bloquear tráfego automatizado suspeito e crawlers maliciosos.
  4. Regras de Page Rules:

    • Configurações agressivas de cache para rotas públicas.
    • Redirecionamentos automáticos de HTTP para HTTPS (Always Use HTTPS).

Essas camadas transformam a Cloudflare em um "escudo" que filtra a maior parte do ruído e tráfego malicioso, deixando o servidor livre para processar apenas requisições legítimas.


3. Firewall na infraestrutura

Além do proxy, configuramos um firewall no nível da VPS.

Isso atua como uma segunda camada de segurança. Caso alguém descubra o IP real da infraestrutura, o firewall impedirá qualquer conexão que não venha dos intervalos de IP da Cloudflare, bloqueando ataques diretos.

Objetivo

Garantir que:

  • Apenas tráfego legítimo chegue ao servidor
  • A API não seja acessível diretamente via IP público

Configuração aplicada

  • Portas abertas:

    • 80 (HTTP)
    • 443 (HTTPS)
  • Origem permitida:

    • Somente os IPs oficiais da Cloudflare

Com isso:

  • Requisições diretas para https://SEU_IP_PUBLICO são bloqueadas
  • Apenas tráfego que passa pela Cloudflare chega ao backend

Esse ponto costuma gerar confusão no início, mas é fundamental entender:

O firewall não bloqueia requisições HTTP, ele bloqueia origens de rede.

O navegador continua conseguindo acessar https://api.dominio.com porque:

  • A Cloudflare faz a requisição em nome do cliente
  • O servidor só “enxerga” o IP da Cloudflare

Camada Extra: Authenticated Origin Pulls (mTLS)

Um ponto avançado, mas importante, é configurar o Authenticated Origin Pulls. Isso garante que, mesmo que alguém descubra o IP real do seu servidor, ele não consiga realizar requisições diretamente, pois o servidor exigirá um certificado TLS que apenas a Cloudflare possui.


4. Segurança no Backend (camada de aplicação)

No backend, combinamos várias práticas:

4.1 Headers de segurança com Helmet

Utilizando o helmet, configuramos headers HTTP como:

  • X-Content-Type-Options: Previne ataques de "MIME sniffing", impedindo que o navegador interprete arquivos como algo diferente do declarado.
  • X-Frame-Options: Protege contra Clickjacking, bloqueando a renderização do site em iframes de outros domínios.
  • Referrer-Policy: Controla o quanto de informação de origem é enviada ao navegar para outros sites.
  • Content Security Policy (CSP)

Isso garante:

  • Aplicação consistente da política
  • Independência do client
  • Proteção contra XSS e carregamento de recursos não autorizados

4.2 Content Security Policy (CSP) na prática

Ajustamos a política para permitir apenas:

  • Scripts e estilos da própria aplicação
  • Conexões com:

    • API de produção
    • API de staging
    • Cloudinary
  • Imagens:

    • HTTPS
    • Domínio do Cloudinary

Esse controle fino evita:

  • Execução de scripts injetados
  • Vazamento de dados via requests não autorizados
  • Uso indevido de recursos externos

4.3 CORS restritivo

O backend aceita requisições somente de:

  • Frontend de produção
  • Frontend de staging

Nenhum wildcard (*) é utilizado. Isso impede que outros domínios maliciosos tentem consumir sua API via navegador sem autorização.


4.4 Autenticação, cookies e validação

Outras medidas importantes:

  • Cookies HttpOnly
  • Validação de input com class-validator e class-transformer
  • Rate limiting: Protege a aplicação contra ataques de força bruta e exaustão de recursos (DoS).
  • Sanitização de dados: Remove códigos maliciosos dos inputs antes de processá-los, prevenindo injeção de scripts (XSS).
  • Autenticação bem definida (sem exposição de tokens no client)

5. Segurança no Frontend

Embora a segurança real deva estar sempre no servidor, o frontend desempenha um papel crucial na prevenção de dados mal formatados e na experiência do usuário.

Validação rigorosa com Zod

Utilizamos Zod para validar todos os formulários e dados de entrada antes mesmo de serem enviados para a API.

  • Tipagem forte: Os schemas do Zod garantem que o dado esteja no formato esperado (ex: email válido, senha forte, campos obrigatórios).
  • Feedback imediato: O usuário sabe o que está errado sem precisar esperar o erro voltar do servidor.
  • Economia de recursos: Evita requisições inúteis para o backend com dados que já sabemos serem inválidos.

Importante: A validação no frontend é uma camada de UX e eficiência, não de segurança final. Um atacante pode ignorar o frontend e chamar a API diretamente. Por isso, a validação no backend é inegociável, independentemente do que é feito no client.


6. Upload seguro de imagens com Cloudinary

Desenhamos o fluxo de upload para evitar erros comuns:

Fluxo adotado

  1. O frontend solicita uma URL assinada ao backend
  2. O backend assina a requisição usando as credenciais
  3. O frontend faz upload direto para o Cloudinary
  4. Apenas a URL final é persistida no banco

Benefícios

  • Nenhuma chave sensível no frontend
  • Menor carga no backend
  • Uploads escaláveis
  • CSP facilmente controlável

7. Bancos de dados protegidos

MongoDB

  • Acesso restrito via IP whitelist
  • Apenas o IP da VPS autorizado

PostgreSQL

  • Conexão segura via TLS
  • Credenciais isoladas por ambiente (staging / production)

8. Observabilidade também é segurança

A stack de observabilidade permite:

  • Detectar padrões anormais (ex: aumento súbito de erros 401/403)
  • Identificar picos suspeitos (sinais de DDoS ou scan de portas)
  • Investigar erros rapidamente
  • Criar alertas proativos para falhas de login em massa

Segurança não é apenas prevenção, é também capacidade de resposta.


Conclusão

Endurecer uma aplicação para produção exige mais do que código limpo. Exige entendimento de rede, infraestrutura e comportamento real do tráfego.

Essa base não elimina todos os riscos, mas reduz drasticamente as chances de problemas graves e prepara o sistema para crescer de forma segura.

Se você está nesse estágio do projeto, vale a pena investir tempo nisso. O retorno vem em forma de estabilidade, previsibilidade e tranquilidade.