question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Tunnel with forwardOut question.

See original GitHub issue

Hi,

First I wanted to say that I am loving this library. Fantastic work!!

I have a question because I have a server at a remote location that I would like to tunnel through to. I’m not sure that it’s that unusual and I’m pretty sure I must be missing something here. There is a firewall in between that uses a key on port 222. Anyway, the way I normally do it is with a command like:

ssh -L localhost:2221:[SERVER IP]:22 -p 222 [F/WALL UNAME]@[F/WALL IP]

Then I just ssh into it:

ssh -p 2221 [SERVER UNAME]@localhost

This is an example of what I’m trying to do.

var  fs = require('fs'),
     Connection = require('ssh2');

var c1 = new Connection();

c1.connect({
  host: '[F/WALL IP]', 
  port: 222, 
  username: '[F/WALL UNAME]', 
  privateKey: require('fs').readFileSync('./keys/sample.key') 
});

c1.on('ready', function(){
  c1.forwardOut('localhost', 2221, '[SERVER IP]', 22, function(err, stream) {

    if(err) throw err;
    console.log('ForwardOut Ready!');

    var c2 = new Connection();

    c2.connect({
      host: 'localhost', 
      port: 2221, 
      username: '[SERVER UNAME]', 
      password: '[SERVER PASSWORD]' 
    });

    c2.on('ready', function(){
      console.log('Connected!');
    });

    c2.on('error', function(err) {
      console.log('Connection :: error :: ' + err);
    });
  })
});

c1.on('error', function(err) {
  console.log('Connection :: error :: ' + err);
});

The ouput I get is:

ForwardOut Ready! Connection :: error :: Error: connect ECONNREFUSED

Is there anything glaring that you can see I’m missing?

Cheers, Paul

Issue Analytics

  • State:closed
  • Created 10 years ago
  • Comments:13 (5 by maintainers)

github_iconTop GitHub Comments

1reaction
jpilloracommented, Oct 3, 2017

Published ssh-http-agent:

const sshAgent = require("ssh-http-agent");
const http = require("http");

https.get(
  {
    host: "echo.jpillora.com",
    path: "/foo/bar",
    agent: sshAgent.http({
      host: "1.2.3.4",
      port: 22,
      username: "root",
      password: "supersecret"
    })
  },
  res => {
    console.log(res.headers);
  }
);

I thought Node’s http would call ref and unref though it doesn’t seem to…

1reaction
mscdexcommented, Sep 28, 2017

@jpillora and anyone else who may be interested:

Here’s an example HTTP/HTTPS Agent implementation that tunnels requests over SSH. It could be improved a bit (e.g. actual/proper ref()/unref() handling) and it might be possible to simplify it a bit because for example, I think node may retry requests that never received a socket, so we may not need to manually handle the 'ready' event handlers.

var HttpAgent = require('http').Agent;
var HttpsAgent = require('https').Agent;
var inherits = require('util').inherits;

var Client = require('ssh2').Client;

[HttpAgent, HttpsAgent].forEach(function(ctor) {
  function SSHAgent(connectCfg, agentOptions) {
    if (!(this instanceof SSHAgent))
      return new SSHAgent(connectCfg, agentOptions);

    ctor.call(this, agentOptions);

    createSSH(this, connectCfg);
    this._defaultSrcIP = (agentOptions && agentOptions.srcIP) || 'localhost';
  }
  inherits(SSHAgent, ctor);

  SSHAgent.prototype.createConnection = createConnection;

  exports[ctor === HttpAgent ? 'SSHTTPAgent' : 'SSHTTPSAgent'] = SSHAgent;
});

function createConnection(options, cb) {
  if (!this._ready) {
    const onReady = () => { this.createConnection(options, cb); };
    onReady.httpCb = cb;
    this._client.once('ready', onReady);
    return;
  }

  var srcIP = (options && options.localAddress) || this._defaultSrcIP;
  var srcPort = (options && options.localPort) || 0;
  var dstIP = options.host;
  var dstPort = options.port;

  this._client.forwardOut(srcIP, srcPort, dstIP, dstPort, (err, stream) => {
    if (err)
      return cb(err);
    cb(null, decorateStream(stream));
  });
}

function createSSH(agent, config) {
  agent._ready = false;
  agent._client = new Client();
  agent._client.on('ready', function() {
    agent._ready = true;
  }).on('error', function(err) {
    // Treat all errors has fatal, canceling pending http
    // requests
    const readies = this.listeners('ready');
    for (var i = 0; i < readies.length; ++i) {
      const fn = readies[i];
      if (typeof fn.httpCb === 'function')
        fn.httpCb(err);
    }
    this.removeAllListeners('ready');
  }).on('close', function() {
    createSSH(agent, config);

    // Re-add callbacks for http requests that were waiting
    // for an SSH connection
    const readies = this.listeners('ready');
    for (var i = 0; i < readies.length; ++i) {
      const fn = readies[i];
      if (typeof fn.httpCb === 'function')
        agent._client.once('ready', fn);
    }
  }).connect(config);
}

function decorateStream(stream) {
  stream.setKeepAlive = noop;
  stream.setNoDelay = noop;
  stream.setTimeout = noop;
  stream.ref = noop;
  stream.unref = noop;
  stream.destroySoon = stream.destroy;
  return stream;
}

function noop() {}

Then use like:

// Or use `SSHTTPSAgent` for HTTPS
const httpAgent = new SSHTTPAgent({
  host: '192.168.100.1',
  username: 'foo',
  agent: process.env.SSH_AUTH_SOCK
});

require('http').get({
  host: '192.168.200.1',
  agent: httpAgent
}, (res) => {
  console.log(res.statusCode);
  console.dir(res.headers);
  res.resume();
});
Read more comments on GitHub >

github_iconTop Results From Across the Web

how do I use npm module ssh2 to tunnel a port - Stack Overflow
I'm now trying to also tunnel a port over the same ssh connection but ... stream) => { // console.log( // "ssh forwardOut...
Read more >
SSH Tunneling: Client Command & Server Configuration
The problem is that port forwarding can in practice only be prevented by a server or firewall. An enterprise cannot control all servers...
Read more >
ASA NAT Question - Anyconnect full-tunnel to internal server via ...
As the title says, I need to access an internal server on the inside interface via it's public IP on the outside interface...
Read more >
How to problem solve Bi-directional Forwarding Detection (BFD)
Step 1: Detach the MPLS-VC interface attached to the configured virtual-switch · Step 2: Delete the static-virtual cirtuit. · Step 3: Delete the ......
Read more >
Understand GRE Tunnel Keepalives - Cisco
This mechanism causes the keepalive response to forward out the physical interface rather than the tunnel interface. This means that the GRE ...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found