Depurar uma conexão HTTPS costuma ser difícil porque o TLS protege exatamente os dados que você gostaria de observar. O atributo SSLContext.keylog_filename do módulo ssl resolve parte desse problema ao permitir que o Python grave, em um arquivo local, os segredos de sessão usados durante o handshake. Ferramentas como o Wireshark podem ler esse arquivo e descriptografar o tráfego capturado, desde que você tenha autorização para analisar a conexão.
Esse recurso é especialmente útil em ambientes de desenvolvimento, testes de integração, análise de APIs internas, diagnóstico de incompatibilidades TLS e investigação de falhas de protocolo. Ele não desativa a criptografia na rede, não altera o certificado e não transforma HTTPS em HTTP. O tráfego continua criptografado; apenas o analista que possui o arquivo de chaves consegue interpretá-lo.
O que é keylog_filename
keylog_filename é uma propriedade de ssl.SSLContext. Ao receber um caminho de arquivo, o contexto passa a registrar segredos TLS no formato NSS Key Log. Esse formato é reconhecido por navegadores, bibliotecas e ferramentas de análise de pacotes. O arquivo normalmente contém linhas como CLIENT_RANDOM ou rótulos específicos do TLS 1.3, associando um identificador de sessão ao segredo correspondente.
O recurso depende de suporte da biblioteca OpenSSL usada pela instalação do Python. Em versões modernas, ele costuma funcionar em Linux, macOS e Windows, mas a disponibilidade real deve ser verificada no ambiente de execução.
Exemplo básico com urllib
import ssl
import urllib.request
contexto = ssl.create_default_context()
contexto.keylog_filename = "tls-keys.log"
with urllib.request.urlopen(
"https://www.python.org/",
context=contexto,
timeout=10,
) as resposta:
dados = resposta.read(200)
print(resposta.status)
print(dados[:80])
O código cria um contexto seguro com as autoridades certificadoras padrão e, em seguida, define o arquivo de log. Quando a conexão TLS é estabelecida, o Python acrescenta as chaves ao arquivo. Se você capturar o tráfego simultaneamente e configurar o Wireshark para usar tls-keys.log, poderá visualizar a camada HTTP dentro da sessão criptografada.
Como configurar o Wireshark
No Wireshark, abra as preferências do protocolo TLS e informe o caminho completo do arquivo no campo de log de chaves. Depois, inicie uma nova captura ou recarregue uma captura existente que corresponda às sessões registradas. O arquivo precisa conter os segredos das conexões específicas presentes no pacote; reutilizar um log antigo não ajuda em novas sessões.
Filtros como tls, http2 e http ajudam a localizar o fluxo. Em APIs modernas, é comum que o conteúdo apareça como HTTP/2, mesmo quando a URL começa com HTTPS. A documentação oficial do módulo ssl do Python explica o comportamento do contexto, enquanto a documentação do Wireshark sobre TLS detalha a importação do arquivo de chaves.
Uso com sockets
import socket
import ssl
contexto = ssl.create_default_context()
contexto.keylog_filename = "segredos-tls.log"
with socket.create_connection(("www.python.org", 443), timeout=10) as bruto:
with contexto.wrap_socket(bruto, server_hostname="www.python.org") as seguro:
seguro.sendall(
b"GET / HTTP/1.1\r\nHost: www.python.org\r\nConnection: close\r\n\r\n"
)
resposta = seguro.recv(4096)
print(resposta.decode("latin-1", errors="replace"))
Nesse exemplo, o arquivo é associado ao contexto antes do handshake. Esse detalhe é importante: configurar a propriedade depois que a sessão já foi negociada não recupera retroativamente os segredos.
Variável SSLKEYLOGFILE
Algumas aplicações e bibliotecas respeitam a variável de ambiente SSLKEYLOGFILE. O Python também pode usar essa variável ao criar contextos padrão em determinadas situações. Mesmo assim, definir context.keylog_filename explicitamente costuma ser melhor em testes, porque torna a intenção visível no código e evita depender do ambiente global.
export SSLKEYLOGFILE="$PWD/tls-keys.log"
python cliente.py
Em automações, prefira um diretório temporário e remova o arquivo ao final. O artigo sobre tempfile no Python ajuda a criar arquivos temporários com ciclo de vida controlado. Para entender melhor caminhos e diretórios, veja também pathlib no Python.
Segurança do arquivo de chaves
O arquivo gerado é extremamente sensível. Quem possui a captura de rede e o log correspondente pode descriptografar as sessões registradas. Por isso, nunca envie esse arquivo para repositórios Git, tickets públicos ou canais de suporte sem proteção. Adicione padrões como *.keylog e tls-keys.log ao .gitignore.
Também evite manter o recurso ativo em produção. Em servidores com alto volume, o arquivo cresce continuamente e concentra material criptográfico de muitas sessões. Isso cria risco de exposição, consumo de disco e problemas de concorrência. Restrinja permissões do arquivo ao usuário do processo e use um diretório protegido.
Função auxiliar segura
from pathlib import Path
import ssl
def criar_contexto_debug(caminho: Path, habilitado: bool = False) -> ssl.SSLContext:
contexto = ssl.create_default_context()
if habilitado:
caminho.parent.mkdir(parents=True, exist_ok=True)
contexto.keylog_filename = str(caminho)
return contexto
contexto = criar_contexto_debug(
Path(".debug") / "tls-keys.log",
habilitado=True,
)
A flag explícita reduz o risco de ativar o recurso sem querer. Em projetos maiores, vincule essa opção a uma configuração local e bloqueie-a em ambientes de produção.
Integração com requests e httpx
A biblioteca requests não expõe diretamente um parâmetro de contexto SSL em sua função principal. É possível criar um adaptador HTTP personalizado para injetar um SSLContext. Já bibliotecas como httpx aceitam um contexto por meio do parâmetro verify.
import ssl
import httpx
contexto = ssl.create_default_context()
contexto.keylog_filename = "httpx-tls.log"
with httpx.Client(verify=contexto, timeout=10) as cliente:
resposta = cliente.get("https://www.python.org/")
print(resposta.status_code)
Ao investigar clientes HTTP, vale revisar o artigo sobre urllib.request no Python e o guia de requisições HTTP com Python. Esses conteúdos ajudam a separar erros de aplicação, DNS, TCP, certificado e protocolo.
Erros comuns
Um erro frequente é usar um caminho sem permissão de escrita. Nesse caso, a criação do arquivo pode falhar ou o log permanecer vazio. Outro problema é capturar uma interface de rede diferente daquela usada pela aplicação. Em contêineres, VPNs e WSL, a interface correta pode não ser a mais óbvia.
Também é comum esperar que o log descriptografe sessões antigas. As chaves só são registradas para handshakes realizados enquanto o contexto está configurado. Reuso de conexão, cache e pooling podem fazer com que nenhuma nova linha apareça. Feche o cliente, force uma nova sessão e repita a captura.
TLS 1.3 e HTTP/2
O TLS 1.3 usa vários segredos durante o handshake e a comunicação. O formato NSS Key Log registra rótulos adequados, e versões recentes do Wireshark conseguem interpretar esses dados. Para HTTP/2, a descriptografia TLS é apenas a primeira etapa; depois disso, o Wireshark precisa decodificar os frames do protocolo.
Quando usar
Use keylog_filename quando precisar confirmar cabeçalhos, negociação ALPN, redirecionamentos, cookies, compactação, frames HTTP/2 ou comportamento de uma API sob TLS. Ele também ajuda a comparar o que a aplicação pensa que enviou com o que realmente saiu pela rede.
Não use o recurso para interceptar tráfego de terceiros, contornar controles ou coletar credenciais. A análise deve ocorrer em sistemas, contas e ambientes para os quais você possui autorização explícita.
Checklist de depuração
- Crie um contexto com validação de certificado ativa.
- Defina o arquivo antes do handshake.
- Proteja o log com permissões restritas.
- Capture a interface correta.
- Configure o caminho completo no Wireshark.
- Force uma nova conexão quando necessário.
- Remova o arquivo após a investigação.
Conclusão
SSLContext.keylog_filename oferece uma forma prática de observar conexões TLS criadas pelo Python sem desativar a criptografia. Com um contexto dedicado, um arquivo protegido e uma captura autorizada, você consegue diagnosticar problemas de HTTPS, HTTP/2 e APIs com muito mais precisão. O principal cuidado é tratar o arquivo de chaves como segredo temporário e nunca deixá-lo ativo em produção sem uma justificativa forte.







