错误:Go TLS 连接中的证书字段差异
尝试使用 Go 与 MongoDB 服务器建立 TLS 连接时,您可能会遇到以下错误:
failed to connect: x509: certificate relies on legacy Common Name field, use SANs or temporarily enable Common Name matching with GODEBUG=x509ignoreCN=0
原因:
当服务器的 TLS 证书依赖旧版通用名称 (CN) 字段进行识别时,会发生此错误,但 Go 的运行时默认使用主题备用名称 (SAN) 进行 TLS 连接。
解决方案:
解决此问题的主要方法有两种:
1.利用服务器证书中的 SAN:
2.暂时禁用 CN 匹配:
如果无法立即重新生成服务器证书,可以通过设置环境变量来暂时禁用 CN 匹配:
GODEBUG=x509ignoreCN=0
但这不是一个长期解决方案,只能用于临时建立连接。
代码实现:
如果您选择在 Go 代码中修复问题,请确保您加载的证书包含与连接期间使用的主机名匹配的 SAN。以下是您提供的代码片段的更新版本:
<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>
此更新的代码使用自定义的VerifyPeerCertificate函数来验证证书是否包含与主机名匹配的CN或与主机名匹配的SAN。如果找到合适的证书,连接就会成功。
以上是为什么我会遇到'连接失败:x509:证书依赖于旧版公用名字段,使用 SAN 或暂时启用与 GODEBUG=x509ignoreCN=0 匹配的公用名”错误的详细内容。更多信息请关注PHP中文网其他相关文章!