Message d’erreur
SSL routines:ssl3_read_bytes:ssl/tls alert bad certificate
Également affiché sous la forme
- SSL routines:ssl3_read_bytes:sslv3 alert bad certificate
- error:0A000412:SSL routines::ssl/tls alert bad certificate
OpenSSL 3.3 et les versions ultérieures affichent « ssl/tls alert bad certificate », les versions antérieures « sslv3 alert bad certificate » (code 0A000412 ; la 1.1.1 utilisait 14094412), puis « SSL alert number 42 ». Les clients OpenSSL eux-mêmes envoient unknown_ca (48) ou certificate_expired (45) pour les mêmes refus.
OpenSSL — TLS alert 42 (bad_certificate) received from the peer
Ce que cela signifie
Le pair a envoyé l’alerte TLS 42 (bad_certificate) : il a rejeté le certificat présenté de ce côté-ci. Le paquet crypto/tls de Go envoie cette alerte pour tout certificat serveur qu’il ne parvient pas à vérifier (autorité inconnue, certificat expiré, mauvais nom) : les serveurs fondés sur OpenSSL (nginx, HAProxy, Postfix, s_server) la consignent donc chaque fois qu’un client Go rejette leur certificat. En TLS mutuel, un serveur l’envoie lorsqu’il rejette le certificat du client.
Pourquoi cela se produit
Un client Go a rejeté le certificat du serveur
fréquenteLes programmes Go (composants Kubernetes, Terraform, Prometheus, Docker, de nombreux CLI) envoient bad_certificate lorsque la vérification échoue. Le côté Go affiche la vraie raison, par exemple « x509: certificate signed by unknown authority ».
TLS mutuel : le serveur a rejeté le certificat client
fréquenteLe certificat client a expiré, n’a pas été émis par une AC acceptée ou n’est pas acceptable pour le serveur pour une autre raison.
L’utilisation de la clé du certificat n’autorise pas son rôle
occasionnelleUn certificat dont l’extendedKeyUsage ne contient pas serverAuth (ou clientAuth pour les certificats client) est rejeté par les vérificateurs stricts comme Go.
Comment corriger l’erreur
- 1.
Trouver le client qui refuse et la raison du refus
La ligne du journal indique l’adresse du client ; sur ce client, le message d’erreur donne la vraie cause. Vérifier la chaîne depuis l’extérieur la révèle souvent directement.
bash # Server log: which client rejected the certificate, and does the chain verify from outside? openssl s_client -connect api.example.com:443 -servername api.example.com </dev/null 2>/dev/null \ | grep -E 'Verify return code' - 2.
Clients Go : faire confiance à l’AC ou corriger la chaîne
Servez une chaîne complète émise par une AC de confiance, ou ajoutez l’AC privée aux RootCAs du client Go ; n’utilisez jamais InsecureSkipVerify comme correctif.
go // Go clients: trust the server's CA explicitly (keeps verification on) pool, _ := x509.SystemCertPool() caPEM, _ := os.ReadFile("internal-ca.pem") pool.AppendCertsFromPEM(caPEM) client := &http.Client{Transport: &http.Transport{TLSClientConfig: &tls.Config{RootCAs: pool}}} - 3.
TLS mutuel : vérifier le certificat client
Les dates de validité, l’émetteur et l’utilisation de la clé du certificat client doivent correspondre à ce qu’attend le serveur.
bash # Mutual TLS: check the client certificate the server rejected openssl x509 -in client.pem -noout -issuer -dates -ext extendedKeyUsage,keyUsage