问题描述
我正在尝试连接 mongodb 服务器,要连接我必须提供 CA 证书文件和 tls 证书文件。
当我使用以下命令时,我没有问题
$ mongo --host customhost:port DB --authenticationDatabase=DB -u ACCOUNT -p PWD --tls --tlsCAFile /etc/ca-files/new-mongo.ca.crt --tlsCertificateKeyFile /etc/ca-files/new-mongo-client.pem
但是当我尝试与 mongo 连接(并且还仅使用 tls 客户端进行测试)时,出现以下错误:
Failed to connect: x509: certificate relies on legacy Common Name field,use SANs or temporarily enable Common Name matching with GODEBUG=x509ignoreCN=0
如果我使用 env 变量一切正常,但我想知道如何修复它而不必使用它。
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,}
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",cert.NotAfter.Format(time.RFC850))
fmt.Printf("%sDNSNames: %v\n\n",cert.DNSNames)
}
fmt.Printf("Success!")
}
证书:
$ openssl x509 -in /etc/ca-files/new-mongo.ca.crt -text -noout
Certificate:
Data:
Version: 3 (0x2)
Serial Number:
....
Signature Algorithm: sha256WithRSAEncryption
Issuer: C = FR,ST = IDF,L = Paris,O = COMP,OU = IT,CN = newmongo
Validity
Not Before: Jun 30 13:02:12 2021 GMT
Not After : Jun 30 13:02:12 2023 GMT
Subject: C = FR,CN = newmongo
...
X509v3 extensions:
X509v3 Subject Key Identifier:
...
X509v3 Authority Key Identifier:
....
X509v3 Basic Constraints: critical
CA:TRUE
$ openssl x509 -in /etc/ca-files/newmongo-client.pem -text -noout
Certificate:
Data:
Version: 3 (0x2)
Serial Number:
...
Signature Algorithm: sha256WithRSAEncryption
Issuer: C = FR,CN = newmongo
Validity
Not Before: Jun 30 13:17:25 2021 GMT
Not After : Jun 30 13:17:25 2023 GMT
Subject: C = FR,CN = newmongo-client
...
X509v3 extensions:
X509v3 Subject Alternative Name:
DNS:customhost:port,DNS:customhost,DNS:newmongo-client
我有点卡住了,不知道问题是出在我的 tls 代码配置和我加载证书的方式上,还是来自 SSL 证书配置错误,但来自哪些证书看起来不错。 我觉得加载的证书因任何原因被忽略
感谢您的帮助
解决方法
您需要在源头解决问题并生成带有 DNS
SAN
字段的证书 - 然后 Go
运行时检查将消失。
这可以通过 openssl
实现,但由于需要配置文件而很棘手 - 因为 SAN 字段选项过于广泛,无法放入简单的命令行选项。
一般要点是,创建一个 CSR:
openssl req -new \
-subj "${SUBJ_PREFIX}/CN=${DNS}/emailAddress=${EMAIL}" \
-key "${KEY}" \
-addext "subjectAltName = DNS:${DNS}" \
-out "${CSR}"
然后用您的 CSR
签署 root CA
:
openssl ca \
-create_serial \
-cert "${ROOT_CRT}" \
-keyfile "${ROOT_KEY}" \
-days "${CERT_LIFETIME}" \
-in "${CSR}" \
-batch \
-config "${CA_CONF}" \
-out "${CRT}"
上面引用的 CA_CONF
看起来像这样:
[ ca ]
default_ca = my_ca
[ my_ca ]
dir = ./db
database = $dir/index.txt
serial = $dir/serial
new_certs_dir = $dir/tmp
x509_extensions = my_cert
name_opt = ca_default
cert_opt = ca_default
default_md = default
policy = policy_match
# 'copy_extensions' will copy over SAN ("X509v3 Subject Alternative Name") from CSR
copy_extensions = copy
[ my_cert ]
basicConstraints = CA:FALSE
nsComment = "generated by https://github.com/me/my-pki"
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid,issuer
[ policy_match ]
# ensure CSR fields match that of delivered Cert
countryName = match
stateOrProvinceName = match
organizationName = match
organizationalUnitName = optional
commonName = supplied
emailAddress = optional
检查生成的服务器证书:
openssl x509 -in server.crt -noout -text
然后应该有一个 SAN
部分,例如:
X509v3 Subject Alternative Name:
DNS:myserver.com