Compare commits
7 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 6e796da80a | |||
| 415ed10b99 | |||
| 6fdf889b0b | |||
| c345d9ec69 | |||
| 58cbe914c1 | |||
| 7add115e5f | |||
| d390df175a |
11
README.md
11
README.md
@ -33,7 +33,7 @@ $ curl http://localhost:3000 -H 'Host: whatever.com'
|
|||||||
Inverse SSH proxy (ssh over https):
|
Inverse SSH proxy (ssh over https):
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
$ sclient --ssh user@example.com
|
$ sclient ssh user@example.com
|
||||||
```
|
```
|
||||||
|
|
||||||
(this is the same as a normal SSH Proxy, just easier to type):
|
(this is the same as a normal SSH Proxy, just easier to type):
|
||||||
@ -42,6 +42,12 @@ $ sclient --ssh user@example.com
|
|||||||
$ ssh -o ProxyCommand="sclient %h" user@example.com
|
$ ssh -o ProxyCommand="sclient %h" user@example.com
|
||||||
```
|
```
|
||||||
|
|
||||||
|
Inverse rsync proxy (rsync over https):
|
||||||
|
|
||||||
|
```bash
|
||||||
|
$ sclient rsync user@example.com:path/ path/
|
||||||
|
```
|
||||||
|
|
||||||
A poor man's (or Windows user's) makeshift replacement for `openssl s_client`, `stunnel`, or `socat`.
|
A poor man's (or Windows user's) makeshift replacement for `openssl s_client`, `stunnel`, or `socat`.
|
||||||
|
|
||||||
Install
|
Install
|
||||||
@ -63,13 +69,12 @@ Usage
|
|||||||
=====
|
=====
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
sclient [flags] <remote> <local>
|
sclient [flags] [ssh|rsync] <remote> [local]
|
||||||
```
|
```
|
||||||
|
|
||||||
* flags
|
* flags
|
||||||
* `-k, --insecure` ignore invalid TLS (SSL/HTTPS) certificates
|
* `-k, --insecure` ignore invalid TLS (SSL/HTTPS) certificates
|
||||||
* `--servername <string>` spoof SNI (to disable use IP as <remote> and do not use this option)
|
* `--servername <string>` spoof SNI (to disable use IP as <remote> and do not use this option)
|
||||||
* `--ssh proxy` proxy ssh over https (_inverse_ ssh proxy, like stunnel)
|
|
||||||
* remote
|
* remote
|
||||||
* must have servername (i.e. example.com)
|
* must have servername (i.e. example.com)
|
||||||
* port is optional (default is 443)
|
* port is optional (default is 443)
|
||||||
|
|||||||
@ -1,3 +1,4 @@
|
|||||||
|
#!/usr/bin/env node
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
var pkg = require('../package.json');
|
var pkg = require('../package.json');
|
||||||
@ -21,19 +22,6 @@ function parseFlags(argv) {
|
|||||||
var args = argv.slice();
|
var args = argv.slice();
|
||||||
var flags = {};
|
var flags = {};
|
||||||
|
|
||||||
args.sort(function (a, b) {
|
|
||||||
if ('-' === a[0]) {
|
|
||||||
if ('-' === b[0]) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
if ('-' === b[0]) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
});
|
|
||||||
|
|
||||||
args.some(function (arg, i) {
|
args.some(function (arg, i) {
|
||||||
if (/^-k|--?insecure$/.test(arg)) {
|
if (/^-k|--?insecure$/.test(arg)) {
|
||||||
flags.rejectUnauthorized = false;
|
flags.rejectUnauthorized = false;
|
||||||
@ -70,6 +58,32 @@ function parseFlags(argv) {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
args.some(function (arg, i) {
|
||||||
|
if (/^--?socks5$/.test(arg)) {
|
||||||
|
flags.socks5 = args[i + 1];
|
||||||
|
if (!flags.socks5 || /^-/.test(flags.socks5)) {
|
||||||
|
usage();
|
||||||
|
process.exit(202);
|
||||||
|
}
|
||||||
|
args.splice(i, 2);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// This works for most (but not all)
|
||||||
|
// of the ssh and rsync flags - because they mostly don't have arguments
|
||||||
|
args.sort(function (a, b) {
|
||||||
|
if ('-' === a[0]) {
|
||||||
|
if ('-' === b[0]) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
if ('-' === b[0]) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
});
|
||||||
|
|
||||||
return {
|
return {
|
||||||
flags: flags
|
flags: flags
|
||||||
@ -109,6 +123,10 @@ function testRemote(opts) {
|
|||||||
var remote = args.shift() + ':' + opts.remotePath;
|
var remote = args.shift() + ':' + opts.remotePath;
|
||||||
args = [ remote, '-e', 'ssh ' + args.join(' ') ];
|
args = [ remote, '-e', 'ssh ' + args.join(' ') ];
|
||||||
}
|
}
|
||||||
|
if (opts.socks5) {
|
||||||
|
args.push('-D');
|
||||||
|
args.push('localhost:' + opts.socks5);
|
||||||
|
}
|
||||||
args = args.concat(opts.args);
|
args = args.concat(opts.args);
|
||||||
var child = spawn(opts.command, args, { stdio: 'inherit' });
|
var child = spawn(opts.command, args, { stdio: 'inherit' });
|
||||||
child.on('exit', function () {
|
child.on('exit', function () {
|
||||||
@ -139,7 +157,7 @@ function main() {
|
|||||||
// Re-arrange argument order for ssh
|
// Re-arrange argument order for ssh
|
||||||
if (cmd.flags.wrapSsh) {
|
if (cmd.flags.wrapSsh) {
|
||||||
cmd.args.splice(3, 0, 'ssh');
|
cmd.args.splice(3, 0, 'ssh');
|
||||||
} else if (-1 !== [ 'ssh', 'rsync' ].indexOf((cmd.args[2]||'').split(':')[0])) {
|
} else if (-1 !== [ 'ssh', 'rsync', 'vpn' ].indexOf((cmd.args[2]||'').split(':')[0])) {
|
||||||
cmd.flags.wrapSsh = true;
|
cmd.flags.wrapSsh = true;
|
||||||
binParam = cmd.args.splice(2, 1);
|
binParam = cmd.args.splice(2, 1);
|
||||||
cmd.args.splice(3, 0, binParam[0]);
|
cmd.args.splice(3, 0, binParam[0]);
|
||||||
@ -157,7 +175,7 @@ function main() {
|
|||||||
}
|
}
|
||||||
local = (cmd.args[3]||'').split(':');
|
local = (cmd.args[3]||'').split(':');
|
||||||
|
|
||||||
if (-1 !== [ 'ssh', 'rsync' ].indexOf(local[0])) {
|
if (-1 !== [ 'ssh', 'rsync', 'vpn' ].indexOf(local[0])) {
|
||||||
cmd.flags.wrapSsh = true;
|
cmd.flags.wrapSsh = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -212,16 +230,24 @@ function main() {
|
|||||||
opts.stdin = process.stdin;
|
opts.stdin = process.stdin;
|
||||||
opts.stdout = process.stdout;
|
opts.stdout = process.stdout;
|
||||||
// no need for port
|
// no need for port
|
||||||
} else if (-1 !== [ 'ssh', 'rsync' ].indexOf(localAddress)) {
|
} else if (-1 !== [ 'ssh', 'rsync', 'vpn' ].indexOf(localAddress)) {
|
||||||
cmd.flags.wrapSsh = true;
|
cmd.flags.wrapSsh = true;
|
||||||
opts.localAddress = 'localhost';
|
opts.localAddress = 'localhost';
|
||||||
opts.localPort = local[1] || 0; // choose at random
|
opts.localPort = local[1] || 0; // choose at random
|
||||||
opts.command = localAddress;
|
opts.command = localAddress;
|
||||||
opts.args = cmd.args.slice(4); // node, sclient, ssh, addr
|
opts.args = cmd.args.slice(4); // node, sclient, ssh, addr
|
||||||
|
opts.socks5 = cmd.flags.socks5;
|
||||||
if ('rsync' === opts.command) {
|
if ('rsync' === opts.command) {
|
||||||
opts.remotePath = opts.remotePort;
|
opts.remotePath = opts.remotePort;
|
||||||
opts.remotePort = 0;
|
opts.remotePort = 0;
|
||||||
}
|
}
|
||||||
|
if ('vpn' === opts.command) {
|
||||||
|
opts.command = 'ssh';
|
||||||
|
if (!opts.socks5) {
|
||||||
|
usage();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
if (!opts.remotePort) {
|
if (!opts.remotePort) {
|
||||||
opts.remotePort = cmd.flags.port || 443;
|
opts.remotePort = cmd.flags.port || 443;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "sclient",
|
"name": "sclient",
|
||||||
"version": "1.4.0",
|
"version": "1.4.3",
|
||||||
"description": "Secure Client for exposing TLS (aka SSL) secured services as plain-text connections locally. Also ideal for multiplexing a single port with multiple protocols using SNI.",
|
"description": "Secure Client for exposing TLS (aka SSL) secured services as plain-text connections locally. Also ideal for multiplexing a single port with multiple protocols using SNI.",
|
||||||
"main": "index.js",
|
"main": "index.js",
|
||||||
"homepage": "https://telebit.cloud/sclient/",
|
"homepage": "https://telebit.cloud/sclient/",
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user