Aller au contenu
ecdsa.com
Python ssl module (OpenSSL host check)cryptography (Python)

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

Comment corriger l’erreur

  1. 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. 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. 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

Parcourir toute la base de données des erreurs de signature