使用Node.js通过SSL连接到MongoDB

如何使用Node.js通过SSL连接到MongoDB服务器?

我已经阅读了一些驱动程序( mongojs , mongodb-native )的源代码,我一直在使用googlesearch,但似乎找不到任何适当的教程,指南或文档。

第1步:获取MongoDB 3.0

首先你需要知道的是,SSL只支持MongoDB 3.0和更高版本。 Ubuntu在默认存储库中没有3.0,所以以下是你如何得到它:

 sudo apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv 7F0CEB10 echo "deb http://repo.mongodb.org/apt/ubuntu trusty/mongodb-org/3.0 multiverse" | sudo tee /etc/apt/sources.list.d/mongodb-org-3.0.list sudo apt-get update sudo apt-get install -y mongodb-org=3.0.7 mongodb-org-server=3.0.7 mongodb-org-shell=3.0.7 mongodb-org-mongos=3.0.7 mongodb-org-tools=3.0.7 

3.0.7是目前最新的稳定版本,但随意用你最喜欢的版本replace3.0.7。

步骤2:获取私钥,证书和PEM文件

PEM包含一个公钥证书及其相关的私钥。 这些文件可以从Certificate Authroity获得,也可以用OpenSSL生成,如下所示:

 openssl req -newkey rsa:2048 -new -x509 -days 3650 -nodes -out mongodb-cert.crt -keyout mongodb-cert.key cat mongodb-cert.key mongodb-cert.crt > mongodb.pem 

mongodb.pem将用作PEM文件,mongodb-cert.key是私钥文件,mongodb-cert.crt是证书文件,也可以用作CA文件。 你将需要所有这三个。

第3步:configurationMongoD

我们假设您将这些文件复制到您所属的/ etc / ssl /文件夹中。 现在我们打开我们的MongoDBconfiguration文件:

 sudo vi /etc/mongod.conf 

并修改“#networking接口”部分,如下所示:

 # network interfaces net: port: 27017 #bindIp: 127.0.0.1 ssl: mode: allowSSL PEMKeyFile: /etc/ssl/mongodb.pem #CAFile: /etc/ssl/mongodb-cert.crt 

请注意:我们正在注释bindIp。 这允许外部连接访问您的Mongo数据库。 我们假设这是您的最终目标(您为什么要在本地主机上encryptionstream量?),但是您应该只在为您的MongoDB服务器设置授权规则后执行此操作。

CAFile也被注释掉,因为它是可选的。 我将解释如何在本文后面设置证书颁发机构信任。

与往常一样,在configuration文件更改生效之前,您必须重新启动MongoDB:

 sudo service mongod restart 

使您的服务器无法启动? 你是自己的,但是你的证书文件可能有问题。 您可以通过手动运行mongod来检查启动错误:

 sudo mongod --config /etc/mongod.conf 

第4步:testing您的服务器设置

在我们讨论Nodeconfiguration之前,让我们确保你的服务器设置通过连接mongo命令行客户端来正常工作:

 mongo --ssl --sslAllowInvalidHostnames --sslAllowInvalidCertificates 

除非证书上的域名是127.0.0.1或localhost,否则–sslAllowInvalidHostnames标志是必需的。 没有它,你可能会得到这个错误:

 E NETWORK The server certificate does not match the host name 127.0.0.1 E QUERY Error: socket exception [CONNECT_ERROR] for at connect (src/mongo/shell/mongo.js:179:14) at (connect):1:6 at src/mongo/shell/mongo.js:179 exception: connect failed 

步骤5)configurationNode.JS / Mongoose

如果您在Node应用程序中使用node-mongodb-native软件包,请立即停止并开始使用Mongoose。 这并不难。 也就是说,mongoose.connect()与mongodb.connect()具有几乎相同的API,所以适当replace。

  var fs = require('fs') , mongoose = require('mongoose') , mongoUri = "mongodb://127.0.0.1:27017?ssl=true" , mongoOpt = { "server": { "sslValidate": false, "sslKey": fs.readFileSync('/etc/ssl/mongodb.pem'), "sslCert": fs.readFileSync('/etc/ssl/mongodb-cert.crt') } } ; mongoose.connect(mongoUri, mongoOpt); 

步骤6)[可选]通过证书颁发机构validation您的证书

为了validation您的SSL证书,您需要从您的证书颁发机构获取一个CA(或包)文件。 这看起来很像你的证书文件,但是通常会包含多个证书(它们组成了可信的证书来validation证书的有效性)。 如果您使用的是自签名证书,则可以使用您的mongodb-cert.crt作为CA文件。

您还需要确保您的MongoDB服务器的主机名与用于创build证书的主机名相匹配。

步骤6.3)更新你的mongodconfiguration

 sudo vi /etc/mongod.conf 

并修改“#networking接口”部分,如下所示:

 # network interfaces net: port: 27017 #bindIp: 127.0.0.1 ssl: mode: allowSSL PEMKeyFile: /etc/ssl/mongodb.pem CAFile: /etc/ssl/mongodb-ca.crt sudo service mongod restart 

步骤6.4)testing你的服务器设置

 mongo --ssl --sslAllowInvalidHostnames --sslCAFile /etc/ssl/mongodb-ca.crt --sslPEMKeyFile /etc/ssl/mongodb.pem 

Mongo客户端也可以通过CA文件以validation他们正在与正确的服务器通话。 这是用–sslCAFile参数完成的

使用CAFileconfiguration的Mongo服务器要求客户端拥有有效的证书和服务器的私钥。 在mongo shell客户端中,这是通过传入–sslPEMKeyFile参数来完成的。

没有PEM文件(包含服务器的证书),您可能会看到这个错误:

 I NETWORK DBClientCursor::init call() failed E QUERY Error: DBClientBase::findN: transport error: 127.0.0.1:27017 ns: admin.$cmd query: { whatsmyuri: 1 } at connect (src/mongo/shell/mongo.js:179:14) at (connect):1:6 at src/mongo/shell/mongo.js:179 exception: connect failed 

可以将服务器configuration为通过启用net.ssl.weakCertificateValidation来接受来自没有PEM文件的客户端的请求,但是您将会削弱您的安全性而无法获得真正的收益。

步骤6.5)configurationNode.JS / Mongoose

这里有几个陷阱,和我一起裸露。

首先,你需要具有node-mongodb-native 2.0或更高版本。 如果您使用的是Mongoose,那么您需要Mongoose 4.0或更高版本。 以前的Mongoose版本使用node-mongodb-native 1. *,它不支持以任何身份进行证书validation。

其次,在node-mongodb-native中不存在sslAllowInvalidHostnames或类似的选项。 这不是node-mongodb本地开发人员可以修复的问题(我现在就可以修复),因为Node 0.10。*中提供的本地TLS库不提供此选项。 在节点4. *和5. *中,有一个checkServerIdentity选项可以提供希望,但是在io.js合并之后从原始节点分支切换到分支可能会导致当前的一些头痛。

所以我们来试试这个:

 var fs = require('fs') , mongoose = require('mongoose') , mongoUri = "mongodb://127.0.0.1:27017?ssl=true" , mongoOpt = { "server": { "sslKey": fs.readFileSync('/etc/ssl/mongodb.pem'), "sslCert": fs.readFileSync('/etc/ssl/mongodb-cert.crt'), "sslCa": fs.readFileSync('/etc/ssl/mongodb-ca.crt') } } ; 

如果您正在获取主机名/ IP不匹配错误,请修复您的证书,或通过禁用sslValidate来否定所有这些难题。

 var fs = require('fs') , mongoose = require('mongoose') , mongoUri = "mongodb://127.0.0.1:27017?ssl=true" , mongoOpt = { "server": { "sslValidate": false, "sslKey": fs.readFileSync('/etc/ssl/mongodb.pem'), "sslCert": fs.readFileSync('/etc/ssl/mongodb-cert.crt'), "sslCa": fs.readFileSync('/etc/ssl/mongodb-ca.crt') } } ; 

资料来源: http : //www.bainweb.com/2015/11/connecting-to-mongodb-over-tlsssl-with.html

正如评论中所build议的那样, node-mongodb-native拥有所有需要的东西。

我用它来运行并运行:

 var mongo = require('mongodb'); var server = new mongo.Server('HOSTNAME', 27017, { ssl: true }); var db = new mongo.Db('NAME_OF_MY_DB', server, { w: 1 }); var auth = { user: 'USERNAME', pass: 'PASSWORD' }; db.open(function(err, db) { if (err) return console.log("error opening", err); db.authenticate(auth.user, auth.pass, function(err, result) { if (err) return console.log("error authenticating", err); console.log("authed?", result); db.collection('whatever').count(function(err, count) { if (err) return console.log("error counting", err); console.log("count", count); db.close() }); }); }); 

编辑

你也可以从mongoose做ssl:

 mongoose.createConnection(connString, { server: { ssl: true }}) 

如果要使用证书进行身份validation,请使用node-mongodb-native

 var buffer = require('fs').readFileSync("mongodb.pem"); var MongoClient = require('mongodb').MongoClient; MongoClient.connect("mongodb://hostname:27017/test?ssl=true", { server: { sslKey: buffer, sslCert: buffer, sslValidate: false //in case of self-generated certificate } }, function(err, db) { console.log(err); console.log(db); db.close(); });