index.js 2.9 KB

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