Toda vez que você acessa um site com o cadeado na barra de endereço, um processo de negociação criptográfica acontece em milissegundos antes de qualquer dado da aplicação ser transmitido. Esse processo do protocolo TLS — o handshake — estabelece qual algoritmo de criptografia as partes vão usar, verifica a identidade do servidor através de um certificado digital, e deriva as chaves que vão proteger toda a comunicação subsequente.
O que parece uma simples verificação de segurança é, na prática, uma coreografia precisa de criptografia de chave pública, acordos de chave efêmeros, funções de derivação de chave e autenticação de mensagens. Cada passo existe por uma razão específica, e omitir ou implementar qualquer um incorretamente cria vulnerabilidades que atacantes exploram.
O TLS (Transport Layer Security) é o protocolo criptográfico que protege praticamente toda a comunicação segura na internet — HTTPS, SMTPS, IMAPS, conexões de banco de dados, APIs REST, e muitos outros protocolos. A versão atual, TLS 1.3 (RFC 8446, 2018), é o resultado de décadas de ataques documentados e respostas técnicas: cada vulnerabilidade que quebraram versões anteriores levou a mudanças de design que a versão seguinte incorporou.
Neste artigo, você vai entender como o TLS funciona em nível técnico — não apenas o que ele faz, mas por que cada componente existe. Cobrimos a estrutura em camadas do protocolo, o handshake passo a passo nas versões 1.2 e 1.3, os algoritmos criptográficos e por que cada um foi escolhido, os componentes de suporte como certificados, OCSP, SNI e ALPN, e como configurar cada elemento de forma segura. Se você implementa, configura ou audita sistemas que usam TLS, este guia tem o que você precisa.
A evolução que explica o estado atual do TLS
O TLS não surgiu de projeto de engenharia especulativo — surgiu de ataques reais que quebraram protocolos anteriores. Entender essa linha do tempo explica por que o TLS 1.3 tem o design que tem.
SSL 2.0 (1995) — a primeira versão pública tinha múltiplas vulnerabilidades críticas: o handshake não protegia contra tampering, o protocolo não verificava a integridade de mensagens de forma adequada, e o encerramento de sessão podia ser forçado por atacantes. O SSL 2.0 foi formalmente deprecado pela RFC 6176 em 2011, mas muitas implementações o suportavam muito depois disso.
SSL 3.0 (1996) — o redesign corrigiu os problemas do 2.0, mas introduziu o modo CBC (Cipher Block Chaining) com padding que eventualmente levaria ao ataque POODLE em 2014. O SSL 3.0 foi deprecado pela RFC 7568 em 2015.
TLS 1.0 (1999) — tecnicamente superior ao SSL 3.0 mas com o modo CBC implementado de forma vulnerável ao ataque BEAST (2011). O BEAST explorava a predictabilidade do IV (Initialization Vector) no CBC do TLS 1.0 para recuperar texto plano incrementalmente.
TLS 1.1 (2006) — adicionou IVs explícitos para mitigar o BEAST, mas não foi amplamente adotado. A maioria das implementações pulou diretamente para o TLS 1.2.
TLS 1.2 (2008) — introduziu suporte a cipher suites AEAD (Authenticated Encryption with Associated Data), que eliminam toda uma classe de vulnerabilidades de padding oracle. Adicionou SHA-256, melhorou a extensibilidade, e separou os algoritmos de hash de autenticação dos de cifragem. TLS 1.2 com cipher suites AEAD modernas ainda é seguro quando configurado corretamente.
TLS 1.3 (2018) — redesenhou o handshake para 1-RTT, removeu todas as cipher suites não-AEAD, tornou ECDHE obrigatório (Perfect Forward Secrecy não é mais opcional), e criptografou a maior parte do handshake que antes era visível em texto claro.
💡 Dica: A evolução do TLS segue um padrão consistente: criptógrafos documentam um ataque teórico ou prático, implementadores confirmam a exploração, e a próxima versão do protocolo elimina a construção vulnerável. O TLS 1.3 não apenas corrigiu vulnerabilidades conhecidas — removeu opcionalidade que permitia que implementações escolhessem configurações inseguras. Com TLS 1.3, é muito mais difícil configurar incorretamente do que com TLS 1.2.
A arquitetura em camadas do TLS
O TLS opera em duas subcamadas que têm responsabilidades distintas dentro do protocolo.
A camada de registro (Record Layer)
A Record Layer é a fundação sobre a qual tudo mais opera. Ela recebe dados da aplicação (ou de outros subprotocolos TLS) e os processa em quatro etapas:
Fragmentação — divide dados maiores em fragmentos de até 2¹⁴ bytes (16.384 bytes). A fragmentação não é apenas limitação técnica — permite que dados sejam processados em chunks gerenciáveis e que registros individuais possam ser verificados e autenticados independentemente.
Compressão — opcional e raramente usada em implementações modernas. Os ataques CRIME (2012) e BREACH (2013) demonstraram que comprimir dados antes de criptografar vaza informações sobre o texto plano através do tamanho do texto cifrado. O TLS 1.3 removeu o suporte a compressão completamente.
Proteção criptográfica — aplica o algoritmo AEAD negociado no handshake. A proteção AEAD garante simultaneamente confidencialidade (o conteúdo é ilegível sem a chave) e autenticidade (qualquer modificação do registro criptografado é detectável). Uma mensagem que falha na verificação de autenticação é descartada, não tentada de descriptografar.
Transmissão — o registro protegido recebe um header com tipo de conteúdo, versão e comprimento, e vai para a camada TCP/IP.
Os subprotocolos da camada de handshake
Sobre a Record Layer operam quatro subprotocolos:
Handshake Protocol — gerencia o estabelecimento da conexão: negociação de versão e cipher suite, autenticação via certificados, e acordo de chave. É o subprotocolo mais complexo e o que determina a postura de segurança da conexão.
Alert Protocol — comunica condições de erro e avisos. Alertas têm nível (warning ou fatal) e descrição (handshake_failure, certificate_expired, decrypt_error, etc.). Um alerta fatal encerra a conexão imediatamente; alertas de aviso permitem que a conexão continue em alguns casos.
Change Cipher Spec Protocol — no TLS 1.2, o cliente e o servidor enviam um registro ChangeCipherSpec para sinalizar que estão prontos para iniciar criptografia com as chaves derivadas. No TLS 1.3, esse mecanismo explícito desapareceu — a transição para comunicação criptografada é implícita.
Application Data Protocol — carrega os dados da aplicação (o HTML de um site, os resultados de uma API, etc.) depois que o handshake estabeleceu a sessão segura. A Application Data só flui após o handshake completar com sucesso.
O handshake TLS 1.2: o processo clássico
O handshake TLS 1.2 requer 2 round-trips antes que dados da aplicação possam ser transmitidos. Cada mensagem tem função específica no estabelecimento de confiança e derivação de chaves.
Fase 1: hello e negociação
Cliente Servidor
| |
|── ClientHello ──────────────────────────────>|
| client_random (32 bytes) |
| cipher_suites: [TLS_ECDHE_RSA_WITH_AES_ |
| 256_GCM_SHA384, TLS_ECDHE_RSA_WITH_ |
| AES_128_GCM_SHA256, ...] |
| extensions: [SNI, supported_groups, |
| signature_algorithms, ...] |
| |
|<─────────────────────────── ServerHello ─────|
| server_random (32 bytes) |
| cipher_suite: TLS_ECDHE_RSA_WITH_AES_ |
| 256_GCM_SHA384 (selecionado) |O client_random e o server_random são 32 bytes de dados criptograficamente aleatórios que ambas as partes geram independentemente. Esses valores são misturados com o pre-master secret durante a derivação de chave — garantindo que chaves de sessão sejam únicas mesmo se o mesmo pre-master secret fosse reutilizado (o que não acontece com ECDHE, mas a proteção existe como defesa em profundidade).
A lista de cipher suites no ClientHello tem ordem de preferência — o cliente lista em ordem decrescente de preferência. O servidor seleciona a cipher suite mais preferida do cliente que ele também suporta.
Fase 2: certificado e troca de chave
|<──────────────────────────── Certificate ─────|
| cadeia de certificados do servidor |
| |
|<──────────────────────── ServerKeyExchange ───|
| parâmetros ECDHE: curva elíptica, ponto |
| público efêmero do servidor |
| assinatura (com chave privada RSA do cert.) |
| |
|<──────────────────────── ServerHelloDone ─────|O ServerKeyExchange existe apenas quando cipher suites ECDHE ou DHE são usadas — que é o caso em qualquer configuração segura moderna. O servidor gera um par de chaves ECDHE efêmero para essa sessão específica e envia o ponto público da curva elíptica.
A assinatura sobre os parâmetros ECDHE é o elemento crítico de segurança aqui: o servidor assina os parâmetros ECDHE com sua chave privada RSA (a chave do certificado). Isso prova que os parâmetros ECDHE vieram do dono legítimo do certificado — não de um Man-in-the-Middle que interceptou e substituiu os parâmetros.
Fase 3: resposta do cliente e estabelecimento
|── ClientKeyExchange ─────────────────────────>|
| ponto público ECDHE efêmero do cliente |
| |
|── ChangeCipherSpec ──────────────────────────>|
|── Finished ──────────────────────────────────>|
| MAC sobre todas as mensagens do handshake |
| (criptografado com chaves de sessão) |
| |
|<──────────────────────── ChangeCipherSpec ────|
|<──────────────────────── Finished ────────────|Com o ponto público ECDHE do cliente e o ponto público do servidor, ambas as partes calculam independentemente o mesmo segredo compartilhado via matemática de curva elíptica — sem que esse segredo tenha trafegado pela rede. Esse é o milagre do Diffie-Hellman: duas partes chegam ao mesmo segredo sem nunca transmiti-lo.
O segredo compartilhado ECDHE combinado com client_random e server_random alimenta uma PRF (Pseudo-Random Function) que deriva múltiplas chaves de sessão: chave de cifragem do cliente, chave de cifragem do servidor, e chaves de MAC (no TLS 1.2 sem AEAD, o MAC é separado).
O Finished é a mensagem mais importante do handshake: contém um MAC sobre todas as mensagens trocadas até aquele ponto, criptografado com as chaves de sessão recém-derivadas. Se qualquer mensagem do handshake foi modificada por um atacante, os MACs não vão conferir e a conexão falha — protegendo contra manipulação retroativa do handshake.
O handshake TLS 1.3: redesenhado para velocidade e segurança
O TLS 1.3 cortou o handshake para 1-RTT e criptografou muito mais do processo. A diferença mais visível é que o servidor responde com dados criptografados muito antes no processo.
Cliente Servidor
|── ClientHello ──────────────────────────────>|
| versão, cipher_suites, |
| key_share (parâmetros ECDHE do cliente) |
| supported_versions, sig_algs |
| |
|<─────────────────── ServerHello ─────────────|
| key_share (parâmetros ECDHE do servidor) |
| |
|<────────────── {EncryptedExtensions} ────────|
|<────────────────────── {Certificate} ────────|
|<──────────────── {CertificateVerify} ────────|
|<────────────────────────── {Finished} ───────|
| |
|── {Finished} ──────────────────────────────> |
| |
|── {Application Data} ──────────────────────> |
|<────────────────────── {Application Data} ───|As mensagens entre {} já chegam criptografadas. Depois do ServerHello, que estabelece a shared secret via key_share, o servidor pode derivar chaves imediatamente e começar a criptografar. O certificado, a verificação do certificado e o Finished chegam ao cliente já criptografados.
Por que isso importa além da velocidade: em TLS 1.2, o certificado do servidor trafegava em texto claro, revelando a identidade do servidor a qualquer observador passivo. Em TLS 1.3, o certificado já vai criptografado — alguém que monitora o tráfego vê apenas o SNI (Server Name Indication) no ClientHello e os parâmetros do handshake público, não o certificado completo.
Mudanças estruturais do TLS 1.3
Remoção de cipher suites legacy — o TLS 1.3 não suporta RSA para troca de chaves, CBC (qualquer mode), RC4, DES, 3DES, MD5 em qualquer contexto, e SHA-1 em certificados. Apenas 5 cipher suites existem no TLS 1.3, todas AEAD:
- TLS_AES_128_GCM_SHA256
- TLS_AES_256_GCM_SHA384
- TLS_CHACHA20_POLY1305_SHA256
- TLS_AES_128_CCM_SHA256
- TLS_AES_128_CCM_8_SHA256 (uso limitado)
ECDHE obrigatório — sem exceção ou fallback. Perfect Forward Secrecy não é opcional.
Derivação de chave com HKDF — o TLS 1.3 usa HKDF (HMAC-based Key Derivation Function) em vez da PRF ad-hoc do TLS 1.2. HKDF tem propriedades de segurança bem analisadas formalmente.
⚠️ Atenção: O 0-RTT (early data) do TLS 1.3 permite enviar dados da aplicação antes do handshake completar, usando uma chave derivada de uma sessão anterior. Isso elimina a latência do handshake em reconexões mas sacrifica proteção contra replay attacks — o servidor não pode distinguir dados 0-RTT legítimos de uma captura replay. Use 0-RTT apenas para operações idempotentes (GET requests) e nunca para operações que modificam estado (POST, PUT, DELETE) ou que carregam informações sensíveis.
Algoritmos criptográficos: a escolha de cada componente
Cifragem simétrica: AES-GCM e ChaCha20-Poly1305
Após o handshake estabelecer chaves de sessão, a cifragem simétrica protege todos os dados da aplicação. O TLS moderno usa exclusivamente modos AEAD (Authenticated Encryption with Associated Data) — que garantem tanto confidencialidade quanto integridade em uma única operação.
AES-GCM (Galois/Counter Mode) combina AES em modo CTR (Counter) para cifragem com GHASH para autenticação. AES-256-GCM usa chave de 256 bits; AES-128-GCM usa 128 bits. Em hardware com instruções AES-NI (presente em praticamente todos os processadores x86-64 e ARM modernos), AES-GCM é extremamente eficiente — throughput de dezenas de gigabits por segundo por core.
A principal fragilidade do AES-GCM é a catastrophic failure em caso de reutilização de nonce: reutilizar o mesmo par (chave, nonce) duas vezes expõe o keystream e permite recuperar o texto plano e a chave de autenticação. O TLS resolve isso gerenciando o nonce como um contador que incrementa a cada registro — nunca reutilizando.
ChaCha20-Poly1305 combina a cifra de stream ChaCha20 com o authenticator Poly1305. Mais rápido que AES-GCM em hardware sem instruções AES-NI (dispositivos móveis mais antigos, IoT, sistemas embarcados). Em hardware com AES-NI, AES-GCM é tipicamente mais rápido. A combinação ChaCha20-Poly1305 tem a vantagem adicional de ser mais resistente a timing attacks de implementação — uma categoria de vulnerabilidade que cifras de bloco como AES têm historicamente sofrido em implementações de software.
Troca de chave: ECDHE e a matemática das curvas elípticas
ECDHE (Elliptic Curve Diffie-Hellman Ephemeral) resolve dois problemas simultâneos: como duas partes derivam uma chave secreta compartilhada sem transmiti-la, e como garantir que o comprometimento da chave privada do servidor não expõe sessões passadas.
A matemática das curvas elípticas usa a estrutura algébrica de curvas da forma y² = x³ + ax + b sobre corpos finitos. A operação fundamental é a “multiplicação escalar” de um ponto da curva por um número inteiro — uma operação fácil de computar mas praticamente irreversível (o problema do logaritmo discreto em curvas elípticas).
As curvas mais usadas no TLS:
X25519 — curva de Bernstein com 128 bits de segurança. Resistente a implementações vulneráveis por design (sem condicionais baseadas em segredo, sem divisões que dependem do valor), extremamente eficiente, e adotada como a curva preferida no TLS 1.3.
P-256 (secp256r1) — curva da NIST com 128 bits de segurança. Amplamente suportada e auditada, mas com algumas preocupações sobre os parâmetros da curva serem escolhidos de forma não completamente transparente.
P-384 (secp384r1) — curva da NIST com 192 bits de segurança. Usada em contextos que requerem segurança maior, como ambientes governamentais.
O “Ephemeral” em ECDHE significa que o par de chaves Diffie-Hellman é gerado especificamente para essa sessão e descartado após o uso. Isso proporciona Perfect Forward Secrecy: mesmo que a chave privada RSA do certificado seja comprometida anos depois, sessões passadas usaram chaves ECDHE efêmeras que não existem mais — não há material para descriptografar.
Funções de hash e derivação de chave
SHA-256 e SHA-384 servem como funções de hash criptográficas no TLS — inputs para a PRF (TLS 1.2) e para o HKDF (TLS 1.3), e como algoritmo de assinatura (RSA-SHA256, ECDSA-P256-SHA256).
HKDF (HMAC-based Key Derivation Function) — o TLS 1.3 usa HKDF para derivar todas as chaves a partir do segredo compartilhado ECDHE. HKDF tem duas fases: extract (combina o segredo com um salt para produzir um “pseudo-random key”) e expand (deriva chaves de comprimento arbitrário do PRK com identificadores de contexto distintos). A derivação de múltiplas chaves (handshake keys, application keys, resumption keys) de um único segredo compartilhado via HKDF garante que as chaves são independentes entre si.
Certificados digitais e a cadeia de confiança
A estrutura X.509
Certificados TLS seguem o padrão X.509 — um formato definido em ASN.1 que especifica a estrutura de informações que um certificado carrega. Os campos mais relevantes para segurança:
Subject — identidade do dono do certificado: Common Name (CN), Organization (O), Country (C). Para certificados DV (Domain Validation), o CN ou o Subject Alternative Name (SAN) contém o nome de domínio.
Subject Alternative Name (SAN) — extensão que lista todos os nomes de domínio que o certificado cobre. O CN foi historicamente usado para esse fim, mas os browsers modernos ignoram o CN se SAN estiver presente. Wildcards (*.example.com) cobrem um nível de subdomínio. Um certificado pode ter múltiplos SANs.
Public Key — a chave pública do dono, que corresponde à chave privada armazenada seguramente no servidor.
Validity Period — Not Before e Not After. Certificados modernos têm validade máxima de 398 dias (Apple impôs esse limite para Safari em 2020; Chrome seguiu). Let’s Encrypt emite certificados de 90 dias.
Signature — a assinatura digital da CA que emitiu o certificado, usando a chave privada da CA. Qualquer modificação do certificado invalida a assinatura.
Key Usage e Extended Key Usage — extensões que especificam para que fins a chave pode ser usada. Um certificado com EKU “TLS Web Server Authentication” pode ser usado para TLS; um com apenas “Email Protection” não deveria funcionar como certificado de servidor TLS em browsers modernos.
A cadeia de confiança
Browsers e sistemas operacionais vêm com um conjunto de certificados Root CA pré-instalados — as raízes de confiança. Nenhuma Root CA emite certificados de servidor diretamente: elas emitem certificados para Intermediate CAs, que emitem certificados para os servidores.
DigiCert Root CA G5
└── DigiCert TLS RSA SHA256 2020 CA1 (Intermediate)
└── example.com (End-entity certificate)
Quando um browser se conecta a example.com, verifica:
- O certificado de example.com foi assinado pela Intermediate CA
- O certificado da Intermediate CA foi assinado pela Root CA
- A Root CA está na lista de confiança pré-instalada
Se qualquer link da cadeia falha — certificado expirado, assinatura inválida, CA não confiável — o browser exibe um aviso de segurança.
Por que Intermediates existem: Root CAs guardam suas chaves privadas em HSMs (Hardware Security Modules) offline, usadas apenas para assinar certificados de Intermediate CA raramente. Se uma Root CA tivesse sua chave privada comprometida, toda a PKI estaria comprometida. Ao usar Intermediates, uma CA comprometida pode ser revogada sem afetar as outras.
Certificate Transparency: o log público
Desde 2018, o Chrome exige que certificados tenham SCTs (Signed Certificate Timestamps) — provas de que o certificado foi registrado em pelo menos dois logs de Certificate Transparency públicos antes de ser aceito.
Certificate Transparency cria um sistema onde qualquer certificado emitido para qualquer domínio aparece em logs públicos auditáveis. Isso permite que operadores de domínio monitorem se CAs estão emitindo certificados não autorizados para seus domínios — uma vulnerabilidade de ataque que, sem CT, era difícil de detectar.
A ferramenta crt.sh permite consultar todos os certificados emitidos para um domínio:
# Todos os certificados emitidos para example.com e subdomínios
curl -s "https://crt.sh/?q=%.example.com&output=json" | \
jq '.[].name_value' | sort -uExtensões TLS: SNI, ALPN, OCSP Stapling
SNI (Server Name Indication)
Sem SNI, um servidor com um único endereço IP só poderia servir um certificado TLS — porque a seleção do certificado precisa acontecer no handshake, antes que o HTTP Host header seja transmitido.
SNI é uma extensão do ClientHello que transmite o hostname de destino no início do handshake, antes de qualquer criptografia. O servidor usa esse valor para selecionar o certificado correto entre múltiplos certificados configurados no mesmo IP.
ClientHello:
extensions:
– server_name: “app.example.com” # SNI
– supported_versions: [TLS 1.3, TLS 1.2]
– key_share: [X25519 …]
A implicação de privacidade: o SNI trafega em texto claro em TLS 1.2 e na maior parte de TLS 1.3 (embora o handshake posterior seja criptografado, o SNI no ClientHello permanece visível). Um observador de rede vê para qual domínio o usuário está estabelecendo conexão mesmo sem poder ler o conteúdo.
O ECH (Encrypted Client Hello) é uma extensão proposta que criptografa o ClientHello completo, incluindo o SNI. O RFC de ECH foi publicado em 2023 e a adoção está crescendo — Cloudflare e Mozilla suportam ECH. Quando ECH se tornar amplamente adotado, a única metadata visível de uma conexão TLS será o servidor fronting público, não o destino real.
ALPN (Application-Layer Protocol Negotiation)
ALPN permite que cliente e servidor negociem qual protocolo de aplicação vão usar dentro da conexão TLS — tudo dentro do handshake, sem round-trips adicionais.
Os valores mais comuns de ALPN:
- “http/1.1” — HTTP/1.1
- “h2” — HTTP/2
- “h3” — HTTP/3 (sobre QUIC, não TLS puro)
- “acme-tls/1” — protocolo do ACME para obtenção de certificados (usado por Let’s Encrypt)
A negociação ALPN no handshake é o que permite que um mesmo servidor escutando na porta 443 suporte tanto HTTP/1.1 quanto HTTP/2 — o protocolo é acordado no TLS, antes de qualquer HTTP ser transmitido.
OCSP Stapling
OCSP (Online Certificate Status Protocol) permite verificar em tempo real se um certificado foi revogado. Sem OCSP Stapling, o browser faz uma requisição à CA para cada certificado — adicionando latência e revelando quais sites o usuário visita à CA.
Com OCSP Stapling, o servidor contata periodicamente a CA para obter uma resposta OCSP assinada (“este certificado é válido”) e inclui essa resposta no TLS handshake. O browser recebe a prova de não-revogação diretamente do servidor — mais rápido e sem revelar navegação à CA.
Configuração de OCSP Stapling no nginx:
server {
listen 443 ssl;
ssl_certificate /etc/ssl/certs/example.com.crt;
ssl_certificate_key /etc/ssl/private/example.com.key;
ssl_trusted_certificate /etc/ssl/certs/ca-chain.crt;
# OCSP Stapling
ssl_stapling on;
ssl_stapling_verify on;
# Resolver para consultar a CA (necessário para buscar a resposta OCSP)
resolver 8.8.8.8 8.8.4.4 valid=300s;
resolver_timeout 5s;
}Perfect Forward Secrecy: o princípio que muda tudo
Perfect Forward Secrecy garante que comprometer a chave privada do servidor hoje não permite descriptografar conversas passadas capturadas. Esta propriedade é consequência direta do uso de chaves ECDHE efêmeras.
Sem PFS (como em configurações com RSA puro para troca de chave, removido no TLS 1.3):
1. Atacante captura tráfego TLS e armazena (captura passiva)
2. Anos depois, consegue a chave privada RSA do servidor
3. Usa a chave privada para descriptografar o pre-master secret de cada sessão capturada
4. Deriva as chaves de sessão e descriptografa todos os dados
Com ECDHE:
1. Atacante captura tráfego TLS e armazena
2. Anos depois, consegue a chave privada RSA do servidor
3. A chave RSA não ajuda: o segredo foi derivado via ECDHE com chaves efêmeras descartadas após cada sessão
4. Sem as chaves ECDHE efêmeras (que não existem mais), não há como descriptografar as sessões capturadas
Organizações como a NSA documentaram práticas de “harvest now, decrypt later” — capturar tráfego criptografado hoje com intenção de descriptografar quando computação quântica ou outros avanços permitirem. PFS limita drasticamente o valor desse modelo de ataque para comunicações TLS modernas.
Configuração de referência para TLS 1.2 e 1.3
Nginx: configuração segura completa
server {
listen 443 ssl http2;
server_name example.com;
ssl_certificate /etc/ssl/certs/example.com.pem;
ssl_certificate_key /etc/ssl/private/example.com.key;
ssl_trusted_certificate /etc/ssl/certs/chain.pem;
# Apenas TLS 1.2 e 1.3
ssl_protocols TLSv1.2 TLSv1.3;
# Cipher suites para TLS 1.2 — apenas AEAD com ECDHE
# TLS 1.3 gerencia seus próprios cipher suites automaticamente
ssl_ciphers 'ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256';
ssl_prefer_server_ciphers on;
# Curvas para ECDHE — X25519 primeiro (mais eficiente e seguro)
ssl_ecdh_curve X25519:P-256:P-384;
# OCSP Stapling
ssl_stapling on;
ssl_stapling_verify on;
resolver 1.1.1.1 8.8.8.8 valid=300s;
# Session cache e session tickets
ssl_session_cache shared:TLS:10m;
ssl_session_timeout 1d;
ssl_session_tickets off; # Desabilitar para TLS 1.3 PFS perfeito
# HSTS — força HTTPS por 2 anos
add_header Strict-Transport-Security "max-age=63072000; includeSubDomains; preload" always;
# Headers adicionais de segurança
add_header X-Frame-Options SAMEORIGIN always;
add_header X-Content-Type-Options nosniff always;
add_header Referrer-Policy strict-origin-when-cross-origin always;
}
# Redireciona HTTP para HTTPS
server {
listen 80;
server_name example.com www.example.com;
return 301 https://example.com$request_uri;
}Verificando a configuração
# Teste completo com openssl
openssl s_client -connect example.com:443 \
-servername example.com \
-tlsextdebug \
2>&1 | head -40
# Verificar versão TLS negociada
openssl s_client -connect example.com:443 \
-tls1_3 -servername example.com 2>&1 | grep "Protocol"
# Verificar OCSP Stapling
openssl s_client -connect example.com:443 \
-servername example.com -status 2>&1 | grep -A 5 "OCSP"
# Verificar cipher suite negociada
openssl s_client -connect example.com:443 \
-servername example.com 2>&1 | grep "Cipher"
# Confirmar que TLS 1.0 está desabilitado
openssl s_client -connect example.com:443 -tls1 2>&1 | \
grep -E "error|handshake failure" # Deve mostrar erroPerguntas frequentes sobre o Protocolo TLS
O TLS 1.2 acumulou cipher suites por razões de compatibilidade retroativa ao longo de anos — incluindo cipher suites com RC4, DES, NULL encryption, e RSA puro para troca de chave que tinham vulnerabilidades conhecidas. A proliferação criou uma superfície de configuração enorme onde escolhas incorretas produziam sistemas inseguros. O TLS 1.3 partiu de um princípio diferente: eliminar qualquer cipher suite que não fosse provadamente segura, deixando apenas construções modernas e bem-analisadas. Com apenas 5 cipher suites disponíveis — todas AEAD, todas com PFS implícito — é impossível configurar TLS 1.3 com cipher suites inseguras.
A chave privada RSA ou ECDSA do servidor é o componente secreto que corresponde à chave pública no certificado. Com TLS 1.2 sem ECDHE (RSA puro para troca de chave), vazar a chave privada permite descriptografar retroativamente qualquer sessão TLS cuja captura de tráfego o atacante possua — o pré-master secret de cada sessão foi cifrado com a chave pública, e a chave privada o descriptografa. Com ECDHE (e em toda conexão TLS 1.3), a chave privada do servidor serve apenas para autenticação — assina os parâmetros ECDHE. O segredo de sessão deriva de chaves ECDHE efêmeras; a chave privada vazada não permite descriptografar sessões passadas. Em ambos os casos, uma chave vazada permite que o atacante se faça passar pelo servidor em conexões futuras — o certificado precisa ser revogado e a chave regenerada imediatamente após qualquer suspeita de comprometimento.
O SNI transmite o hostname em texto claro no ClientHello, visível para observadores de rede como o ISP, firewalls corporativos, ou equipamentos de vigilância. O ECH (Encrypted Client Hello) criptografa o ClientHello completo, incluindo o SNI, mas ainda está em fase de implantação (2024-2025). Enquanto ECH não está universalmente disponível, uma mitigação parcial é usar DNS over HTTPS (DoH) ou DNS over TLS (DoT) para resolver nomes de domínio de forma criptografada — assim o observador de rede não vê a query DNS que precederia o SNI. Mas com acesso à conexão TLS em si, o SNI no ClientHello ainda é visível mesmo com DoH/DoT.
A revogação é um problema tecnicamente difícil. CRLs (Certificate Revocation Lists) são arquivos que CAs publicam listando certificados revogados — mas podem crescer para megabytes e os browsers não baixam CRLs para cada verificação. OCSP é mais eficiente (consulta apenas o certificado em questão) mas adiciona latência e revela navegação à CA. OCSP Stapling melhora isso mas requer suporte do servidor. Na prática, browsers modernos implementam revogação “soft-fail” — se não conseguem verificar o status OCSP, aceitam o certificado. Isso significa que um certificado revogado frequentemente funciona se o atacante bloqueia a verificação OCSP. O Chrome usa CRLSets — uma lista curada de revogações críticas distribuída via atualização do browser — para os casos mais graves. A revogação é uma área onde o ecossistema TLS ainda tem limitações conhecidas.
Session resumption permite que cliente e servidor retomem uma sessão TLS anterior sem executar o handshake completo — economizando round-trips. No TLS 1.2, isso funciona via session IDs (o servidor armazena estado de sessão) ou session tickets (estado criptografado pelo servidor, enviado ao cliente). O problema de segurança com session tickets é que eles usam uma chave estática do servidor — se essa chave vazar, sessões resumidas tornam-se descriptografáveis retroativamente (quebrando PFS). No TLS 1.3, session resumption usa PSK (Pre-Shared Keys) derivados do handshake anterior, com PFS preservado porque cada PSK deriva de material de chave único. A configuração de session tickets off em nginx para TLS 1.2 é uma troca consciente: perde-se a performance da resumption mas preserva-se PFS completo.
TLS como protocolo vivo
Ao longo deste artigo, o TLS revelou-se muito mais do que “o protocolo do cadeado” — é uma construção criptográfica sofisticada onde cada componente existe por razão específica, frequentemente como resposta a um ataque documentado que quebrou uma versão anterior.
O handshake estabelece autenticação e acorda chaves de forma que um observador externo não possa comprometer a confidencialidade presente ou futura. Os algoritmos AEAD combinam cifragem e autenticação em operações matematicamente provadas seguras. O ECDHE efêmero garante que comprometer a chave privada do servidor hoje não afeta sessões passadas. A cadeia de certificados X.509 cria um sistema de identidade verificável que permite ao cliente confiar em quem está do outro lado.
O TLS 1.3 representa uma maturidade de design que as versões anteriores não tinham: ao remover opcionalidade que permitia configurações inseguras e ao incorporar as lições de uma década de ataques documentados, criou um protocolo onde a implementação padrão é também a implementação segura.
O trabalho de quem implementa e configura TLS é garantir que essa segurança chegue ao usuário final: TLS 1.2 e 1.3 habilitados, versões anteriores desabilitadas, cipher suites modernas configuradas, certificados com ciclos de vida curtos e renovação automática, HSTS para prevenir downgrade, e OCSP Stapling para eficiência na verificação. Nenhum desses passos é tecnicamente complexo; o que exige atenção é a consistência em aplicá-los em toda a infraestrutura.
👉 Compartilhe este artigo com engenheiros de plataforma, administradores de sistemas e times de segurança que configuram e auditam conexões TLS — pode ser a referência técnica que transforma configurações legacy em configurações que resistem às ameaças atuais.
Uma resposta