mirror of
https://github.com/vale981/autossh
synced 2025-03-04 17:01:41 -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 => {
|
||||
console.error('ERROR: ', err);
|
||||
})
|
||||
.on('init', () => {
|
||||
console.log('connected. Ready to do other stuff.');
|
||||
.on('connect', connection => {
|
||||
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
|
||||
```
|
||||
|
||||
#### 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`.
|
||||
|
||||
**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
|
||||
const myAutossh = autossh({
|
||||
|
@ -50,12 +61,24 @@ const myAutossh = autossh({
|
|||
localPort: 64444,
|
||||
remotePort: 5432
|
||||
})
|
||||
.on('error', err => {
|
||||
console.error('ERROR: ', err);
|
||||
})
|
||||
.on('init', () => {
|
||||
console.log('connected. Ready to do other stuff.');
|
||||
.on('connect', connection => {
|
||||
console.log('connected: ', connection);
|
||||
});
|
||||
|
||||
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';
|
||||
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({
|
||||
host: '104.131.150.215',
|
||||
username: 'same',
|
||||
localPort: 60001,
|
||||
remotePort: 5432
|
||||
})
|
||||
.on('error', err => {
|
||||
console.error('ERROR: ', err);
|
||||
})
|
||||
.on('init', connection => {
|
||||
console.log('connected.');
|
||||
});
|
||||
/* Possible output example (localPort results are be random)
|
||||
|
||||
**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.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 () {
|
||||
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');
|
||||
|
||||
_this.execTunnel();
|
||||
_this.emit('init', { kill: _this.kill, pid: _this.currentProcess.pid, currentProcess: _this.currentProcess });
|
||||
_portfinder2.default.getPort({
|
||||
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 () {
|
||||
|
@ -58,6 +70,13 @@ var AutoSSH = function (_EventEmitter) {
|
|||
}
|
||||
|
||||
_createClass(AutoSSH, [{
|
||||
key: 'generateRandomPort',
|
||||
value: function generateRandomPort() {
|
||||
var minPort = 3000;
|
||||
var maxPort = 65535;
|
||||
return Math.floor(Math.random() * (maxPort - minPort + 1)) + minPort;
|
||||
}
|
||||
}, {
|
||||
key: 'execTunnel',
|
||||
value: function execTunnel() {
|
||||
var _this2 = this;
|
||||
|
@ -66,7 +85,7 @@ var AutoSSH = function (_EventEmitter) {
|
|||
var userAtHost = this.username + '@' + this.host;
|
||||
var exitOnFailure = '-o "ExitOnForwardFailure yes"';
|
||||
var execString = 'ssh -NL ' + bindAddress + ' ' + exitOnFailure + ' ' + userAtHost;
|
||||
console.log('execString: ', execString);
|
||||
|
||||
this.currentProcess = (0, _child_process.exec)(execString, function (err, stdout, stderr) {
|
||||
if (/Address already in use/i.test(stderr)) {
|
||||
_this2.kill();
|
||||
|
|
35
src/index.js
35
src/index.js
|
@ -13,48 +13,55 @@ class AutoSSH extends EventEmitter {
|
|||
this.remotePort = conf.remotePort;
|
||||
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)
|
||||
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');
|
||||
|
||||
this.localPort = freePort;
|
||||
|
||||
this.execTunnel();
|
||||
|
||||
this.emit('init', {
|
||||
this.emit('connect', {
|
||||
kill: this.kill,
|
||||
pid: this.currentProcess.pid,
|
||||
host: this.host,
|
||||
username: this.username,
|
||||
remotePort: this.remotePort,
|
||||
localPort: this.localPort,
|
||||
localPort: this.localPort
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
process.on('exit', () => {
|
||||
this.kill();
|
||||
});
|
||||
}
|
||||
|
||||
generateRandomPort() {
|
||||
const minPort = 3000;
|
||||
const maxPort = 65535;
|
||||
return Math.floor(Math.random() * (maxPort - minPort + 1)) + minPort;
|
||||
}
|
||||
execTunnel() {
|
||||
const bindAddress = `${this.localPort}:localhost:${this.remotePort}`;
|
||||
const userAtHost = `${this.username}@${this.host}`;
|
||||
const exitOnFailure = '-o "ExitOnForwardFailure yes"'
|
||||
const execString = `ssh -NL ${bindAddress} ${exitOnFailure} ${userAtHost}`;
|
||||
console.log('execString: ', execString);
|
||||
|
||||
this.currentProcess = exec(execString, (err, stdout, stderr) => {
|
||||
if (/Address already in use/i.test(stderr)) {
|
||||
this.kill();
|
||||
|
|
Loading…
Add table
Reference in a new issue