无法通过GoLang连接AWS DocumentDB,证书验证报错求助
解决GoLang mongo-driver连接AWS DocumentDB的证书验证问题
问题背景
已通过SSH隧道建立本地端口转发:
ssh -i "key.pem" -L 28100:endpoint.docdb.amazonaws.com:27017 ec2-user@111.111.111.111.region.compute.amazonaws.com
使用如下URI连接时,Mongo Compass可以正常访问AWS DocumentDB,但GoLang的mongo-driver连接失败:
mongodb://user:password@localhost:28100/?ssl=true&ssl_ca_certs=secrets/global-bundle.pem&retryWrites=false&directConnection=true
错误信息
server selection error: server selection timeout, current topology: { Type: Single, Servers: [{ Addr: localhost:28100, Type: Unknown, Last error: tls: failed to verify certificate: x509: certificate is valid for endpoint.docdb.amazonaws.com, not localhost }, ] }
问题原因
DocumentDB返回的TLS证书是签发给自己的官方端点域名(endpoint.docdb.amazonaws.com),但Go客户端连接的是localhost:28100,证书域名与连接地址不匹配,导致TLS验证失败。Mongo Compass内部自动处理了这种域名映射,所以可以正常连接。
解决方案
在Go的TLS配置中指定ServerName为DocumentDB的真实端点域名,让TLS验证时用该域名匹配证书:
import ( "crypto/tls" "crypto/x509" "context" "io/ioutil" "log" "time" "go.mongodb.org/mongo-driver/mongo" "go.mongodb.org/mongo-driver/mongo/options" ) func main() { uri := "mongodb://user:password@localhost:28100/?ssl=true&retryWrites=false&directConnection=true" connectTimeout := 10 docdbEndpoint := "endpoint.docdb.amazonaws.com" // 替换为你的DocumentDB实际端点 // 加载CA证书 caCertBytes, err := ioutil.ReadFile("secrets/global-bundle.pem") if err != nil { log.Fatalf("无法读取CA证书: %v", err) } certPool := x509.NewCertPool() if !certPool.AppendCertsFromPEM(caCertBytes) { log.Fatal("无法将CA证书添加到证书池") } // 配置TLS,指定ServerName为DocumentDB端点域名 tlsCfg := &tls.Config{ RootCAs: certPool, ServerName: docdbEndpoint, // 关键配置:让TLS验证使用DocumentDB的域名 MinVersion: tls.VersionTLS12, // 可选:强制使用符合AWS要求的TLS版本 } // 创建Mongo客户端并设置TLS配置 clientOpts := options.Client().ApplyURI(uri).SetTLSConfig(tlsCfg) client, err := mongo.Connect(context.TODO(), clientOpts) if err != nil { log.Fatalf("创建客户端失败: %v", err) } defer func() { if err := client.Disconnect(context.TODO()); err != nil { log.Fatal(err) } }() // 验证连接 ctx, cancel := context.WithTimeout(context.Background(), time.Duration(connectTimeout)*time.Second) defer cancel() if err := client.Ping(ctx, nil); err != nil { log.Fatalf("Ping失败: %v", err) } log.Println("成功连接到DocumentDB!") }
关键说明
ServerName必须设置为DocumentDB的真实端点域名,确保TLS验证时匹配证书的域名字段- 确保CA证书路径正确,且证书文件能正常读取
- 连接URI保持
localhost:28100即可,SSH隧道会负责端口转发
内容的提问来源于stack exchange,提问作者Boon
相关产品推荐
相关产品推荐

