Ler um certificado de par TLS através de um proxy HTTP em Python
Use o suporte de túnel do HTTPConnection do Python antes de envolver o socket num contexto SSL que valide.
ssl.get_server_certificate não negocia um proxy HTTP. Estabeleça primeiro o túnel, depois execute TLS com o nome de host de destino e obtenha o certificado do par.
Para um proxy HTTP sem autenticação, usando o host e a porta de um candidato da lista de proxies HTTP:
from contextlib import closing
import http.client
import ssl
hostname = "example.com"
context = ssl.create_default_context()
with closing(http.client.HTTPConnection(
"proxy.example.net", 8080, timeout=10
)) as connection:
connection.set_tunnel(hostname, 443)
connection.connect()
with context.wrap_socket(
connection.sock, server_hostname=hostname
) as tls:
certificate_der = tls.getpeercert(binary_form=True)
certificate_pem = ssl.DER_cert_to_PEM_cert(certificate_der)
HTTPConnection trata o pedido CONNECT e a sua resposta. O contexto SSL verifica depois a cadeia e a identidade do destino antes de o certificado ser devolvido. Não é necessário qualquer HTTP GET ao destino para este handshake.
Se o ambiente usar uma AC privada aprovada, carregue essa AC no contexto em vez de desativar a verificação. Uma cadeia rejeitada faz falhar o handshake mostrado.
getpeercert devolve o certificado folha do par, não uma cadeia completa exportada automaticamente. Com interceção TLS de confiança, o certificado do par pode ser o certificado gerado pelo intermediário para este nome de host. Preserve essa distinção ao compará-lo com um certificado observado por outra rota.