英文:
Connecting golang mgo to mongo via ssl
问题
我正在尝试在本地设置MongoDB以测试在https://www.compose.com/articles/connect-to-mongo-3-2-on-compose-from-golang/中描述的设置的部分"A Little Harder"。
MongoDB
我有一组可用的自签名凭据和MongoDB设置。我已经包含了密钥,因为这些密钥只会在开发过程中使用,以确保MongoDB SSL代码正常工作。
使用以下命令运行:
mongod --config config/location
配置如下:
net:
port: 27017
ssl:
mode: requireSSL
CAFile: /data/mongo/ca.crt
PEMKeyFile: /data/mongo/server.pem
allowInvalidHostnames: true
allowConnectionsWithoutCertificates: true
然后可以使用以下命令连接到数据库:
mongo --ssl --sslCAFile /data/mongo/ca.crt
Golang
func NewSession(url string, ca string) (m *mgo.Session, err error) {
roots := x509.NewCertPool()
roots.AppendCertsFromPEM([]byte(ca))
tlsConfig := &tls.Config{}
tlsConfig.RootCAs = roots
url = strings.TrimSuffix(url, "?ssl=true")
dialInfo, err := mgo.ParseURL(url)
dialInfo.DialServer = func(addr *mgo.ServerAddr) (net.Conn, error) {
conn, err := tls.Dial("tcp", addr.String(), tlsConfig)
return conn, err
}
// 这里是session。从这里开始你可以自行处理 ;)
session, err := mgo.DialWithInfo(dialInfo)
if err != nil {
return m, err
}
session.SetMode(mgo.Monotonic, true)
return session, nil
}
结果
Golang部分尝试连接并达到了10秒的超时时间。在session的顶部使用fmt打印显示正确的文件已经传入了ca变量。
MongoDB日志显示:
utumongo_1 | 2017-07-27T08:09:14.964+0000 I NETWORK [initandlisten] connection accepted from 172.19.0.4:57474 #30 (1 connection now open)
utumongo_1 | 2017-07-27T08:09:14.966+0000 E NETWORK [conn30] SSL: error:14094412:SSL routines:SSL3_READ_BYTES:sslv3 alert bad certificate
utumongo_1 | 2017-07-27T08:09:14.967+0000 I NETWORK [conn30] end connection 172.19.0.4:57474 (0 connections now open)
编辑
更新了MongoDB配置
英文:
I'm trying to setup mongo locally to test the setup described in
https://www.compose.com/articles/connect-to-mongo-3-2-on-compose-from-golang/
"A Little Harder" section
Mongo
I have a working set of self signed credentials, and mongo setup.
I've included keys, as those will only be used during dev to make sure mongo ssl code is working.
When using this, running via
mongod --config config/location
The config is
net:
port: 27017
ssl:
mode: requireSSL
CAFile: /data/mongo/ca.crt
PEMKeyFile: /data/mongo/server.pem
allowInvalidHostnames: true
allowConnectionsWithoutCertificates: true
I can then connect to the db with
mongo --ssl --sslCAFile /data/mongo/ca.crt
Golang
func NewSession(url string, ca string) (m *mgo.Session, err error) {
roots := x509.NewCertPool()
roots.AppendCertsFromPEM([]byte(ca))
tlsConfig := &tls.Config{}
tlsConfig.RootCAs = roots
url = strings.TrimSuffix(url, "?ssl=true")
dialInfo, err := mgo.ParseURL(url)
dialInfo.DialServer = func(addr *mgo.ServerAddr) (net.Conn, error) {
conn, err := tls.Dial("tcp", addr.String(), tlsConfig)
return conn, err
}
//Here it is the session. Up to you from here ;)
session, err := mgo.DialWithInfo(dialInfo)
if err != nil {
return m, err
}
session.SetMode(mgo.Monotonic, true)
return session, nil
}
Result
The golang stuff tries to connect and hits the 10s timeout. A fmt at the top of session shows the correct file is making it into the ca var.
Mongo logs show
utumongo_1 | 2017-07-27T08:09:14.964+0000 I NETWORK [initandlisten] connection accepted from 172.19.0.4:57474 #30 (1 connection now open)
utumongo_1 | 2017-07-27T08:09:14.966+0000 E NETWORK [conn30] SSL: error:14094412:SSL routines:SSL3_READ_BYTES:sslv3 alert bad certificate
utumongo_1 | 2017-07-27T08:09:14.967+0000 I NETWORK [conn30] end connection 172.19.0.4:57474 (0 connections now open)
Edit
Updated mongo config
答案1
得分: 3
你将什么作为NewSession
的ca
参数传递?这应该是PEM编码的CA证书字节,而不是CA证书的文件名。如果成功添加了任何证书到证书池中,AppendCertsFromPEM
将返回true
。
文章已经展示了如何实现这一点的代码:
if ca, err := ioutil.ReadFile("myPEM"); err == nil {
roots.AppendCertsFromPEM(ca)
}
SSL错误意味着客户端拒绝了服务器证书。我怀疑这是因为你的自签名证书没有正确添加到证书池中。
编辑
我在本地使用你的配置运行了一个mongo副本。使用Docker,命令如下:
docker run --rm -ti -v $(pwd):/data/mongo --net=host mongo -f /data/mongo/mongo.yaml
在你提取配置的位置运行
在Go中使用你的NewSession
函数时,发现tls.Dial
返回了一个错误,原因是缺少任何主题访问名称(SAN)扩展,如下面的评论所述。
你需要修改服务器证书,以包含所需的主机名(或IP地址)SAN条目。
你可以使用以下代码调试此问题以及其他发生的TLS连接错误:
dialInfo.DialServer = func(addr *mgo.ServerAddr) (net.Conn, error) {
conn, err := tls.Dial("tcp", addr.String(), tlsConfig)
if err != nil {
fmt.Println(err)
}
return conn, err
}
英文:
What are you passing into NewSession
as the ca
parameter? This needs to be the PEM encoded CA certificate bytes, not the file name of the CA certificate. AppendCertsFromPEM
will return true
if it managed to add any certificates to the pool.
The article already shows code to do this:
if ca, err := ioutil.ReadFile("myPEM"); err == nil {
roots.AppendCertsFromPEM(ca)
}
The SSL error means that the client is rejecting the server certificate. I suspect it is because your self-signed certificate was not added to the pool correctly.
EDIT
I ran a copy of mongo locally with your config. Using docker, this was:
docker run --rm -ti -v $(pwd):/data/mongo --net=host mongo -f /data/mongo/mongo.yaml
When ran from where your configuration was extracted
Using your NewSession
func inside Go showed that the tls.Dial
was returning an error due to the lack of any Subject Access Name (SAN) extensions as per my comment below.
You will need to correct your server certificate to have the appropriate host name (or IP address) SAN entries required.
You can debug this and any other TLS connection errors that occur with:
dialInfo.DialServer = func(addr *mgo.ServerAddr) (net.Conn, error) {
conn, err := tls.Dial("tcp", addr.String(), tlsConfig)
if err != nil {
fmt.Println(err)
}
return conn, err
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论