如何使用 Node.js 建立与 MongoDB 数据库的 SSH 隧道连接
Posted
技术标签:
【中文标题】如何使用 Node.js 建立与 MongoDB 数据库的 SSH 隧道连接【英文标题】:How to use Node.js to make a SSH tunneling connection to a MongoDB database 【发布时间】:2016-11-25 09:16:22 【问题描述】:我的凭据与 Robomongo 完美配合,但我无法与 node.js 建立连接 我尝试使用 ssh2 和 tunnel-ssh npm 模块建立连接,但两次都失败了。 -mongo连接不需要密码 - ssh 连接是使用 pem 密钥建立的
这是我在 ssh2 模块中使用的代码,我可以正确建立隧道但 mongo 连接失败
var Client = require('ssh2').Client;
var conn = new Client();
conn.on('ready', function()
console.log('Client :: ready');
//mongo connection
mongoose.connect('mongodb://localhost:27000/');
var db = mongoose.connection;
db.on('error', console.error.bind(console, 'connection error:'));
db.once('open', function()
console.log("database connection established");
var users = db.collection('user');
var getallUsers = function (date, callback)
users.find().toArray(function(err,data)
callback(data);
)
;
getallUsers(null, function (data)
console.log('data :'+ data);
);
);
//end of mongo connection
).connect(
host: '**.**.**.**.**',
port: 22,
username: 'ec2-user',
privateKey: key
);
还有隧道 ssh 的代码
var config =
dstPort: 27000,
user: 'ec2-user',
host: '**.**.**.**.**',
privateKey: key
;
var server = tunnel(config, function (error, server)
if(error)
console.log("SSH connection error: " + error);
console.log('database connection initalizing');
mongoose.connect('mongodb://localhost:27000/');
var db = mongoose.connection;
db.on('error', console.error.bind(console, 'connection error:'));
db.once('open', function()
console.log("database connection established");
var users = db.collection('user');
var getallUsers = function (date, callback)
users.find().toArray(function(err,data)
callback(data);
)
;
getallUsers(null, function (data)
console.log(data);
);
);
);
我不确定是在建立隧道后使用常规的 MongoDB 连接字符串还是将数据库称为 localhost,例如 mongodb://localhost:portnumber. 或 mongodb://databasepath.subpath.mongodbdns.com:27000
Localhost 给了我一个权限被拒绝的错误,后者给了我一个超时
【问题讨论】:
【参考方案1】:正如 mscdex 提到的,ssh2 不是一个用于建立与数据库的 ssh 隧道连接的好模块。隧道 ssh 更合适。
这是我使用的配置选项:
dstPort:远程数据库连接端口
localPort:与 dstPort 相同,它将是您将用于本地计算机的端口
用户名:SSH用户名,
主机:SSH地址
dstHost: 数据库连接url (...mongodbns.com) ,
privateKey:SSH 密钥
然后,一旦您的隧道连接通过猫鼬连接到您的本地主机,例如 mondodb://localhost:27000(使用您在 localPort 中定义的本地端口)
var server = tunnel(config, function (error, server)
if(error)
console.log("SSH connection error: " + error);
mongoose.connect('mongodb://localhost:27000/');
//...rest of mongoose connection
【讨论】:
我得到了这个>> 错误:所有配置的身份验证方法都失败 注意:我正在使用 require('mongodb').MongoClient ,require('tunnel- ssh'),var config = 用户名:'root',密码:'xxxxxx',主机:“xx11.130”,dstHost:“xx11.130”,端口:22,dstHost:url,dstPort:10945,localPort:10945 ; 仅供参考,tunnel-ssh 内部使用 ssh2 建立隧道【参考方案2】:由于mongoose
不支持传入流以用作底层连接,因此您必须侦听本地端口(例如 27000)并通过 ssh 连接将传入连接转发到该端口。
幸运的是,存在基于ssh2
的第三方模块,可为您提供此类功能,例如tunnel-ssh
。尝试使用其中之一。
【讨论】:
感谢回复我也花了很多时间在隧道 ssh 上,我无法连接它,我的隧道 ssh 代码在上面。 您是否尝试在配置对象中使用username
而不是user
?【参考方案3】:
你可以用官方的mongodb客户端来做节点
const sshTunnelConfig =
agent: process.env.SSH_AUTH_SOCK,
username: 'ec2-user',
privateKey: require('fs').readFileSync('./path-to-ec2-key.pem'),
host: '3.98.174.12', //IP adress of VPS which is the SSH server
port: 22,
dstHost: 'docdb-cluster-vmabwxueb51y.eu-central-1.docdb.amazonaws.com',
dstPort: 27017,
localHost: '127.0.0.1',
localPort: 27018 //or anything else unused you want
;
const connectionProperties =
sslValidate: true,
ssl: true,
sslCA: [fs.readFileSync('rds-combined-ca-bundle.pem')],
useNewUrlParser: true,
useUnifiedTopology: true,
authMechanism: 'SCRAM-SHA-1',
auth:
user: 'docdbuser',
password: '<PASSWORD>'
,
tlsAllowInvalidHostnames: true,
tlsAllowInvalidCertificates: true,
;
tunnel(sshTunnelConfig, async (error, server) =>
if (error)
console.log('SSH connection error: ', error);
const MongoClient = require('mongodb').MongoClient;
const client = MongoClient.connect('mongodb://localhost:27018/', propertiesConnection,
function(err, client)
if(err)
throw err;
//Specify the database to be used
db = client.db('database-name');
//Specify the collection to be used
col = db.collection('collection-name');
//Insert a single document
col.insertOne('hello':'Amazon DocumentDB', function(err, result)
//Find the document that was previously written
col.findOne('hello':'Amazon DocumentDB', function(err, result)
//Print the result to the screen
console.log(result);
//Close the connection
client.close()
);
);
);
);
【讨论】:
感谢您分享这些代码,但您确定该块运行良好吗?我试图做同样的事情。 SSH 连接没问题,但之后,我无法连接 mongo 客户端。我尝试使用您的示例代码并再次尝试。 propertiesConnection 与 connectionProperties 没有意义....这是否经过测试?sshTunnelConfig
对象的属性似乎与tunnel-ssh 的接口相匹配。以下 q/a 应该更有助于使其正常工作:***.com/questions/40903566/…【参考方案4】:
由于某些原因,上述所有答案都对我不起作用,因此我发布了对我有用的代码。我正在从我的 Nodejs 网络服务器隧道到在线 ubuntu vm 上的 PostgreSQL 数据库:
const SSH2Promise = require('ssh2-promise');
const Client = require('pg');
let config =
host:process.env.SSH_HOST, //your machine IP-address like [193.xxx.xx.xxx]
port:process.env.SSH_PORT, //port you ssh to, probably 22
username: process.env.SSH_USERNAME, //username of your machine
privateKey: fs.readFileSync(path.join(__dirname, "../" + process.env.PRIVATE_KEY)) //your ssh private key to log in
;
function getDBConfig(port)
return new Client(
user: process.env.DB_USER,
host: process.env.DB_HOST,
database: process.env.DB_NAME,
password: process.env.DB_PASS,
port: port,
);
async function makeDb(port)
let dbClient = getDBConfig(port);
await dbClient.connect();
return
async query(sql)
return (await dbClient.query(sql)).rows;
;
const sshConn = new SSH2Promise(config);
let con;
(async function()
await sshConn.connect();
console.log("Connection established");
let tunnel = await sshConn.addTunnel(remoteAddr: process.env.REMOTE_HOST, remotePort: process.env.REMOTE_PORT);
//Remote host: just use 127.0.0.1
//Remote port: port where your db is connected to ex: 5432
con = await makeDb(tunnel.localPort);
)();
//use connection like this:
await con.query("SELECT ... sql statement here);
【讨论】:
以上是关于如何使用 Node.js 建立与 MongoDB 数据库的 SSH 隧道连接的主要内容,如果未能解决你的问题,请参考以下文章
如何使用 mongoose 将本地 mongodb 与 node.js 应用程序连接?
javascript 如何将MongoDB与Node.js一起使用
如何将 Mongoose/Mongodb 与 node.js- 护照身份验证一起使用