DEV Community

PKI security
PKI security

Posted on Fully Autonomous

A Python TLS probe that keeps certificate verification enabled

A script that works only after setting verify=False has lost an important part of its connection check. Before changing trust settings, make the failure observable: which host did the program contact, which name did it verify, and did it reach the TLS handshake?

This example uses Python's standard library. It opens one connection to a service you are authorized to test, performs a TLS handshake, prints a few certificate fields, and exits. It does not send an HTTP request or change the operating system's trust store.

The complete probe

Save this as tls_probe.py. Pass a hostname, without https:// or a path.

import socket
import ssl
import sys

host = sys.argv[1] if len(sys.argv) > 1 else "www.python.org"
context = ssl.create_default_context()
try:
    with socket.create_connection((host, 443), timeout=10) as raw:
        with context.wrap_socket(raw, server_hostname=host) as tls:
            cert = tls.getpeercert()
            print("TLS:", tls.version())
            print("SAN:", cert.get("subjectAltName"))
            print("Not after:", cert.get("notAfter"))
except ssl.SSLCertVerificationError as error:
    print("Certificate verification failed:", error.verify_message)
    raise SystemExit(2)
except (OSError, ssl.SSLError) as error:
    print("Connection or TLS failure:", type(error).__name__, str(error))
    raise SystemExit(3)
Enter fullscreen mode Exit fullscreen mode
python tls_probe.py www.python.org
Enter fullscreen mode Exit fullscreen mode

create_default_context() supplies client verification defaults. server_hostname supplies the intended DNS name for hostname checking and, where applicable, SNI. Do not replace it with an arbitrary name obtained from the certificate: the name must come from the service you meant to reach. Python ssl documentation / RFC 9525 — Service Identity in TLS

To turn a failed probe into a useful report, PKI Channel’s TLS chain debugging checklist shows which client, network and certificate observations to preserve before changing the trust configuration.

Reading the outcome

Outcome What it establishes Next step
TLS version and fields printed This Python context accepted this connection Check the application separately
Certificate verification failed Certificate validation rejected the peer Record the exact message, name and runtime
DNS, timeout or connection error The connection did not reach a usable TLS session Check name resolution, routing and service availability
Other TLS error TLS negotiation failed for another reason Compare protocol support and server configuration

Successful output is not an HTTP health check. A server can present an acceptable certificate and still return an application error. Conversely, a network timeout is not evidence that its certificate has expired.

A private CA without a global change

If the service intentionally uses an organizational CA, obtain the approved CA file through your administrator. Add this line after creating the context:

context.load_verify_locations(cafile="organization-ca.pem")
Enter fullscreen mode Exit fullscreen mode

This adds trust material to this context. Verify the CA's origin before using it. Downloading whatever certificate an unknown server presents and treating it as a trust anchor does not establish its identity.

For a scheduled probe, the certificate monitoring decision map adds the distinction between a failed connection, a missing observation and a certificate approaching expiry. That distinction helps keep an empty result from becoming a healthy status.

Useful limits of this probe

This script makes a direct socket connection. It does not automatically reproduce your browser's HTTP proxy configuration. That difference matters on corporate networks. Python and its linked OpenSSL version also affect behavior, so record python --version and ssl.OPENSSL_VERSION with a bug report.

The probe is a documented example, not a claim that your endpoint has been tested. A useful report includes the hostname, UTC time, runtime version, exact error and network location. Those details give the next person a reproducible problem without asking them to weaken verification.

Primary sources

AI was used to assist with research and drafting.

Top comments (0)