Skip to content

Instantly share code, notes, and snippets.

@norbornen
Created October 14, 2020 12:31
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save norbornen/d36c2657356a192764866703a2ebd361 to your computer and use it in GitHub Desktop.
Save norbornen/d36c2657356a192764866703a2ebd361 to your computer and use it in GitHub Desktop.
Node.js postgresql connecting with ssh-tunnel proxy
const fs = require('fs');
const os = require('os');
const tunnelSsh = require('tunnel-ssh');
const { Pool } = require('pg');
(async () => {
/** @type {import('net').Server} */
let tunnel;
try {
tunnel = await createTunnel();
} catch (err) {
console.error(err);
return;
}
try {
const db = connectPg();
const { rows } = await db.query('select now()');
console.log(rows); // [ { now: 2020-10-13T22:08:50.496Z } ]
} catch (err) {
console.error(err);
} finally {
tunnel.close();
}
})();
/**
* @param {number} [localPort=63334]
* @returns {Promise<import('net').Server>}
*/
async function createTunnel(localPort = 63334) {
/** @type {import('tunnel-ssh').Config} */
const tunnelConfig = {
username: 'имя пользователя на удалённом сервере',
password: 'пароль пользователя на удалённом сервере',
// в случае если настроен доступ по ключу
// privateKey: fs.readFileSync(`${os.homedir()}/.ssh/id_rsa`),
host: 'адрес удалённого сервера',
port: 22, // порт для ssh-соединения
dstPort: 5432, // порт postgres на удалённом сервере
localPort: localPort, // порт postgres на локальной машине
keepAlive: true,
readyTimeout: 10000,
};
return new Promise((resolve, reject) => {
tunnelSsh(tunnelConfig, (err, server) => {
if (err) {
return reject(err);
}
resolve(server);
})
.on('error', (err) => console.error('[tunnel-ssh] error:', err))
.on('connection', () => console.log('[tunnel-ssh] connected'))
.on('close', () => console.log('[tunnel-ssh] closed'));
});
}
/**
* @param {number} [localPort=63334]
* @returns {import('pg').Pool}
*/
function connectPg(localPort = 63334) {
/** @type {import('pg').ConnectionConfig} */
const connectionConfig = {
database: 'db_name',
port: localPort, // порт, куда туннель проксирует postgres
user: 'db_user_name',
password: 'db_user_password'
};
return new Pool(connectionConfig);
}
@norbornen
Copy link
Author

associated ru.so question

@ramki-pvrs
Copy link

ramki-pvrs commented Apr 10, 2023

Hi Norbornen,
I am trying to use the code you have given, I am getting error TypeError: tunnelSsh is not a function, I could not fix it, can you please suggest what could be the issue. My Node version is v18.12.1 and npm version is 8.19.2..

Thank you

with warm regards
ramki

@jexroid
Copy link

jexroid commented Jul 27, 2023

i have the exact same error : i even used this code but still same :

const tunnel = require('tunnel-ssh');


        var server = tunnel.tunnel(config, function (error, server) {
            if (error) {
                console.log("SSH connection error: " + error);
            } else {
                console.log('SSH tunnel created successfully');
            }
            
        })```

@norbornen
Copy link
Author

norbornen commented Aug 31, 2023

For tunnel-ssh v5:

async function run() {
  const localPort = 63334;
  const [server, client] = await createTunnel(
    { autoClose: false },
    { port: localPort },
    {
      host: ...,
      port: 22,
      username: ...,
      password: ...,
      keepaliveInterval: 1000,
      readyTimeout: 10000,
    },
    { dstPort: 5432 }
  );

  const db = new Pool({
    database: ...,
    port: localPort,
    user: ...,
  });

  const { rows } = await db.query('select now()');
  console.log(rows);
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment