Maison  >  Article  >  développement back-end  >  Pourquoi est-ce que je rencontre l'erreur "Échec de la connexion : x509 : le certificat repose sur le champ Nom commun existant, utilisez les SAN ou activez temporairement la correspondance du nom commun avec GODEBUG=x509ignoreCN=0\"

Pourquoi est-ce que je rencontre l'erreur "Échec de la connexion : x509 : le certificat repose sur le champ Nom commun existant, utilisez les SAN ou activez temporairement la correspondance du nom commun avec GODEBUG=x509ignoreCN=0\"

Barbara Streisand
Barbara Streisandoriginal
2024-10-28 12:10:30609parcourir

Why am I encountering the

Erreur : écart de champ de certificat dans la connexion Go TLS

Lorsque vous essayez d'établir une connexion TLS à un serveur MongoDB avec Go, vous pouvez rencontrer l'erreur suivante :

failed to connect: x509: certificate relies on legacy Common Name field, use SANs or temporarily enable Common Name matching with GODEBUG=x509ignoreCN=0

Cause :

Cette erreur se produit lorsque le certificat TLS du serveur s'appuie sur l'ancien champ Common Name (CN) pour l'identification, mais que celui de Go par défaut, le runtime utilise des noms alternatifs de sujet (SAN) pour les connexions TLS.

Solution :

Il existe deux approches principales pour résoudre ce problème :

1. Utiliser les SAN dans le certificat de serveur :

  • Régénérez le certificat de serveur avec des SAN qui correspondent aux noms d'hôte ou aux adresses IP utilisés pour se connecter au serveur.
  • Cela peut être réalisé en utilisant des outils comme OpenSSL ou des autorités de certification tierces.

2. Désactiver temporairement la correspondance CN :

Si vous ne pouvez pas régénérer le certificat du serveur immédiatement, vous pouvez désactiver temporairement la correspondance CN en définissant la variable d'environnement :

GODEBUG=x509ignoreCN=0

Cependant, ce n'est pas un solution à long terme et ne doit être utilisée que pour établir des connexions temporairement.

Mise en œuvre du code :

Si vous choisissez de résoudre le problème dans votre code Go, assurez-vous que le Le certificat que vous chargez contient des SAN qui correspondent aux noms d'hôte utilisés lors de la connexion. Voici une version mise à jour de l'extrait de code que vous avez fourni :

<code class="go">const CONFIG_DB_CA = "/etc/ca-files/new-mongo.ca.crt"

func main() {
    cer, err := tls.LoadX509KeyPair("/mongo-server.crt", "/mongo-server.key")
    if err != nil {
        log.Println(err)
        return
    }

    roots := x509.NewCertPool()
    ca, err := ioutil.ReadFile(CONFIG_DB_CA)
    if err != nil {
        fmt.Printf("Failed to read or open CA File: %s.\n", CONFIG_DB_CA)
        return
    }
    roots.AppendCertsFromPEM(ca)

    tlsConfig := &tls.Config{
        Certificates: []tls.Certificate{cer},
        RootCAs:      roots,
        VerifyPeerCertificate: func(rawCerts [][]*x509.Certificate) error {
            for _, certs := range rawCerts {
                for _, cert := range certs {
                    if len(cert.Subject.CommonName) > 0 {
                        continue
                    }
                    for _, dns := range cert.DNSNames {
                        if dns == "customhost" || dns == "customhost:port" {
                            return nil
                        }
                    }
                    return errors.New("certificate does not contain a SAN for the host")
                }
            }
            return errors.New("no valid certificate found")
        },
    }

    conn, err := tls.Dial("tcp", "customhost:port", tlsConfig)
    if err != nil {
        fmt.Printf("failed to connect: %v.\n", err)
        return
    }

    err = conn.VerifyHostname("customhost")
    if err != nil {
        panic("Hostname doesn't match with certificate: " + err.Error())
    }
    for i, cert := range conn.ConnectionState().PeerCertificates {
        prefix := fmt.Sprintf("CERT%d::", i+1)
        fmt.Printf("%sIssuer: %s\n", prefix, cert.Issuer)
        fmt.Printf("%sExpiry: %v\n", prefix, cert.NotAfter.Format(time.RFC850))
        fmt.Printf("%sDNSNames: %v\n\n", prefix, cert.DNSNames)
    }

    fmt.Printf("Success!")
}</code>

Ce code mis à jour utilise une fonction VerifyPeerCertificate personnalisée pour vérifier que le certificat contient soit un CN qui correspond au nom d'hôte, soit un SAN qui correspond au nom d'hôte. Si un certificat approprié est trouvé, la connexion réussira.

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn