Чтение сертификата узла TLS через HTTP-прокси в Python
Используйте поддержку туннеля HTTPConnection в Python, прежде чем обернуть сокет в проверяющий контекст SSL.
ssl.get_server_certificate не согласует HTTP-прокси. Сначала установите туннель, затем выполните TLS с именем хоста назначения и получите сертификат узла.
Для HTTP-прокси без аутентификации, используя хост и порт кандидата из списка 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 обрабатывает запрос CONNECT и ответ на него. Затем контекст SSL проверяет цепочку и подлинность назначения, прежде чем сертификат будет возвращён. Для этого рукопожатия HTTP GET к назначению не требуется.
Если среда использует одобренный частный CA, загрузите этот CA в контекст вместо отключения проверки. Отклонённая цепочка приводит к сбою показанного рукопожатия.
getpeercert возвращает листовой сертификат узла, а не автоматически экспортированную полную цепочку. При доверенном перехвате TLS сертификат узла может быть сертификатом, созданным посредником для этого имени хоста. Сохраняйте это различие при сравнении с сертификатом, наблюдённым другим маршрутом.