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
Das Zertifikat enthält diesen Hostnamen nicht
häufigDas Zertifikat deckt andere Namen ab (www., die Apex-Domain, einen alten Dienstnamen). Wildcards decken genau ein Label ab, daher passt *.example.com auf api.example.com, aber nicht auf example.com oder a.b.example.com.
Verbindung per IP-Adresse, localhost oder Container-Alias
häufigDie URL verwendet 127.0.0.1, eine private IP, „localhost“ oder einen Dienstnamen aus docker-compose – nichts davon steht in einem Zertifikat, das für einen öffentlichen DNS-Namen ausgestellt wurde.
Der Server hat das Zertifikat einer anderen Website geliefert
gelegentlichGemeinsam genutzte Hosts wählen das Zertifikat anhand des SNI-Namens; ein Name ohne eigene Konfiguration bekommt das Standardzertifikat.
So behebst du den Fehler
- 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.
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.
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
x509: certificate is valid for example.com, not api.example.comGo crypto/x509curl: (60) SSL: no alternative certificate subject name matches target hostname…curl (OpenSSL backend)Hostname/IP does not match certificate's altnames: Host: api.example.com. is no…Node.js tls.checkServerIdentity()Max retries exceeded with url: / (Caused by SSLError(SSLCertVerificationError(1…requests / urllib3 (Python)