我正在尝试将 go 客户端连接到启用 ssl 运行的 mongodb 服务器。我收到一条明确的错误消息,表明由于 ssl 错误而导致握手失败。我在客户端使用自签名证书。
从 mongodb 服务器获取以下信息:
2017-05-13T04:38:53.910+0000 I NETWORK [thread1] connection accepted from 172.17.0.1:51944 #10 (1 connection now open)
2017-05-13T04:38:53.911+0000 E NETWORK [conn10] SSL: error:14094412:SSL routines:SSL3_READ_BYTES:sslv3 alert bad certificate
2017-05-13T04:38:53.911+0000 I - [conn10] end connection
Go 客户端错误:
Could not connect to mongodb_s1.dev:27017 x509: certificate signed by unknown authority (possibly because of "crypto/rsa: verification error" while trying to verify candidate authority certificate "XYZ")
尝试了多种选择,但没有帮助
您可以使用
InsecureSkipVerify = true
跳过 TLS 安全检查。这允许您使用自签名证书。请参阅下面的compose help中的代码。
建议将用于签署证书的 CA 添加到系统的受信任 CA 列表中,而不是跳过安全检查。
package main
import (
"crypto/tls"
"fmt"
"net"
"os"
"strings"
"gopkg.in/mgo.v2"
)
func main() {
uri := os.Getenv("MONGODB_URL")
if uri == "" {
fmt.Println("No connection string provided - set MONGODB_URL")
os.Exit(1)
}
uri = strings.TrimSuffix(uri, "?ssl=true")
这里:
tlsConfig := &tls.Config{}
tlsConfig.InsecureSkipVerify = true
dialInfo, err := mgo.ParseURL(uri)
if err != nil {
fmt.Println("Failed to parse URI: ", err)
os.Exit(1)
}
这里:
dialInfo.DialServer = func(addr *mgo.ServerAddr) (net.Conn, error) {
conn, err := tls.Dial("tcp", addr.String(), tlsConfig)
return conn, err
}
session, err := mgo.DialWithInfo(dialInfo)
if err != nil {
fmt.Println("Failed to connect: ", err)
os.Exit(1)
}
defer session.Close()
dbnames, err := session.DB("").CollectionNames()
if err != nil {
fmt.Println("Couldn't query for collections names: ", err)
os.Exit(1)
}
fmt.Println(dbnames)
}
如果您使用官方 MongoDB Go 客户端,您可以通过设置
mongo.Connect(context.TODO(), opts)
选项来使用自定义 CA:
caCert, err := os.ReadFile(caFile)
if err != nil {
panic(err)
}
caCertPool := x509.NewCertPool()
if ok := caCertPool.AppendCertsFromPEM(caCert); !ok {
panic("Error: CA file must be in PEM format")
}
// Instantiates a Config instance
tlsConfig := &tls.Config{
RootCAs: caCertPool,
}
opts := options.Client().ApplyURI(uri).SetTLSConfig(tlsConfig)
您还可以使用
跳过验证 serverAPI := options.ServerAPI(options.ServerAPIVersion1)
opts := options.Client().ApplyURI(uri).SetServerAPIOptions(serverAPI)
opts.TLSConfig.InsecureSkipVerify = true
测试时跳过验证有时是合理的,但应避免。