Message d’erreur
[SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: Hostname mismatch, certificate is not valid for 'api.example.com'.
Également affiché sous la forme
- [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: IP address mismatch, certificate is not valid for '127.0.0.1'.
Le nom entre guillemets est l’hôte auquel vous vous êtes connecté. Pour les adresses IP, Python indique « IP address mismatch, certificate is not valid for '…'. ». Un emplacement dans le code source, comme « (_ssl.c:1082) », suit le message.
Python ssl module (OpenSSL host check) — ssl.SSLCertVerificationError, X509_V_ERR_HOSTNAME_MISMATCH (62)
Ce que cela signifie
La chaîne de certificats est approuvée, mais le nom que Python devait vérifier (l’hôte de l’URL, ou server_hostname) ne figure pas parmi les noms alternatifs du sujet (Subject Alternative Names) du certificat. Depuis Python 3.7, cette vérification est effectuée par OpenSSL pendant le handshake : elle apparaît donc comme un échec de vérification du certificat plutôt que sous la forme de l’ancienne exception ssl.CertificateError.
Pourquoi cela se produit
Le certificat ne mentionne pas ce nom d’hôte
fréquenteLe certificat couvre d’autres noms (www., le domaine apex, un ancien nom de service). Un wildcard couvre exactement un niveau du nom : *.example.com correspond donc à api.example.com, mais ni à example.com ni à a.b.example.com.
Connexion par adresse IP, localhost ou alias de conteneur
fréquenteL’URL utilise 127.0.0.1, une adresse IP privée, « localhost » ou un nom de service docker-compose, dont aucun ne figure dans un certificat émis pour un nom DNS public.
Le serveur a renvoyé le certificat d’un autre site
occasionnelleLes serveurs mutualisés choisissent le certificat d’après le nom SNI ; un nom sans configuration propre reçoit le certificat par défaut.
Comment corriger l’erreur
- 1.
Lister les noms couverts par le certificat
Comparez les entrées subjectAltName avec l’hôte que vous passez à Python.
bash echo | openssl s_client -connect api.example.com:443 -servername api.example.com 2>/dev/null \ | openssl x509 -noout -subject -ext subjectAltName - 2.
Réémettre avec tous les noms dans subjectAltName
Ajoutez chaque nom DNS et, pour un accès par adresse IP, des entrées IP. Les noms qui ne figurent que dans le nom commun (CN) ne sont pas utilisés pour la correspondance.
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.
Vérifier le nom du certificat tout en se connectant à une adresse
Lorsque vous devez joindre une adresse précise (un nœud de répartiteur de charge, un tunnel), laissez server_hostname réglé sur le nom du certificat au lieu de désactiver la vérification du nom d’hôte.
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())
Erreurs associées
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)