ssl.get_server_certificate tidak menegosiasikan proxy HTTP. Bangun terowongan terlebih dahulu, lalu lakukan TLS dengan nama host tujuan dan dapatkan sertifikat peer.

Untuk proxy HTTP tanpa autentikasi, menggunakan host dan port kandidat dari daftar proxy 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 menangani permintaan CONNECT dan responsnya. Konteks SSL kemudian memverifikasi rantai dan identitas tujuan sebelum sertifikat dikembalikan. Tidak ada HTTP GET ke tujuan yang diperlukan untuk jabat tangan ini.

Jika lingkungan menggunakan CA privat yang disetujui, muat CA tersebut ke dalam konteks alih-alih menonaktifkan verifikasi. Rantai yang ditolak membuat jabat tangan yang ditampilkan gagal.

getpeercert mengembalikan sertifikat daun peer, bukan rantai lengkap yang diekspor secara otomatis. Dengan intersepsi TLS tepercaya, sertifikat peer dapat berupa sertifikat yang dibuat perantara untuk nama host ini. Pertahankan perbedaan itu saat membandingkannya dengan sertifikat yang diamati melalui rute lain.

Artikel terkait