Node.js tunneling to MongoDB Atlas replica set via bastion host

Hi all,

I’m trying to connect to an Atlas cluster via tunneling through a bastion host (since I’m executing code from Pipedream which launches from a non-static set of IPs so I can’t know which to whitelist unless I use my own bastion server).

Using node.js packages, I’m running this code below wrapped in an async function, but it seems to not be able to connect to the MongoDB Atlas cluster through the tunnel. I’ve verified that the tunnel actually works for various other purposes. I’m using the ssh package “ssh2-promise”, and have also tried “tunnel-ssh”. If I don’t use tunneling and just connect the driver straight to the cluster via the +SRV name or the explicit standard connection string, it’ll work (with 0.0.0.0/0 access allowed, of course). But I really want to get this tunnel working. What am I doing wrong here?

const SSH2Promise = require('ssh2-promise');
const MongoClient = require('mongodb').MongoClient

const database = "<database name>";
const mongoUsername = auths.mongodb.username;
const mongoPassword = auths.mongodb.password;

const { 
  host, 
  port,
  username, 
  privateKey,
} = auths.ssh

const ssh = new SSH2Promise({
  host,
  username,
  privateKey,
})

const tunnel1 = await ssh.addTunnel({
  remoteAddr: "<shard00>.55gfk.mongodb.net", 
  remotePort: 27017,
  localHost: "127.0.0.1"
})

const tunnel2 = await ssh.addTunnel({
  remoteAddr: "<shard01>.55gfk.mongodb.net", 
  remotePort: 27017,
  localHost: "127.0.0.1"
})

const tunnel3 = await ssh.addTunnel({
  remoteAddr: "<shard02>.55gfk.mongodb.net", 
  remotePort: 27017,
  localHost: "127.0.0.1"
})

console.log("tunnel established");

const url = `mongodb://${mongoUsername}:${mongoPassword}@${tunnel1.localHost}:${tunnel1.localPort},${tunnel2.localHost}:${tunnel2.localPort},${tunnel3.localHost}:${tunnel3.localPort}/${database}?ssl=true&replicaSet=atlas-<cluster>-shard-0&authSource=admin&retryWrites=true&w=majority`

console.log(url)

const client = await MongoClient.connect(url, { 
  useNewUrlParser: true, 
  useUnifiedTopology: true 
});

console.log("db connection established");

client.close();
ssh.close();
1 Like

Hi! Did you find a solution?

Nope. I’ve resigned to just making really secure credentials and allowing 0.0.0.0/0 for now until Pipedream can NAT out its compute somehow to a static IP.

@Nghia_Nguyen looking at the ssh2promise docs, addTunnel() accepts localPort not localHost for configuration. tunnelX.localHost returns undefined when I try it. It could be that you are using an older version of the package that did support that. So maybe the connection string is incorrect? The connection string should be:

const url = `mongodb://${mongoUsername}:${mongoPassword}@localhost:${tunnel1.localPort},localhost:${tunnel2.localPort},localhost:${tunnel3.localPort}/${database}?ssl=true&replicaSet=atlas-<cluster>-shard-0&authSource=admin&retryWrites=true&w=majority`

Did that solve it, @Nghia_Nguyen ?

I’m pretty sure I made sure to check the local host and local port resolved to values when I tried this a while back. Never got it to work–but you should take a crack at it if you’re facing similar problems.