Zum Inhalt springen
ecdsa.com
Python ssl module (OpenSSL host check)Python cryptography

Fehlermeldung

[SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: Hostname mismatch, certificate is not valid for 'api.example.com'.

Auch ausgegeben als

  • [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: IP address mismatch, certificate is not valid for '127.0.0.1'.

Der Name in Anführungszeichen ist der Host, mit dem du dich verbunden hast. Bei IP-Adressen meldet Python „IP address mismatch, certificate is not valid for '…'.“ Auf die Meldung folgt eine Quellcode-Position wie „(_ssl.c:1082)“.

Python ssl module (OpenSSL host check) — ssl.SSLCertVerificationError, X509_V_ERR_HOSTNAME_MISMATCH (62)

Was der Fehler bedeutet

Der Zertifikatskette wird vertraut, aber der Name, den Python prüfen sollte (der Host in der URL oder server_hostname), steht nicht unter den Subject Alternative Names des Zertifikats. Seit Python 3.7 übernimmt OpenSSL diese Prüfung während des Handshakes, deshalb äußert sich die Abweichung als fehlgeschlagene Zertifikatsprüfung und nicht mehr als der frühere ssl.CertificateError.

Warum der Fehler auftritt

So behebst du den Fehler

  1. 1.

    Vom Zertifikat abgedeckte Namen auflisten

    Vergleiche die Einträge in subjectAltName mit dem Host, den du an Python übergibst.

    bash
    echo | openssl s_client -connect api.example.com:443 -servername api.example.com 2>/dev/null \
      | openssl x509 -noout -subject -ext subjectAltName
  2. 2.

    Mit allen Namen in subjectAltName neu ausstellen

    Nimm jeden DNS-Namen auf und für Zugriffe per IP auch IP-Einträge. Namen, die nur im Common Name stehen, werden beim Abgleich nicht berücksichtigt.

    bash
    # Include every DNS name and IP address clients use
    openssl req -new -key server.key -out server.csr -subj "/CN=api.example.com" \
      -addext "subjectAltName=DNS:api.example.com,DNS:api.internal.example.com,IP:10.0.0.5"
  3. 3.

    Beim Verbinden mit einer Adresse den Namen des Zertifikats prüfen

    Musst du eine bestimmte Adresse erreichen (einen Knoten des Load Balancers, einen Tunnel), setze server_hostname weiterhin auf den Namen im Zertifikat, statt die Hostnamenprüfung abzuschalten.

    python
    import socket, ssl
    
    # Connect to an address, but verify (and send SNI) for the certificate's name
    ctx = ssl.create_default_context()
    with socket.create_connection(("10.0.0.5", 443)) as raw:
        with ctx.wrap_socket(raw, server_hostname="api.example.com") as tls:
            print(tls.version())

Verwandte Fehler

Gesamte Signaturfehler-Datenbank durchsuchen