Pular para o conteúdo

TLS e certificados

Intermediário18 min de leituraredes
Antes disto:

Certificado expirado ainda é uma das causas mais bobas e mais frequentes de indisponibilidade — inclusive em empresas grandes. A boa notícia é que o problema está resolvido há anos: emissão e renovação automáticas por ACME, com monitoramento de expiração como rede de segurança. O que sobra é entender a cadeia, para diagnosticar quando algo foge do trilho.

O navegador confia em um punhado de autoridades raiz. Elas assinam intermediárias, que assinam o certificado do seu domínio. Para a validação funcionar, o servidor precisa entregar o certificado folha mais a cadeia intermediária — a raiz já está no cliente.

Janela do terminal
openssl s_client -connect loja.exemplo.com.br:443 -servername loja.exemplo.com.br < /dev/null \
| openssl x509 -noout -subject -issuer -dates
# a cadeia completa que o servidor entrega:
openssl s_client -showcerts -connect loja.exemplo.com.br:443 -servername loja.exemplo.com.br < /dev/null

O erro clássico: funciona no navegador (que sabe buscar a intermediária) e falha no curl, no cliente Java ou no Go. Sintoma de cadeia incompleta — o servidor não está enviando a intermediária.

O -servername importa: com SNI, vários certificados moram no mesmo IP, e testar sem ele devolve o certificado padrão, que quase nunca é o que você quer diagnosticar.

Let’s Encrypt e as ACME equivalentes emitem certificados de 90 dias, gratuitos e automatizáveis. Validação por HTTP-01 (arquivo na porta 80) ou DNS-01 (registro TXT — a única opção para curinga e para serviço interno sem exposição pública).

# cert-manager no Kubernetes: emite e renova sozinho
apiVersion: cert-manager.io/v1
kind: Certificate
metadata: { name: loja-tls, namespace: loja }
spec:
secretName: loja-tls
issuerRef: { name: letsencrypt-prod, kind: ClusterIssuer }
dnsNames: ["loja.exemplo.com.br", "www.loja.exemplo.com.br"]
Janela do terminal
certbot certonly --dns-cloudflare -d '*.exemplo.com.br' # curinga exige DNS-01
kubectl describe certificate loja-tls -n loja # eventos explicam falha de emissão

Use o ambiente de staging da autoridade enquanto configura: os limites de emissão do ambiente de produção são baixos e, uma vez atingidos, você fica horas sem poder emitir.

Configure o registro CAA no domínio para restringir quem pode emitir certificado para ele. É uma linha de DNS e fecha uma porta real.

Automatizar a renovação não dispensa monitorar a expiração — a automação também falha (permissão do DNS revogada, validação bloqueada por firewall, disco cheio).

Janela do terminal
# verificação simples, para rodar como check periódico
fim=$(openssl s_client -connect loja.exemplo.com.br:443 -servername loja.exemplo.com.br </dev/null 2>/dev/null \
| openssl x509 -noout -enddate | cut -d= -f2)
dias=$(( ( $(date -d "$fim" +%s) - $(date +%s) ) / 86400 ))
echo "expira em $dias dias"

Alerte com 30 dias (ticket) e 7 dias (página). E monitore o certificado servido na porta, não o arquivo no disco: o caso mais comum de expiração com automação funcionando é o serviço que renovou o arquivo e nunca recarregou a configuração.

Não esqueça dos certificados que ninguém vê: cliente de banco, mTLS interno, webhook, integração com parceiro, e o certificado da CA interna — que expira em anos e derruba tudo de uma vez.

  • No balanceador / CDN: mais simples, com gestão de certificado centralizada. O tráfego para trás é interno.
  • Ponta a ponta até a aplicação: exigido quando a política proíbe tráfego em claro em qualquer trecho, ou quando a aplicação precisa do certificado do cliente.
  • Reencriptado: encerra na borda para inspecionar, e abre nova conexão TLS para trás. É o meio-termo mais comum em ambiente regulado.

Se a rede entre borda e aplicação é compartilhada, encerre na borda e reencripte. E, em qualquer arranjo, redirecione HTTP para HTTPS e envie HSTS — com cuidado, porque HSTS com preload é praticamente irreversível.

No mTLS, o cliente também apresenta certificado, e a identidade deixa de depender do IP. Fazer isso à mão significa emitir, distribuir, rotacionar e revogar certificado para cada serviço — trabalhoso o bastante para ser feito mal.

Por isso, na prática, mTLS interno vem de uma camada que automatiza: um service mesh, o cert-manager com CA interna, ou SPIFFE. Adote quando houver requisito real (regulação, rede não confiável, segmentação forte), não por estética de arquitetura.

  • Certificado expirado — automatize e monitore o que é servido.
  • Cadeia incompleta — funciona no navegador, quebra no cliente HTTP.
  • Nome errado: certificado para exemplo.com.br não cobre www.exemplo.com.br; o curinga *.exemplo.com.br não cobre a.b.exemplo.com.br nem o ápice.
  • Relógio errado no cliente ou no servidor: tudo passa a ser inválido.
  • CA interna não distribuída para todos os clientes (container base sem os certificados, JVM com truststore próprio).
  • Protocolo e cifra antigos ainda habilitados — desligue TLS 1.0/1.1, mantenha 1.2 e 1.3.
  • Chave privada versionada no Git. Se aconteceu, revogue o certificado e emita outro; apagar o commit não basta.

Próximo passo: com nome e criptografia resolvidos, distribua a carga em Balanceamento de carga. O passo a passo em cluster está em Expor serviço com TLS.