Mensagem de erro
[SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: Hostname mismatch, certificate is not valid for 'api.example.com'.
Também aparece como
- [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: IP address mismatch, certificate is not valid for '127.0.0.1'.
O nome entre aspas é o host ao qual você se conectou. Para endereços IP, o Python diz “IP address mismatch, certificate is not valid for '…'.” Depois da mensagem vem uma localização no código-fonte, como “(_ssl.c:1082)”.
Python ssl module (OpenSSL host check) — ssl.SSLCertVerificationError, X509_V_ERR_HOSTNAME_MISMATCH (62)
O que significa
A cadeia de certificados é confiável, mas o nome que o Python precisava verificar (o host da URL ou server_hostname) não está entre os Subject Alternative Names do certificado. Desde o Python 3.7, a verificação é feita pelo OpenSSL durante o handshake, por isso aparece como falha na verificação do certificado, e não como o antigo ssl.CertificateError.
Por que acontece
O certificado não inclui este nome de host
comumO certificado cobre outros nomes (www., o domínio apex, um nome de serviço antigo). Um curinga cobre exatamente um nível do nome, então *.example.com corresponde a api.example.com, mas não a example.com nem a a.b.example.com.
Conexão por endereço IP, localhost ou alias de contêiner
comumA URL usa 127.0.0.1, um IP privado, “localhost” ou um nome de serviço do docker-compose, e nenhum deles aparece em um certificado emitido para um nome DNS público.
O servidor retornou o certificado de outro site
ocasionalHosts compartilhados escolhem o certificado pelo nome do SNI; um nome sem configuração própria recebe o certificado padrão.
Como corrigir
- 1.
Listar os nomes que o certificado cobre
Compare as entradas de subjectAltName com o host que você passa ao 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.
Reemitir com todos os nomes no subjectAltName
Adicione todos os nomes DNS e, para acesso por IP, entradas de IP. Nomes que estão apenas no Common Name não são usados na correspondência.
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.
Verificar o nome do certificado ao se conectar a um endereço
Quando você precisar acessar um endereço específico (um nó do balanceador de carga, um túnel), mantenha server_hostname definido com o nome do certificado em vez de desativar a verificação do nome do host.
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())
Erros relacionados
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)