147 lines
3.4 KiB
JavaScript
Executable File
147 lines
3.4 KiB
JavaScript
Executable File
'use strict';
|
|
|
|
var pkg = require('../package.json');
|
|
var remote;
|
|
var local;
|
|
var isPiped = !process.stdin.isTTY;
|
|
var localAddress;
|
|
var localPort;
|
|
var rejectUnauthorized;
|
|
var servername;
|
|
var sshProxy;
|
|
|
|
function usage() {
|
|
console.info("");
|
|
console.info("sclient.js v" + pkg.version);
|
|
console.info("Usage: sclient [--servername <string>] [-k | --insecure] <servername:port> <port>");
|
|
console.info(" ex: sclient whatever.com 3000");
|
|
console.info(" (whatever.com:443 localhost:3000)");
|
|
console.info(" ex: sclient whatever.com:4080 0.0.0.0:3000");
|
|
console.info("");
|
|
}
|
|
|
|
function parseFlags() {
|
|
process.argv.some(function (arg, i) {
|
|
if (/^-k|--?insecure$/.test(arg)) {
|
|
rejectUnauthorized = false;
|
|
process.argv.splice(i, 1);
|
|
return true;
|
|
}
|
|
});
|
|
process.argv.some(function (arg, i) {
|
|
if (/^--?servername$/.test(arg)) {
|
|
servername = process.argv[i + 1];
|
|
if (!servername || /^-/.test(servername)) {
|
|
usage();
|
|
process.exit(2);
|
|
}
|
|
process.argv.splice(i, 2);
|
|
return true;
|
|
}
|
|
});
|
|
process.argv.some(function (arg, i) {
|
|
if (/^--?ssh$/.test(arg)) {
|
|
sshProxy = true;
|
|
process.argv.splice(i, 1);
|
|
process.argv[3] = '$';
|
|
return true;
|
|
}
|
|
});
|
|
}
|
|
|
|
parseFlags();
|
|
|
|
remote = (process.argv[2]||'').split(':');
|
|
local = (process.argv[3]||'').split(':');
|
|
|
|
if ('ssh' === remote[0]) {
|
|
sshProxy = true;
|
|
remote = local;
|
|
local = ['$'];
|
|
} else if ('ssh' === local[0]) {
|
|
sshProxy = true;
|
|
local[0] = '$';
|
|
}
|
|
|
|
// arg 0 is node
|
|
// arg 1 is sclient
|
|
// arg 2 is remote
|
|
// arg 3 is local
|
|
if (4 !== process.argv.length) {
|
|
if (isPiped) {
|
|
local = ['|'];
|
|
} else {
|
|
usage();
|
|
process.exit(1);
|
|
}
|
|
}
|
|
|
|
// Check for the first argument (what to connect to)
|
|
if (!remote[0]) {
|
|
usage();
|
|
return;
|
|
}
|
|
|
|
if (!local[0]) {
|
|
usage();
|
|
return;
|
|
}
|
|
if (local[0] === String(parseInt(local[0], 10))) {
|
|
localPort = parseInt(local[0], 10);
|
|
localAddress = 'localhost';
|
|
} else {
|
|
localAddress = local[0]; // potentially '-' or '|' or '$'
|
|
localPort = parseInt(local[1], 10);
|
|
}
|
|
|
|
var rparts = remote[0].split('@');
|
|
var username = rparts[1] ? (rparts[0] + '@') : '';
|
|
var opts = {
|
|
remoteAddr: rparts[1] || rparts[0]
|
|
, remotePort: remote[1] || 443
|
|
, localAddress: localAddress
|
|
, localPort: localPort
|
|
, rejectUnauthorized: rejectUnauthorized
|
|
, servername: servername
|
|
, stdin: null
|
|
, stdout: null
|
|
};
|
|
|
|
if ('-' === localAddress || '|' === localAddress) {
|
|
opts.stdin = process.stdin;
|
|
opts.stdout = process.stdout;
|
|
// no need for port
|
|
} else if ('$' === localAddress) {
|
|
sshProxy = true;
|
|
opts.localAddress = 'localhost';
|
|
opts.localPort = 0; // choose at random
|
|
} else if (!localPort) {
|
|
usage();
|
|
return;
|
|
}
|
|
|
|
var emitter = require('../')(opts);
|
|
emitter.once('listening', function (opts) {
|
|
var port = opts.localPort;
|
|
console.info('[listening] ' + opts.remoteAddr + ":" + opts.remotePort
|
|
+ " <= " + opts.localAddress + ":" + opts.localPort);
|
|
|
|
if (sshProxy) {
|
|
// TODO choose at random and connect to ssh after test
|
|
var spawn = require('child_process').spawn;
|
|
var ssh = spawn('ssh', [
|
|
username + 'localhost'
|
|
, '-p', port
|
|
// we're _inverse_ proxying ssh, so we must alias the serveranem and ignore the IP
|
|
, '-o', 'HostKeyAlias=' + opts.remoteAddr
|
|
, '-o', 'CheckHostIP=no'
|
|
], { stdio: 'inherit' });
|
|
ssh.on('exit', function () {
|
|
console.info('shutting down...');
|
|
});
|
|
ssh.on('close', function () {
|
|
opts.server.close();
|
|
});
|
|
}
|
|
});
|