Headers de segurança essenciais
Conjunto básico de headers que toda aplicação deveria ter:
# /etc/nginx/conf.d/security-headers.conf
# Incluir em todos os server blocks: include /etc/nginx/conf.d/security-headers.conf;
# Forçar HTTPS por 1 ano (HSTS)
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always;
# Prevenir clickjacking: não permitir incorporação em iframe
add_header X-Frame-Options "SAMEORIGIN" always;
# Prevenir MIME sniffing
add_header X-Content-Type-Options "nosniff" always;
# Controlar informações no Referer header
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
# Desabilitar FLoC/Topics API e outras features sensíveis
add_header Permissions-Policy "camera=(), microphone=(), geolocation=(), interest-cohort=()" always;
# Remover header Server (não revelar versão do Nginx)
server_tokens off;
# X-XSS-Protection (legacy — navegadores modernos ignoram)
add_header X-XSS-Protection "1; mode=block" always;Content Security Policy (CSP)
CSP é o header mais poderoso, define de onde cada tipo de recurso pode ser carregado:
# CSP básica para API (sem frontend):
add_header Content-Security-Policy "default-src 'none'; frame-ancestors 'none';" always;
# CSP para aplicação web completa:
add_header Content-Security-Policy "
default-src 'self';
script-src 'self' 'nonce-NONCE_AQUI' https://cdn.jsdelivr.net;
style-src 'self' 'unsafe-inline' https://fonts.googleapis.com;
img-src 'self' data: https://images.exemplo.com;
font-src 'self' https://fonts.gstatic.com;
connect-src 'self' https://api.seudominio.com.br wss://api.seudominio.com.br;
frame-ancestors 'none';
form-action 'self';
upgrade-insecure-requests;
" always;
# CSP Report-Only (testar sem bloquear — reportar violações):
add_header Content-Security-Policy-Report-Only "
default-src 'self';
report-uri https://api.seudominio.com.br/csp-report;
" always;
# Diretivas importantes:
# default-src 'self': apenas recursos do próprio domínio por padrão
# script-src 'nonce-XYZ': permitir apenas scripts com o nonce correto
# frame-ancestors 'none': substituiu X-Frame-Options (mais moderno)
# upgrade-insecure-requests: converter http:// para https:// automaticamenteConfigurar CORS com segurança
CORS (Cross-Origin Resource Sharing) para APIs acessadas por domínios diferentes:
# /etc/nginx/conf.d/cors.conf — CORS para API
# ATENÇÃO: nunca use Access-Control-Allow-Origin: * para APIs autenticadas
# Map para validar origins permitidas
map $http_origin $allowed_origin {
default "";
"https://app.seudominio.com.br" "https://app.seudominio.com.br";
"https://admin.seudominio.com.br" "https://admin.seudominio.com.br";
# Desenvolvimento:
"http://localhost:3000" "http://localhost:3000";
}
server {
location /api/ {
# Responder preflight OPTIONS
if ($request_method = 'OPTIONS') {
add_header Access-Control-Allow-Origin $allowed_origin;
add_header Access-Control-Allow-Methods "GET, POST, PUT, DELETE, OPTIONS";
add_header Access-Control-Allow-Headers "Authorization, Content-Type, X-Requested-With";
add_header Access-Control-Allow-Credentials "true";
add_header Access-Control-Max-Age 86400;
add_header Content-Length 0;
return 204;
}
# Headers CORS para requisições normais
add_header Access-Control-Allow-Origin $allowed_origin always;
add_header Access-Control-Allow-Credentials "true" always;
proxy_pass http://127.0.0.1:3000;
}
}Ocultar informações do servidor
Reduza a superfície de ataque ocultando versões de software:
# nginx.conf — bloco http {}
# Remover versão do Nginx dos headers e páginas de erro
server_tokens off;
# Remover header X-Powered-By do backend (Node.js)
# (o Nginx não pode remover headers do backend diretamente, mas pode sobrescrever)
proxy_hide_header X-Powered-By;
proxy_hide_header Server;
# Adicionar um Server header neutro:
add_header Server "VPS" always;
# Remover header X-AspNet-Version (se usar .NET):
proxy_hide_header X-AspNet-Version;
proxy_hide_header X-AspNetMvc-Version;
# No backend Node.js/Express — remover X-Powered-By:
# app.disable('x-powered-by')
# Ou usar helmet: app.use(helmet())
# Verificar headers retornados:
curl -I https://api.seudominio.com.br/
# Deve mostrar Server: VPS (não "nginx/1.25.3")Testar e verificar os headers
Ferramentas para validar que os headers estão configurados corretamente:
# Verificar headers com curl:
curl -s -I https://seudominio.com.br | grep -i "strict-transport\|x-frame\|content-security\|x-content"
# Teste online:
# https://securityheaders.com — análise completa com nota A-F
# https://observatory.mozilla.org — análise da Mozilla
# Verificar CSP com navegador (DevTools):
# F12 → Console → ver erros "Refused to load..." de violações CSP
# Script para verificar múltiplos headers de uma vez:
for HEADER in "Strict-Transport-Security" "X-Frame-Options" "X-Content-Type-Options" \
"Content-Security-Policy" "Referrer-Policy" "Permissions-Policy"; do
VALUE=$(curl -s -I https://seudominio.com.br | grep -i "^${HEADER}:" | tr -d '\r')
if [ -z "$VALUE" ]; then
echo "❌ AUSENTE: $HEADER"
else
echo "✅ $VALUE"
fi
done