14

I have two Mongo DBs. One for my dev environment, one for production as seen here from my Robomongo setup:

Two Mongo DBs

The production db is SSH tunneled to my Digital Ocean virtual server as seen here (specifics have been changed obviously). This setup works fine when connecting to/from my production website:

SSH Tunnel Settings

I am now working on a different/related project and need to connect my local machine to my production DB, so I assumed I'd need to use something like tunnel-ssh to get it done. I've followed this answer as an example, but I'm either getting Error: (SSH) Channel open failure: open failed OR it's connecting to my Dev db (when I use 27017 as my dstHost/dstPort/localPort). I must be thinking about this wrong or I'm being dumb with my configuration. I am admittedly a total Mongo/Mongoose novice, so both are equally possible. Any advice?

var fs = require("fs");
var mongoose = require('mongoose');
var tunnel = require('tunnel-ssh');

//===== db connection =====

var config = {
    username:'my.username',
    host:'my.ip.address',
    agent : process.env.SSH_AUTH_SOCK,
    privateKey:require('fs').readFileSync('/Users/myusername/.ssh/id_rsa'),
    port:22,
    dstHost:'mongodb://localhost:27000/mydbname',
    dstPort:27000,
    localHost:'127.0.0.1',
    password:'mypassword',
    localPort: 27000
};

var server = tunnel(config, function (error, server) {
    if(error){
        console.log("SSH connection error: " + error);
    }
    mongoose.connect('mongodb://localhost:27000/mydbname');

    var db = mongoose.connection;
    db.on('error', console.error.bind(console, 'DB connection error:'));
    db.once('open', function() {
        // we're connected!
        console.log("DB connection successful");
        // console.log(server);
    });
});

Thanks in advance!

Community
  • 1
  • 1
jeremytripp
  • 1,038
  • 1
  • 11
  • 25
  • Thanks! very useful! The only thing that I had to change is, in my case, the config must have "passphrase" instead of "password". – Emigus Aug 10 '19 at 01:09

3 Answers3

24

The final working config for future reference. Thanks to mscdex -- I simply needed to provide the correct dstPort and include it in my Mongo URI string (the 27017). So simple.

var config = {
    username:'myusername',
    host:'my.ip.address',
    agent : process.env.SSH_AUTH_SOCK,
    privateKey:require('fs').readFileSync('/Users/myusername/.ssh/id_rsa'),
    port:22,
    dstPort:27017,
    password:'mypassword'
};

var server = tunnel(config, function (error, server) {
    if(error){
        console.log("SSH connection error: " + error);
    }
    mongoose.connect('mongodb://localhost:27017/mydbname');

    var db = mongoose.connection;
    db.on('error', console.error.bind(console, 'DB connection error:'));
    db.once('open', function() {
        // we're connected!
        console.log("DB connection successful");
    });
});
halfer
  • 19,824
  • 17
  • 99
  • 186
jeremytripp
  • 1,038
  • 1
  • 11
  • 25
8

Or if you don't want to change your code, provided that you have your ssh public key on the tunnel server, you can create a tunnel via ssh on the terminal:

ssh -fNL <local_port>:<mongodb_server_hostname_or_ip>:<mongodb_server_port> <tunnel_server_user>@<tunnel_server_hostname_or_ip>

Example with made-up IPs connecting to a fake AWS EC2 AMI Linux

ssh -fNL 27000:101.202.10.20:27000 ec2-user@33.44.55.66

Now this mongoose.connect('mongodb://localhost:27000/mydbname'); works like a charm. ;)

tiomno
  • 2,178
  • 26
  • 31
  • 2
    Best answer IMO ! – Titou Mar 15 '21 at 14:45
  • May I ask you how to connect through ssh tunnel with the user name password of MongoDB? @Titou – Hai Alison Dec 15 '22 at 03:46
  • 1
    @HaiAlison You do not use mongoDB username/pwd to connect through ssh. You pass the username/pwd as parameters of the mongodb connexion query through an established tunnel. – Titou Dec 16 '22 at 07:51
  • thank you @Titou, I've been fixing my problem with config mongo.conf file added IP address server to bindIp, and it worked. – Hai Alison Dec 16 '22 at 16:25
  • I am trying this solution with mongo atlas srv string but it is showing srv string do not need port and if I am trying it without srv it is showing no address associated with hostname, can you help please. https://stackoverflow.com/questions/75434045/connecting-to-mongo-srv-string-using-mongoose-nestjs-with-ssh-tunneling – Raghu Chahar Feb 13 '23 at 16:51
  • @RaghuChahar, I saw you already fix your issue. Interesting tool; thanks for sharing. – tiomno Feb 15 '23 at 01:04
7

dstHost needs to be a hostname/IP, not a MongoDB connection string. In this particular case, you can actually omit dstHost, localHost, and localPort in this particular case because they already default to the values you're providing.

mscdex
  • 104,356
  • 15
  • 192
  • 153
  • Well, progress at least. Commenting out those three, now I get `Error: (SSH) Channel open failure: Connection refused`. Mean anything to you? Off I go to the Google machine... – jeremytripp Dec 01 '16 at 07:52
  • 1
    You're not using the same port as you show in your screenshot. So try changing it accordingly to match that instead. You'll also need to change the port in your connection string as well. – mscdex Dec 01 '16 at 08:06
  • That's the ticket. Painfully obvious and fixed in 5 seconds after reading your comment this morning. Thanks so much! – jeremytripp Dec 01 '16 at 13:10