Home >Backend Development >Golang >Why am I encountering the \'failed to connect: x509: certificate relies on legacy Common Name field, use SANs or temporarily enable Common Name matching with GODEBUG=x509ignoreCN=0\' error w
Error: Certificate Field Discrepancy in Go TLS Connection
When attempting to establish a TLS connection to a MongoDB server with Go, you may encounter the following error:
failed to connect: x509: certificate relies on legacy Common Name field, use SANs or temporarily enable Common Name matching with GODEBUG=x509ignoreCN=0
Cause:
This error occurs when the server's TLS certificate relies on the legacy Common Name (CN) field for identification, but Go's runtime defaults to using Subject Alternative Names (SANs) for TLS connections.
Solution:
There are two main approaches to resolving this issue:
1. Utilize SANs in the Server Certificate:
2. Disable CN Matching Temporarily:
If you cannot regenerate the server certificate immediately, you can temporarily disable CN matching by setting the environment variable:
GODEBUG=x509ignoreCN=0
However, this is not a long-term solution and should be used only to establish connections temporarily.
Code Implementation:
If you choose to fix the issue in your Go code, ensure that the certificate you load contains SANs that match the hostnames used during the connection. Here's an updated version of the code snippet you provided:
<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>
This updated code uses a custom VerifyPeerCertificate function to verify that the certificate contains either a CN that matches the hostname or a SAN that matches the hostname. If a suitable certificate is found, the connection will succeed.
The above is the detailed content of Why am I encountering the \'failed to connect: x509: certificate relies on legacy Common Name field, use SANs or temporarily enable Common Name matching with GODEBUG=x509ignoreCN=0\' error w. For more information, please follow other related articles on the PHP Chinese website!