如何使用 Node.js 建立到 MongoDB 数据库的 SSH 隧道连接
How to use Node.js to make a SSH tunneling connection to a MongoDB database
我的凭据与 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
});
以及 tunnel-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 连接字符串还是将数据库引用为本地主机,例如
mongodb://localhost:portnumber.
或
mongodb://databasepath.subpath.mongodbdns.com:27000
Localhost给我一个权限被拒绝的错误,后者给我一个超时
由于 mongoose
不支持传入流以用作基础连接,您将必须侦听本地端口(例如 27000)并通过 ssh 连接将传入连接转发到该端口。
幸运的是,存在基于 ssh2
构建的第三方模块,可为您提供此类功能,例如 tunnel-ssh
。尝试使用其中之一。
正如 mscdex 提到的,ssh2 不是用于建立到数据库的 ssh 隧道连接的好模块。 tunnel-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
}
您可以使用官方 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()
});
});
});
});
由于上述所有答案出于某种原因对我都不起作用,所以我发布了对我有用的代码。我正在从我的 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);
我的凭据与 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
});
以及 tunnel-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 连接字符串还是将数据库引用为本地主机,例如
mongodb://localhost:portnumber.
或
mongodb://databasepath.subpath.mongodbdns.com:27000
Localhost给我一个权限被拒绝的错误,后者给我一个超时
由于 mongoose
不支持传入流以用作基础连接,您将必须侦听本地端口(例如 27000)并通过 ssh 连接将传入连接转发到该端口。
幸运的是,存在基于 ssh2
构建的第三方模块,可为您提供此类功能,例如 tunnel-ssh
。尝试使用其中之一。
正如 mscdex 提到的,ssh2 不是用于建立到数据库的 ssh 隧道连接的好模块。 tunnel-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
}
您可以使用官方 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()
});
});
});
});
由于上述所有答案出于某种原因对我都不起作用,所以我发布了对我有用的代码。我正在从我的 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);