Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

How to use ssh2 with node-postgres #67

Closed
BrandonCopley opened this issue Jul 19, 2013 · 10 comments
Closed

How to use ssh2 with node-postgres #67

BrandonCopley opened this issue Jul 19, 2013 · 10 comments

Comments

@BrandonCopley
Copy link

I am trying to redirect my app traffic (10's of ip's) into only 1, I should be able to use a tunnel, but I'm noticing that if I try to ssh tunnel and then call pg, pg doesn't know how to handle this and requests are STILL coming from my local server.

@BrandonCopley
Copy link
Author

c.connect({
    host : '192.168.1.1',
    port : 22,
    username : 'ubuntu',
    privateKey : require('fs').readFileSync('./ssh_keys/my_key')
  });
  c.on('connect', function() {
    console.log('Connection :: connect');
  });
  c.on('ready', function() {
    console.log('Connection :: ready');
    var pg = require('pg');
    var conString = "postgres://user:password@host:5432/postgres";
    var client = new pg.Client(conString);
    client.connect(function(err) {

    });
  });

@mscdex
Copy link
Owner

mscdex commented Jul 19, 2013

The issue here is that when creating a remote outbound connection (forwardOut()), the TCP stream is passed to the callback.

So, the 'pg' module here needs to be able to accept a stream instead of connecting itself. Or you can create a TCP proxy server (for 'pg' to connect to) that on connection, will call fowardOut() and pipe to the incoming socket and back. The latter might look something like:

var pg = require('pg'),
    ssh2 = require('ssh2');
var pgHost = 'localhost', // remote hostname/ip
    pgPort = 5432,
    proxyPort = 9090,
    ready = false;

var proxy = require('net').createServer(function(sock) {
  if (!ready)
    return sock.destroy();
  c.forwardOut(sock.remoteAddress, sock.remotePort, pgHost, pgPort, function(err, stream) {
    if (err)
      return sock.destroy();
    sock.pipe(stream);
    stream.pipe(sock);
  });
});
proxy.listen(proxyPort, '127.0.0.1');

var c = new ssh2();
c.connect({
  host : '192.168.1.1',
  port : 22,
  username : 'ubuntu',
  privateKey : require('fs').readFileSync('./ssh_keys/my_key')
});
c.on('connect', function() {
  console.log('Connection :: connect');
});
c.on('ready', function() {
  ready = true;
  var conString = 'postgres://user:password@127.0.0.1:' + proxyPort + '/postgres',
      client = new pg.Client(conString);
  client.connect(function(err) {
    // ....
  });
});

@BrandonCopley
Copy link
Author

This worked perfectly. I set it up so I can have cycling ports and connect
to multiple databases, this looks great!

@alesak23
Copy link

alesak23 commented Oct 6, 2020

still works great in 2020!

@andreikho
Copy link

andreikho commented Feb 26, 2021

This just made my day, spent the last 24h banging the wall haha.
Still works great in 2021!

@salvadorplj
Copy link

If you need to work async you should defenitely look into using ssh2-promise instead.

All you'd need is something like this:

    let sshConnectionString = {
      host: '123.123.123.123', // bastionip,
      port: 22, // bastionport
      username: 'username', // bastionuser
      privateKey: key // bastionkey
    }

    // Create ssh connection and tunnel the target server through it
    var sshConn = new SSH2Promise(sshConnectionString);
    await sshConn.connect();
    await sshConn.addTunnel({remoteAddr: fqdn, remotePort: port}).then((tunnel) => {
      port = tunnel.localPort; //Local port 
      fqdn = '127.0.0.1';
    });
  }

@renschler
Copy link

thanks @mscdex ! this was a big help

@CaliforniaLuv
Copy link

In 2022, this code still works 😁
Thanks to you, I lived in my company.

@jamie-legg
Copy link

Still works in 2023. Thank you.

@amsanket22
Copy link

https://github.com/amsanket22/ssh-pg there is the repo you can use, just set up the env and ready to go

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

9 participants