mirror of
https://github.com/vale981/autossh
synced 2025-03-05 09:21:40 -05:00
adds auto port generation
This commit is contained in:
parent
37624b4b1a
commit
0bfb740253
4 changed files with 130 additions and 46 deletions
41
README.md
41
README.md
|
@ -26,8 +26,9 @@ autossh({
|
||||||
.on('error', err => {
|
.on('error', err => {
|
||||||
console.error('ERROR: ', err);
|
console.error('ERROR: ', err);
|
||||||
})
|
})
|
||||||
.on('init', () => {
|
.on('connect', connection => {
|
||||||
console.log('connected. Ready to do other stuff.');
|
console.log('connected. Tunnel established on port ' + connection.localPort);
|
||||||
|
console.log('pid: ' + connection.pid);
|
||||||
});
|
});
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -37,11 +38,21 @@ autossh({
|
||||||
ssh -NL 64444:localhost:5432 root@111.22.333.444
|
ssh -NL 64444:localhost:5432 root@111.22.333.444
|
||||||
```
|
```
|
||||||
|
|
||||||
#### To Kill
|
#### Generate Dynamic Local Port
|
||||||
|
|
||||||
|
If you want to dynamically/randomly generate a port number, provide a string `auto` for the `localPort`.
|
||||||
|
|
||||||
|
Port conflicts will automatically be avoided and the generated port will not be in use.
|
||||||
|
|
||||||
|
See `demo.js` for ean example.
|
||||||
|
|
||||||
|
#### Killing the Autossh Process
|
||||||
|
|
||||||
The autossh process will automatically die if the node process is closed, but you can manually kill the process using `kill`.
|
The autossh process will automatically die if the node process is closed, but you can manually kill the process using `kill`.
|
||||||
|
|
||||||
**Example**
|
If you try to kill the ssh process from the command line while the node process is active, a new ssh tunnel will be established (which is the point of autossh). You will need to kill the node process first or call the `kill` method on the instance.
|
||||||
|
|
||||||
|
**Example 1**
|
||||||
|
|
||||||
``` javascript
|
``` javascript
|
||||||
const myAutossh = autossh({
|
const myAutossh = autossh({
|
||||||
|
@ -50,12 +61,24 @@ const myAutossh = autossh({
|
||||||
localPort: 64444,
|
localPort: 64444,
|
||||||
remotePort: 5432
|
remotePort: 5432
|
||||||
})
|
})
|
||||||
.on('error', err => {
|
.on('connect', connection => {
|
||||||
console.error('ERROR: ', err);
|
console.log('connected: ', connection);
|
||||||
})
|
|
||||||
.on('init', () => {
|
|
||||||
console.log('connected. Ready to do other stuff.');
|
|
||||||
});
|
});
|
||||||
|
|
||||||
myAutossh.kill();
|
myAutossh.kill();
|
||||||
```
|
```
|
||||||
|
|
||||||
|
**Example 2**
|
||||||
|
|
||||||
|
``` javascript
|
||||||
|
const myAutossh = autossh({
|
||||||
|
host: '111.22.333.444',
|
||||||
|
username: 'root',
|
||||||
|
localPort: 64444,
|
||||||
|
remotePort: 5432
|
||||||
|
})
|
||||||
|
.on('connect', connection => {
|
||||||
|
console.log('connected: ', connection);
|
||||||
|
connection.kill();
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
59
demo.js
59
demo.js
|
@ -1,17 +1,52 @@
|
||||||
'use strict';
|
'use strict';
|
||||||
const autossh = require('./index.js');
|
const autossh = require('./index.js');
|
||||||
|
|
||||||
|
// open 10 ssh tunnels
|
||||||
|
for (let i = 0; i < 5; i++) {
|
||||||
|
// set up config
|
||||||
|
autossh({
|
||||||
|
host: '104.131.150.215', // enter host address
|
||||||
|
username: 'same', // enter username
|
||||||
|
localPort: 'auto', // 'auto' or port number
|
||||||
|
remotePort: 5432
|
||||||
|
})
|
||||||
|
// listen for errors
|
||||||
|
.on('error', err => {
|
||||||
|
console.error('ERROR: ', err);
|
||||||
|
})
|
||||||
|
// listen for connection
|
||||||
|
.on('connect', connection => {
|
||||||
|
console.log('\n**connected**');
|
||||||
|
console.log('localPort: \t' + connection.localPort);
|
||||||
|
console.log('pid: \t\t' + connection.pid);
|
||||||
|
console.log(`tunnel established from localhost:${connection.localPort} to ${connection.host}:${connection.remotePort} as ${connection.username}`);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
autossh({
|
/* Possible output example (localPort results are be random)
|
||||||
host: '104.131.150.215',
|
|
||||||
username: 'same',
|
|
||||||
localPort: 60001,
|
|
||||||
remotePort: 5432
|
|
||||||
})
|
|
||||||
.on('error', err => {
|
|
||||||
console.error('ERROR: ', err);
|
|
||||||
})
|
|
||||||
.on('init', connection => {
|
|
||||||
console.log('connected.');
|
|
||||||
});
|
|
||||||
|
|
||||||
|
**connected**
|
||||||
|
localPort: 39570
|
||||||
|
pid: 7477
|
||||||
|
tunnel established from localhost:39570 to xyz.xy.xyz.yz:5432 as same
|
||||||
|
|
||||||
|
**connected**
|
||||||
|
localPort: 53139
|
||||||
|
pid: 7478
|
||||||
|
tunnel established from localhost:53139 to xyz.xy.xyz.yz:5432 as same
|
||||||
|
|
||||||
|
**connected**
|
||||||
|
localPort: 56421
|
||||||
|
pid: 7479
|
||||||
|
tunnel established from localhost:56421 to xyz.xy.xyz.yz:5432 as same
|
||||||
|
|
||||||
|
**connected**
|
||||||
|
localPort: 5360
|
||||||
|
pid: 7480
|
||||||
|
tunnel established from localhost:5360 to xyz.xy.xyz.yz:5432 as same
|
||||||
|
|
||||||
|
**connected**
|
||||||
|
localPort: 40321
|
||||||
|
pid: 7481
|
||||||
|
tunnel established from localhost:40321 to xyz.xy.xyz.yz:5432 as same
|
||||||
|
*/
|
||||||
|
|
41
index.js
41
index.js
|
@ -36,19 +36,31 @@ var AutoSSH = function (_EventEmitter) {
|
||||||
_this.remotePort = conf.remotePort;
|
_this.remotePort = conf.remotePort;
|
||||||
_this.localPort = conf.localPort;
|
_this.localPort = conf.localPort;
|
||||||
|
|
||||||
_portfinder2.default.basePort = _this.localPort;
|
|
||||||
_portfinder2.default.getPort({ port: _this.localPort }, function (err, result) {
|
|
||||||
console.log('Error: ', err);
|
|
||||||
console.log('result: ', result);
|
|
||||||
});
|
|
||||||
setImmediate(function () {
|
setImmediate(function () {
|
||||||
if (!conf.host) return _this.emit('error', 'Missing host');
|
|
||||||
if (!conf.username) return _this.emit('error', 'Missing username');
|
|
||||||
if (!conf.remotePort) return _this.emit('error', 'Missing remotePort');
|
|
||||||
if (!conf.localPort) return _this.emit('error', 'Missing localPort');
|
if (!conf.localPort) return _this.emit('error', 'Missing localPort');
|
||||||
|
|
||||||
_this.execTunnel();
|
_portfinder2.default.getPort({
|
||||||
_this.emit('init', { kill: _this.kill, pid: _this.currentProcess.pid, currentProcess: _this.currentProcess });
|
port: _this.localPort === 'auto' ? _this.generateRandomPort() : _this.localPort
|
||||||
|
}, function (err, freePort) {
|
||||||
|
if (err) return _this.emit('error', 'Port error: ' + err);
|
||||||
|
if (_this.localPort !== 'auto' && _this.localPort !== freePort) return _this.emit('error', 'Port ' + _this.localPort + ' is not available');
|
||||||
|
if (!conf.host) return _this.emit('error', 'Missing host');
|
||||||
|
if (!conf.username) return _this.emit('error', 'Missing username');
|
||||||
|
if (!conf.remotePort) return _this.emit('error', 'Missing remotePort');
|
||||||
|
|
||||||
|
_this.localPort = freePort;
|
||||||
|
|
||||||
|
_this.execTunnel();
|
||||||
|
|
||||||
|
_this.emit('connect', {
|
||||||
|
kill: _this.kill,
|
||||||
|
pid: _this.currentProcess.pid,
|
||||||
|
host: _this.host,
|
||||||
|
username: _this.username,
|
||||||
|
remotePort: _this.remotePort,
|
||||||
|
localPort: _this.localPort
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
process.on('exit', function () {
|
process.on('exit', function () {
|
||||||
|
@ -58,6 +70,13 @@ var AutoSSH = function (_EventEmitter) {
|
||||||
}
|
}
|
||||||
|
|
||||||
_createClass(AutoSSH, [{
|
_createClass(AutoSSH, [{
|
||||||
|
key: 'generateRandomPort',
|
||||||
|
value: function generateRandomPort() {
|
||||||
|
var minPort = 3000;
|
||||||
|
var maxPort = 65535;
|
||||||
|
return Math.floor(Math.random() * (maxPort - minPort + 1)) + minPort;
|
||||||
|
}
|
||||||
|
}, {
|
||||||
key: 'execTunnel',
|
key: 'execTunnel',
|
||||||
value: function execTunnel() {
|
value: function execTunnel() {
|
||||||
var _this2 = this;
|
var _this2 = this;
|
||||||
|
@ -66,7 +85,7 @@ var AutoSSH = function (_EventEmitter) {
|
||||||
var userAtHost = this.username + '@' + this.host;
|
var userAtHost = this.username + '@' + this.host;
|
||||||
var exitOnFailure = '-o "ExitOnForwardFailure yes"';
|
var exitOnFailure = '-o "ExitOnForwardFailure yes"';
|
||||||
var execString = 'ssh -NL ' + bindAddress + ' ' + exitOnFailure + ' ' + userAtHost;
|
var execString = 'ssh -NL ' + bindAddress + ' ' + exitOnFailure + ' ' + userAtHost;
|
||||||
console.log('execString: ', execString);
|
|
||||||
this.currentProcess = (0, _child_process.exec)(execString, function (err, stdout, stderr) {
|
this.currentProcess = (0, _child_process.exec)(execString, function (err, stdout, stderr) {
|
||||||
if (/Address already in use/i.test(stderr)) {
|
if (/Address already in use/i.test(stderr)) {
|
||||||
_this2.kill();
|
_this2.kill();
|
||||||
|
|
35
src/index.js
35
src/index.js
|
@ -13,48 +13,55 @@ class AutoSSH extends EventEmitter {
|
||||||
this.remotePort = conf.remotePort;
|
this.remotePort = conf.remotePort;
|
||||||
this.localPort = conf.localPort;
|
this.localPort = conf.localPort;
|
||||||
|
|
||||||
portfinder.getPort({port: this.localPort === 'auto' ? 8000 : this.localPort}, (err, freePort) => {
|
|
||||||
console.log('Error: ', err);
|
|
||||||
if (this.localPort !== 'auto' && this.localPort !== freePort) {
|
|
||||||
return console.error(`Port ${this.localPort} is not available`);
|
|
||||||
}
|
|
||||||
this.localPort = result;
|
|
||||||
|
|
||||||
setImmediate(() => {
|
setImmediate(() => {
|
||||||
|
if (!conf.localPort)
|
||||||
|
return this.emit('error', 'Missing localPort');
|
||||||
|
|
||||||
|
portfinder.getPort({
|
||||||
|
port: this.localPort === 'auto' ? this.generateRandomPort() : this.localPort
|
||||||
|
}, (err, freePort) => {
|
||||||
|
if (err)
|
||||||
|
return this.emit('error', 'Port error: ' + err);
|
||||||
|
if (this.localPort !== 'auto' && this.localPort !== freePort)
|
||||||
|
return this.emit('error', `Port ${this.localPort} is not available`);
|
||||||
if (!conf.host)
|
if (!conf.host)
|
||||||
return this.emit('error', 'Missing host');
|
return this.emit('error', 'Missing host');
|
||||||
if (!conf.username)
|
if (!conf.username)
|
||||||
return this.emit('error', 'Missing username');
|
return this.emit('error', 'Missing username');
|
||||||
if (!conf.remotePort)
|
if (!conf.remotePort)
|
||||||
return this.emit('error', 'Missing remotePort');
|
return this.emit('error', 'Missing remotePort');
|
||||||
if (!conf.localPort)
|
|
||||||
return this.emit('error', 'Missing localPort');
|
this.localPort = freePort;
|
||||||
|
|
||||||
this.execTunnel();
|
this.execTunnel();
|
||||||
|
|
||||||
this.emit('init', {
|
this.emit('connect', {
|
||||||
kill: this.kill,
|
kill: this.kill,
|
||||||
pid: this.currentProcess.pid,
|
pid: this.currentProcess.pid,
|
||||||
host: this.host,
|
host: this.host,
|
||||||
username: this.username,
|
username: this.username,
|
||||||
remotePort: this.remotePort,
|
remotePort: this.remotePort,
|
||||||
localPort: this.localPort,
|
localPort: this.localPort
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
process.on('exit', () => {
|
process.on('exit', () => {
|
||||||
this.kill();
|
this.kill();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
generateRandomPort() {
|
||||||
|
const minPort = 3000;
|
||||||
|
const maxPort = 65535;
|
||||||
|
return Math.floor(Math.random() * (maxPort - minPort + 1)) + minPort;
|
||||||
|
}
|
||||||
execTunnel() {
|
execTunnel() {
|
||||||
const bindAddress = `${this.localPort}:localhost:${this.remotePort}`;
|
const bindAddress = `${this.localPort}:localhost:${this.remotePort}`;
|
||||||
const userAtHost = `${this.username}@${this.host}`;
|
const userAtHost = `${this.username}@${this.host}`;
|
||||||
const exitOnFailure = '-o "ExitOnForwardFailure yes"'
|
const exitOnFailure = '-o "ExitOnForwardFailure yes"'
|
||||||
const execString = `ssh -NL ${bindAddress} ${exitOnFailure} ${userAtHost}`;
|
const execString = `ssh -NL ${bindAddress} ${exitOnFailure} ${userAtHost}`;
|
||||||
console.log('execString: ', execString);
|
|
||||||
this.currentProcess = exec(execString, (err, stdout, stderr) => {
|
this.currentProcess = exec(execString, (err, stdout, stderr) => {
|
||||||
if (/Address already in use/i.test(stderr)) {
|
if (/Address already in use/i.test(stderr)) {
|
||||||
this.kill();
|
this.kill();
|
||||||
|
|
Loading…
Add table
Reference in a new issue