使用 PyMongo 的自签名 SSL 连接
Self-signed SSL connection using PyMongo
我正在尝试使用 PyMongo 创建到 MongoDB 的安全 SSL 连接。目标是将此配置用于我可以与 Python 客户端连接的 EC2 上的 Mongo 实例 运行ning。为了进行测试,我只是想先让配置在本地运行。可以找到我尚未失败的尝试 here.
我认为问题的简短版本:我的客户端证书颁发机构文件 ca.pem
不正确。按照我的方式,这个文件实际上与我在服务器端使用的文件相同。两者都是使用 x509
和 openssl
创建的,我怀疑我的客户端文件需要某种不同的内容,但我不确定究竟如何生成该内容,或者这种怀疑是否正确.
以下是我为创建必要的证书和密钥所做的详细信息(在 Mac El Capitan 上):
首先,生成证书颁发机构:
$ mkdir ~/ssl
$ cd ~/ssl
$ openssl req -out ca.pem -new -x509 -days 3650
# enter info
生成服务器.pem
文件:
$ openssl genrsa -out server.key 2048
$ openssl req -key server.key -new -out server.req
# enter info
$ openssl x509 -req -in server.req -CA ca.pem -CAkey privkey.pem -CAserial file.srl -out server.crt -days 3650
$ cat server.key server.crt > server.pem
现在为客户做同样的事情:
$ openssl genrsa -out client.key 2048
$ openssl req -key client.key -new -out client.req
$ openssl x509 -req -in client.req -CA ca.pem -CAkey privkey.pem -CAserial file.srl -out client.crt -days 3650
$ cat client.key client.crt > client.pem
然后我在etc/mongod.conf
中做如下配置:
net:
...
ssl:
mode: requireSSL
PEMKeyFile: ~/ssl/server.pem
CAFile: ~/ssl/ca.pem
现在开始 mongo (Mac)
$ mongod --config /etc/mongod.conf
按预期工作。进程 运行s,似乎正在接受配置。
然后在 Python 端(也在本地主机上 运行ning 进行调试),我在调用 mongo 时执行以下操作:
import ssl
from pymongo import MongoClient
client = MongoClient(
'127.0.0.1',
27017,
ssl=True,
ssl_certfile='~/ssl/client.pem',
ssl_cert_reqs=ssl.CERT_REQUIRED,
ssl_ca_certs='~/ssl/ca.pem'
)
# try a simple insert
当我 运行 这个时,Python 代码块在创建 MongoClient
之后,我在 mongo
日志中看到:
2016-03-03T22:11:30.331-0800 E NETWORK [conn21] SSL: error:14094418:SSL routines:ssl3_read_bytes:tlsv1 alert unknown ca
根据下面万的评论,我重做了整个事情,确保'Distinguished Name'中的信息与那些规范一致。旧版本肯定为服务器和客户端使用相同的通用名称。连接仍未成功,但消息有些不同:
2016-03-11T12:29:40.380-0800 I NETWORK [initandlisten] connection accepted from 127.0.0.1:57363 #3 (1 connection now open)
2016-03-11T12:29:40.386-0800 I NETWORK [conn3] end connection 127.0.0.1:57363 (0 connections now open)
这 2 条消息一直重复,直到我停止 Python 进程,该进程在尝试打开连接时阻塞。 end connection
部分现在位于 alert unknown ca
行之前在 mongo 日志中的位置。
用于调试的附加信息:
$ openssl verify -CAfile ca.pem client.pem
client.pem: OK
$ openssl verify -CAfile ca.pem server.pem
server.pem: OK
$ openssl x509 -noout -subject -in server.pem
subject= /C=US/ST=Washington/L=Seattle/O=codeMelon/OU=Engineering/CN=server.com/emailAddress=<my-email-address>@gmail.com
$ openssl x509 -noout -subject -in client.pem
subject= /C=US/ST=Washington/L=Seattle/O=codeMelon/OU=Engineering/CN=client.com/emailAddress=<my-email-address>@gmail.com
正确形成主题行后的底线是 mongo 正在接受连接,然后结束它,并且 Python 进程在没有进行预期插入的情况下被阻塞。
非常感谢任何帮助!
还有其他方法可以用 Certificate Authority 生成 server/client pem,即不涉及 file.srl
,但这个答案是为了跟进这个问题。
值得一提的是,大多数 MongoDB v3.0+ 发行版现在都包含对 SSL 的支持,请务必选择支持 SSL 的软件包。下面的例子是用 MongoDB v3.2 on Ubuntu Linux 14.04 with PyMongo v3.2.1 测试的。出于演示目的,一台机器生成 CA、服务器和客户端 pem 文件。
让我们生成 ca.pem
和 privkey.pem
。主题结构为 /C=<Country Name>/ST=<State>/L=<Locality Name>/O=<Organisation Name>/emailAddress=<email>/CN=<Common Name>
.
mkdir ~/ssl
cd ~/ssl
openssl req -out ca.pem -new -x509 -days 3650 -subj "/C=AU/ST=NSW/O=Organisation/CN=root/emailAddress=user@domain.com"
生成 server .pem
文件:
hostname # note down the value
echo "00" > file.srl # two random digits number
openssl genrsa -out server.key 2048
openssl req -key server.key -new -out server.req -subj "/C=AU/ST=NSW/O=Organisation/CN=server1/CN=<hostname value>/emailAddress=user@domain.com"
openssl x509 -req -in server.req -CA ca.pem -CAkey privkey.pem -CAserial file.srl -out server.crt -days 3650
cat server.key server.crt > server.pem
openssl verify -CAfile ca.pem server.pem
虽然您也可以使用 IP 地址作为 CN
值,但不推荐这样做。参见 RFC-6125。
现在让我们生成 client.pem
文件:
openssl genrsa -out client.key 2048
openssl req -key client.key -new -out client.req -subj "/C=AU/ST=NSW/O=Organisation/CN=client1/emailAddress=user@domain.com"
openssl x509 -req -in client.req -CA ca.pem -CAkey privkey.pem -CAserial file.srl -out client.crt -days 3650
cat client.key client.crt > client.pem
openssl verify -CAfile ca.pem client.pem
生成 .pem
个文件后,现在您可以 运行 mongod。例如:
mongod --sslMode requireSSL --sslPEMKeyFile ~/server.pem --sslCAFile ~/ca.pem
您可以使用 mongo shell 测试连接,例如:
mongo --ssl --sslPEMKeyFile ~/client.pem --sslCAFile ~/ca.pem --host <server hostname>
连接成功后,您可以尝试使用PyMongo。例如:
import ssl
from pymongo import MongoClient
client = MongoClient(
'<server hostname>',
27017,
ssl=True,
ssl_certfile='~/client.pem',
ssl_cert_reqs=ssl.CERT_REQUIRED,
ssl_ca_certs='~/ca.pem'
)
或者,您也可以使用 mongod
标志 --sslAllowInvalidHostnames 来指定 localhost
,等等
对于生产用途,您的 MongoDB 部署应使用由单个证书颁发机构生成和签名的有效证书。如果您使用自签名证书,虽然通信通道将被加密,但不会验证服务器身份。使用由受信任的证书颁发机构签署的证书将允许 MongoDB 驱动程序验证服务器的身份。通常,除非网络是可信的,否则请避免使用自签名证书。
您可能会觉得有用的其他相关链接:
我正在尝试使用 PyMongo 创建到 MongoDB 的安全 SSL 连接。目标是将此配置用于我可以与 Python 客户端连接的 EC2 上的 Mongo 实例 运行ning。为了进行测试,我只是想先让配置在本地运行。可以找到我尚未失败的尝试 here.
我认为问题的简短版本:我的客户端证书颁发机构文件 ca.pem
不正确。按照我的方式,这个文件实际上与我在服务器端使用的文件相同。两者都是使用 x509
和 openssl
创建的,我怀疑我的客户端文件需要某种不同的内容,但我不确定究竟如何生成该内容,或者这种怀疑是否正确.
以下是我为创建必要的证书和密钥所做的详细信息(在 Mac El Capitan 上):
首先,生成证书颁发机构:
$ mkdir ~/ssl
$ cd ~/ssl
$ openssl req -out ca.pem -new -x509 -days 3650
# enter info
生成服务器.pem
文件:
$ openssl genrsa -out server.key 2048
$ openssl req -key server.key -new -out server.req
# enter info
$ openssl x509 -req -in server.req -CA ca.pem -CAkey privkey.pem -CAserial file.srl -out server.crt -days 3650
$ cat server.key server.crt > server.pem
现在为客户做同样的事情:
$ openssl genrsa -out client.key 2048
$ openssl req -key client.key -new -out client.req
$ openssl x509 -req -in client.req -CA ca.pem -CAkey privkey.pem -CAserial file.srl -out client.crt -days 3650
$ cat client.key client.crt > client.pem
然后我在etc/mongod.conf
中做如下配置:
net:
...
ssl:
mode: requireSSL
PEMKeyFile: ~/ssl/server.pem
CAFile: ~/ssl/ca.pem
现在开始 mongo (Mac)
$ mongod --config /etc/mongod.conf
按预期工作。进程 运行s,似乎正在接受配置。
然后在 Python 端(也在本地主机上 运行ning 进行调试),我在调用 mongo 时执行以下操作:
import ssl
from pymongo import MongoClient
client = MongoClient(
'127.0.0.1',
27017,
ssl=True,
ssl_certfile='~/ssl/client.pem',
ssl_cert_reqs=ssl.CERT_REQUIRED,
ssl_ca_certs='~/ssl/ca.pem'
)
# try a simple insert
当我 运行 这个时,Python 代码块在创建 MongoClient
之后,我在 mongo
日志中看到:
2016-03-03T22:11:30.331-0800 E NETWORK [conn21] SSL: error:14094418:SSL routines:ssl3_read_bytes:tlsv1 alert unknown ca
根据下面万的评论,我重做了整个事情,确保'Distinguished Name'中的信息与那些规范一致。旧版本肯定为服务器和客户端使用相同的通用名称。连接仍未成功,但消息有些不同:
2016-03-11T12:29:40.380-0800 I NETWORK [initandlisten] connection accepted from 127.0.0.1:57363 #3 (1 connection now open)
2016-03-11T12:29:40.386-0800 I NETWORK [conn3] end connection 127.0.0.1:57363 (0 connections now open)
这 2 条消息一直重复,直到我停止 Python 进程,该进程在尝试打开连接时阻塞。 end connection
部分现在位于 alert unknown ca
行之前在 mongo 日志中的位置。
用于调试的附加信息:
$ openssl verify -CAfile ca.pem client.pem
client.pem: OK
$ openssl verify -CAfile ca.pem server.pem
server.pem: OK
$ openssl x509 -noout -subject -in server.pem
subject= /C=US/ST=Washington/L=Seattle/O=codeMelon/OU=Engineering/CN=server.com/emailAddress=<my-email-address>@gmail.com
$ openssl x509 -noout -subject -in client.pem
subject= /C=US/ST=Washington/L=Seattle/O=codeMelon/OU=Engineering/CN=client.com/emailAddress=<my-email-address>@gmail.com
正确形成主题行后的底线是 mongo 正在接受连接,然后结束它,并且 Python 进程在没有进行预期插入的情况下被阻塞。
非常感谢任何帮助!
还有其他方法可以用 Certificate Authority 生成 server/client pem,即不涉及 file.srl
,但这个答案是为了跟进这个问题。
值得一提的是,大多数 MongoDB v3.0+ 发行版现在都包含对 SSL 的支持,请务必选择支持 SSL 的软件包。下面的例子是用 MongoDB v3.2 on Ubuntu Linux 14.04 with PyMongo v3.2.1 测试的。出于演示目的,一台机器生成 CA、服务器和客户端 pem 文件。
让我们生成 ca.pem
和 privkey.pem
。主题结构为 /C=<Country Name>/ST=<State>/L=<Locality Name>/O=<Organisation Name>/emailAddress=<email>/CN=<Common Name>
.
mkdir ~/ssl
cd ~/ssl
openssl req -out ca.pem -new -x509 -days 3650 -subj "/C=AU/ST=NSW/O=Organisation/CN=root/emailAddress=user@domain.com"
生成 server .pem
文件:
hostname # note down the value
echo "00" > file.srl # two random digits number
openssl genrsa -out server.key 2048
openssl req -key server.key -new -out server.req -subj "/C=AU/ST=NSW/O=Organisation/CN=server1/CN=<hostname value>/emailAddress=user@domain.com"
openssl x509 -req -in server.req -CA ca.pem -CAkey privkey.pem -CAserial file.srl -out server.crt -days 3650
cat server.key server.crt > server.pem
openssl verify -CAfile ca.pem server.pem
虽然您也可以使用 IP 地址作为 CN
值,但不推荐这样做。参见 RFC-6125。
现在让我们生成 client.pem
文件:
openssl genrsa -out client.key 2048
openssl req -key client.key -new -out client.req -subj "/C=AU/ST=NSW/O=Organisation/CN=client1/emailAddress=user@domain.com"
openssl x509 -req -in client.req -CA ca.pem -CAkey privkey.pem -CAserial file.srl -out client.crt -days 3650
cat client.key client.crt > client.pem
openssl verify -CAfile ca.pem client.pem
生成 .pem
个文件后,现在您可以 运行 mongod。例如:
mongod --sslMode requireSSL --sslPEMKeyFile ~/server.pem --sslCAFile ~/ca.pem
您可以使用 mongo shell 测试连接,例如:
mongo --ssl --sslPEMKeyFile ~/client.pem --sslCAFile ~/ca.pem --host <server hostname>
连接成功后,您可以尝试使用PyMongo。例如:
import ssl
from pymongo import MongoClient
client = MongoClient(
'<server hostname>',
27017,
ssl=True,
ssl_certfile='~/client.pem',
ssl_cert_reqs=ssl.CERT_REQUIRED,
ssl_ca_certs='~/ca.pem'
)
或者,您也可以使用 mongod
标志 --sslAllowInvalidHostnames 来指定 localhost
,等等
对于生产用途,您的 MongoDB 部署应使用由单个证书颁发机构生成和签名的有效证书。如果您使用自签名证书,虽然通信通道将被加密,但不会验证服务器身份。使用由受信任的证书颁发机构签署的证书将允许 MongoDB 驱动程序验证服务器的身份。通常,除非网络是可信的,否则请避免使用自签名证书。
您可能会觉得有用的其他相关链接: