Search code examples
sslpython-3.7x509certificate

Python ssl: IP address in check_hostname


Can Python3 ssl library work with IP addresses, not hostnames in the certificate?

Let's suppose I try to connect to a server:

ip = '192.168.0.99'
context = ssl.create_default_context(cafile='ca.crt')
with socket.create_connection((ip, 443)) as sock:
  with context.wrap_socket(sock, server_hostname=ip) as ssock:
    print(ssock.version())

When I run it, I get an error:

SSLCertVerificationError: [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: unable to get local issuer certificate (_ssl.c:1056)

IP address 192.168.0.99 is written into certificate Common Name and into Subject Alt Name too.

$ openssl x509 -in san.crt  -noout  -text | grep -B 1 192.168.0.99
        Signature Algorithm: sha256WithRSAEncryption
        Issuer: C = RU, ST = MSK, O = Internet Widgits Pty Ltd, OU = example, CN = 192.168.0.99
--
            Not After : Jul  4 21:31:32 2030 GMT
        Subject: C = RU, ST = MSK, O = Internet Widgits Pty Ltd, OU = example, CN = 192.168.0.99
--
            X509v3 Subject Alternative Name:
                IP Address:192.168.0.99

Solution

  • SSLCertVerificationError: [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: unable to get local issuer certificate (_ssl.c:1056)

    The error is not about the hostname not matching the certificate but about the inability to find a locally trusted issuer for the certificate.

    context = ssl.create_default_context(cafile='ca.crt')
    

    I assume your intention is that ca.crt is the issuer for san.crt. But according to what you show from the certificate it looks like a self-signed certificate instead (subject and issuer is the same) and not signed by ca.crt.