How to use Node.js to make a SSH tunneling connection to a MongoDB database

17,442

Solution 1

As mscdex mentioned ssh2 isn't a good module to use to make an ssh tunnel connection to a database. tunnel-ssh is more appropriate.

Here are the configuration options I've used :

dstPort: remote database connection port

localPort: same as dstPort, It'll be the port you'll use for your local machine

username: SSH username,

host: SSH address

dstHost: database connection url (...mongodbns.com) ,

privateKey: SSH key

Then once your tunnel is connected connect via mongoose to your localhost such as mondodb://localhost:27000 (use the localport you defined in 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
}

Solution 2

Since mongoose does not support passing in a stream to use as the underlying connection, you will have to listen on a local port (e.g. 27000) and forward incoming connections to that port over the ssh connection.

Fortunately there exists third party modules that build on ssh2 that provide this kind of functionality for you, such as tunnel-ssh. Try using one of those.

Share:
17,442
user3382714
Author by

user3382714

Updated on June 04, 2022

Comments

  • user3382714
    user3382714 almost 2 years

    My credentials work perfectly with Robomongo but I can't make the connection with node.js
    I have tried to make the connection using ssh2 and tunnel-ssh npm module and failed both times.
    -The mongo connection does not require a password
    -The ssh connection is made with a pem key

    This is the code I've used with ssh2 module, I can establish the tunneling correctly but the mongo connection fails

    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
    });
    

    And the code the 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);
            });
    
        });
    });
    

    I'm not sure whether to use the regular MongoDB connection string after establishing the tunnel or referring to the database as localhost such as
    mongodb://localhost:portnumber.
    or
    mongodb://databasepath.subpath.mongodbdns.com:27000

    Localhost gives me a permission denied error, the latter gives me a timeout