UNPKG

2.94 kBJavaScriptView Raw
1var net = require('net');
2var debug = require('debug')('tunnel-ssh');
3var Connection = require('ssh2');
4var createConfig = require('./lib/config');
5var events = require('events');
6var noop = function () {
7};
8
9function bindSSHConnection(config, netConnection) {
10 var sshConnection = new Connection();
11
12 sshConnection.on('ready', function () {
13 debug('sshConnection:ready');
14 netConnection.emit('sshConnection', sshConnection, netConnection);
15 sshConnection.forwardOut(config.srcHost, config.srcPort, config.dstHost, config.dstPort, function (err, sshStream) {
16 if (err) {
17 // Bubble up the error => netConnection => server
18 netConnection.emit('error', err);
19 debug('Destination port:', err);
20 return;
21 }
22
23 debug('sshStream:create');
24 netConnection.emit('sshStream', sshStream);
25 netConnection.pipe(sshStream).pipe(netConnection);
26 });
27 });
28 return sshConnection;
29}
30
31function createServer(config) {
32 var server;
33 var sshConnection;
34 var connections = [];
35 var connectionCount = 0;
36
37 server = net.createServer(function (netConnection) {
38 connectionCount++;
39 netConnection.on('error', server.emit.bind(server, 'error'));
40 netConnection.on('close', function () {
41 connectionCount--;
42 if (connectionCount === 0) {
43 if (!config.keepAlive) {
44 setTimeout(function () {
45 if (connectionCount === 0) {
46 server.close();
47 }
48 }, 2);
49 }
50 }
51 });
52
53 server.emit('netConnection', netConnection, server);
54 sshConnection = bindSSHConnection(config, netConnection);
55 sshConnection.on('error', server.emit.bind(server, 'error'));
56
57 netConnection.on('sshStream', function (sshStream) {
58 sshStream.on('error', function () {
59 server.close();
60 });
61 });
62
63 connections.push(sshConnection, netConnection);
64 debug('sshConfig', config);
65 sshConnection.connect(config);
66 });
67
68 server.on('close', function () {
69 connections.forEach(function (connection) {
70 connection.end();
71 });
72 });
73
74 return server;
75}
76
77function tunnel(configArgs, callback) {
78 var server;
79 var config;
80
81 if (!callback) {
82 callback = noop;
83 }
84 try {
85 config = createConfig(configArgs);
86 server = createServer(config);
87
88 server.listen(config.localPort, config.localHost, function (error) {
89 callback(error, server);
90 });
91 } catch (e) {
92 server = new events.EventEmitter();
93 setImmediate(function () {
94 callback(e);
95 server.emit('error', e);
96 });
97 }
98 return server;
99}
100
101module.exports = tunnel;