Message d’erreur
curl: (60) SSL: no alternative certificate subject name matches target hostname 'api.example.com'
Également affiché sous la forme
- curl: (60) SSL: no alternative certificate subject name matches target host name 'api.example.com'
curl 8.x affiche « target hostname » ; curl 7.x affichait « target host name ». L’hôte entre guillemets est celui que contenait l’URL. Les très anciennes versions de curl (avant 7.62.0) utilisaient le code de sortie 51 pour cette vérification.
curl (OpenSSL backend) — CURLE_PEER_FAILED_VERIFICATION, hostname check in lib/vtls/openssl.c
Ce que cela signifie
La chaîne de certificats est approuvée, mais aucun des noms DNS (ni aucune des adresses IP) de l’extension Subject Alternative Name du certificat ne correspond à l’hôte de l’URL. curl compare l’hôte de l’URL uniquement aux entrées SAN ; le nom commun (Common Name) du sujet est ignoré lorsqu’une extension SAN est présente. Le nom entre guillemets à la fin est l’hôte que curl devait joindre.
Pourquoi cela se produit
Le certificat ne mentionne pas ce nom
fréquenteUn certificat pour example.com ne couvre ni www.example.com ni api.example.com, sauf si chaque nom figure dans la liste des SAN. Les nouveaux sous-domaines et les nouveaux environnements (staging, eu.) nécessitent un certificat réémis.
L’URL utilise une adresse IP, localhost ou un alias interne
fréquentehttps://10.0.0.5, https://localhost ou un nom de service docker-compose atteignent le bon serveur, mais demandent un nom pour lequel le certificat n’a jamais été émis. Les adresses IP ne correspondent qu’aux entrées SAN de type IP, jamais aux entrées DNS.
Le serveur a renvoyé le certificat d’un autre site
occasionnelleSur les IP partagées, le certificat est choisi selon le SNI. Si le nom demandé n’a pas de bloc server correspondant, le serveur répond avec son certificat par défaut, qui désigne un autre site.
Un wildcard est censé couvrir plus qu’il ne couvre réellement
occasionnelle*.example.com couvre api.example.com, mais ni example.com ni v2.api.example.com : un wildcard remplace exactement un niveau du nom.
Comment corriger l’erreur
- 1.
Comparer la liste des SAN avec l’URL
Affichez l’extension subjectAltName du certificat servi. La correction consiste soit à obtenir un certificat qui contient ce nom, soit à utiliser une URL avec l’un des noms listés.
bash # Names the served certificate actually covers 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 le certificat avec tous les noms utilisés
Demandez tous les noms d’hôte (et les adresses IP, si des clients se connectent par IP) comme entrées SAN. Placer le nom uniquement dans le nom commun ne fonctionne avec aucun client actuel.
bash # ACME: list every name the certificate must cover sudo certbot certonly --nginx -d example.com -d www.example.com -d api.example.com # Private CA: put all names into subjectAltName (CN is ignored for matching) openssl req -new -key server.key -out server.csr -subj "/CN=api.example.com" \ -addext "subjectAltName=DNS:api.example.com,DNS:www.example.com,IP:10.0.0.5" - 3.
Garder le nom, ne changer que l’adresse
Lorsque vous devez joindre une adresse précise (un nœud de répartiteur de charge, un tunnel, une IP de staging), --resolve ou --connect-to conservent l’hôte de l’URL, si bien que le SNI et la vérification du nom d’hôte utilisent toujours le nom du certificat.
bash # Keep the certificate's name in the URL and steer the connection to another address curl --resolve api.example.com:443:10.0.0.5 https://api.example.com/ curl --connect-to api.example.com:443:lb-internal.example.net:443 https://api.example.com/ - 4.
Propriétaires de serveurs : vérifier le routage SNI
Si le certificat diffère entre les requêtes avec et sans SNI, ajoutez un bloc server (ou une règle d’ingress) pour ce nom et assurez-vous que les clients n’obtiennent pas le certificat par défaut pour de vrais noms d’hôte.
bash # Compare what the server returns with and without SNI openssl s_client -connect 10.0.0.5:443 -servername api.example.com </dev/null 2>/dev/null | openssl x509 -noout -subject openssl s_client -connect 10.0.0.5:443 -noservername </dev/null 2>/dev/null | openssl x509 -noout -subject
Erreurs associées
x509: certificate is valid for example.com, not api.example.comGo crypto/x509Hostname/IP does not match certificate's altnames: Host: api.example.com. is no…Node.js tls.checkServerIdentity()[SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: Hostname mismatch,…Python ssl module (OpenSSL host check)No subject alternative DNS name matching api.example.com found.Java (JSSE HostnameChecker)fatal: unable to access 'https://git.example.com/team/app.git/': SSL: certifica…git over HTTPS with libcurl-gnutls (Debian, Ubuntu)