v1.2.0: bring up to par with sclient.go; add --servername, allow pipes, use - for stdin
This commit is contained in:
		
							parent
							
								
									f14708495a
								
							
						
					
					
						commit
						1287ccc1ce
					
				
							
								
								
									
										33
									
								
								README.md
									
									
									
									
									
								
							
							
						
						
									
										33
									
								
								README.md
									
									
									
									
									
								
							| @ -51,9 +51,12 @@ Usage | |||||||
| ===== | ===== | ||||||
| 
 | 
 | ||||||
| ```bash | ```bash | ||||||
| sclient <remote> <local> [-k | --insecure] | sclient [flags] <remote> <local> | ||||||
| ``` | ``` | ||||||
| 
 | 
 | ||||||
|  | * flags | ||||||
|  |   * -k, --insecure ignore invalid TLS (SSL/HTTPS) certificates | ||||||
|  |   * --servername <string> spoof SNI (to disable use IP as <remote> and do not use this option) | ||||||
| * 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) | ||||||
| @ -79,5 +82,31 @@ sclient telebit.cloud:443 localhost:3000 | |||||||
| Ignore a bad TLS/SSL/HTTPS certificate and connect anyway. | Ignore a bad TLS/SSL/HTTPS certificate and connect anyway. | ||||||
| 
 | 
 | ||||||
| ```bash | ```bash | ||||||
| sclient badtls.telebit.cloud:443 localhost:3000 -k | sclient -k badtls.telebit.cloud:443 localhost:3000 | ||||||
|  | ``` | ||||||
|  | 
 | ||||||
|  | Reading from stdin | ||||||
|  | 
 | ||||||
|  | ```bash | ||||||
|  | sclient telebit.cloud:443 - | ||||||
|  | ``` | ||||||
|  | 
 | ||||||
|  | ```bash | ||||||
|  | sclient telebit.cloud:443 - </path/to/file | ||||||
|  | ``` | ||||||
|  | 
 | ||||||
|  | Piping | ||||||
|  | 
 | ||||||
|  | ```bash | ||||||
|  | printf "GET / HTTP/1.1\r\nHost: telebit.cloud\r\n\r\n" | sclient telebit.cloud:443 | ||||||
|  | ``` | ||||||
|  | 
 | ||||||
|  | Testing for security vulnerabilities on the remote: | ||||||
|  | 
 | ||||||
|  | ```bash | ||||||
|  | sclient --servername "Robert'); DROP TABLE Students;" -k example.com localhost:3000 | ||||||
|  | ``` | ||||||
|  | 
 | ||||||
|  | ```bash | ||||||
|  | sclient --servername "../../../.hidden/private.txt" -k example.com localhost:3000 | ||||||
| ``` | ``` | ||||||
|  | |||||||
| @ -1,30 +1,68 @@ | |||||||
| 'use strict'; | 'use strict'; | ||||||
| 
 | 
 | ||||||
| var pkg = require('../package.json'); | var pkg = require('../package.json'); | ||||||
| var remote = (process.argv[2]||'').split(':'); | var remote; | ||||||
| var local = (process.argv[3]||'').split(':'); | var local; | ||||||
|  | var isPiped = !process.stdin.isTTY; | ||||||
| var localAddress; | var localAddress; | ||||||
| var localPort; | var localPort; | ||||||
| var rejectUnauthorized; | var rejectUnauthorized; | ||||||
|  | var servername; | ||||||
| 
 | 
 | ||||||
| function usage() { | function usage() { | ||||||
|   console.info(""); |   console.info(""); | ||||||
|   console.info("sclient.js v" + pkg.version); |   console.info("sclient.js v" + pkg.version); | ||||||
|   console.info("Usage: sclient <servername:port> <port> [-k | --insecure]"); |   console.info("Usage: sclient  [--servername <string>] [-k | --insecure] <servername:port> <port>"); | ||||||
|   console.info("   ex: sclient whatever.com 3000"); |   console.info("   ex: sclient whatever.com 3000"); | ||||||
|   console.info("       (whatever.com:443 localhost:3000)"); |   console.info("       (whatever.com:443 localhost:3000)"); | ||||||
|   console.info("   ex: sclient whatever.com:4080 0.0.0.0:3000"); |   console.info("   ex: sclient whatever.com:4080 0.0.0.0:3000"); | ||||||
|   console.info(""); |   console.info(""); | ||||||
|   process.exit(0); |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | 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; | ||||||
|  |     } | ||||||
|  |   }); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | parseFlags(); | ||||||
|  | 
 | ||||||
|  | remote = (process.argv[2]||'').split(':'); | ||||||
|  | local = (process.argv[3]||'').split(':'); | ||||||
|  | 
 | ||||||
|  | // 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]) { | if (!remote[0]) { | ||||||
|   usage(); |   usage(); | ||||||
|   return; |   return; | ||||||
| } | } | ||||||
| if (!remote[1]) { |  | ||||||
|   remote[1] = 443; |  | ||||||
| } |  | ||||||
| 
 | 
 | ||||||
| if (!local[0]) { | if (!local[0]) { | ||||||
|   usage(); |   usage(); | ||||||
| @ -34,24 +72,23 @@ if (local[0] === String(parseInt(local[0], 10))) { | |||||||
|   localPort = parseInt(local[0], 10); |   localPort = parseInt(local[0], 10); | ||||||
|   localAddress = 'localhost'; |   localAddress = 'localhost'; | ||||||
| } else { | } else { | ||||||
|   localAddress = local[0]; |   localAddress = local[0]; // potentially '-' or '|'
 | ||||||
|   localPort = parseInt(local[1], 10); |   localPort = parseInt(local[1], 10); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| if (!localPort) { | if ('-' === localAddress || '|' === localAddress) { | ||||||
|  |   // no need for port
 | ||||||
|  | } else if (!localPort) { | ||||||
|   usage(); |   usage(); | ||||||
|   return; |   return; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| if (/^-k|--insecure$/.test(process.argv[4])) { |  | ||||||
|   rejectUnauthorized = false; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| var opts = { | var opts = { | ||||||
|   remoteAddr: remote[0] |   remoteAddr: remote[0] | ||||||
| , remotePort: remote[1] | , remotePort: remote[1] | ||||||
| , localAddress: localAddress | , localAddress: localAddress | ||||||
| , localPort: localPort | , localPort: localPort | ||||||
| , rejectUnauthorized: rejectUnauthorized | , rejectUnauthorized: rejectUnauthorized | ||||||
|  | , servername: servername | ||||||
| }; | }; | ||||||
| require('../')(opts); | require('../')(opts); | ||||||
|  | |||||||
							
								
								
									
										28
									
								
								index.js
									
									
									
									
									
								
							
							
						
						
									
										28
									
								
								index.js
									
									
									
									
									
								
							| @ -4,7 +4,7 @@ var net = require('net'); | |||||||
| var tls = require('tls'); | var tls = require('tls'); | ||||||
| 
 | 
 | ||||||
| function listenForConns(opts) { | function listenForConns(opts) { | ||||||
|   var server = net.createServer(function (c) { |   function pipeConn(c, out) { | ||||||
|     var sclient = tls.connect({ |     var sclient = tls.connect({ | ||||||
|       servername: opts.remoteAddr, host: opts.remoteAddr, port: opts.remotePort |       servername: opts.remoteAddr, host: opts.remoteAddr, port: opts.remotePort | ||||||
|     , rejectUnauthorized: opts.rejectUnauthorized |     , rejectUnauthorized: opts.rejectUnauthorized | ||||||
| @ -12,7 +12,7 @@ function listenForConns(opts) { | |||||||
|       console.info('[connect] ' + sclient.localAddress.replace('::1', 'localhost') + ":" + sclient.localPort |       console.info('[connect] ' + sclient.localAddress.replace('::1', 'localhost') + ":" + sclient.localPort | ||||||
|         + " => " + opts.remoteAddr + ":" + opts.remotePort); |         + " => " + opts.remoteAddr + ":" + opts.remotePort); | ||||||
|       c.pipe(sclient); |       c.pipe(sclient); | ||||||
|       sclient.pipe(c); |       sclient.pipe(out || c); | ||||||
|     }); |     }); | ||||||
|     sclient.on('error', function (err) { |     sclient.on('error', function (err) { | ||||||
|       console.error('[error] (remote) ' + err.toString()); |       console.error('[error] (remote) ' + err.toString()); | ||||||
| @ -20,7 +20,19 @@ function listenForConns(opts) { | |||||||
|     c.on('error', function (err) { |     c.on('error', function (err) { | ||||||
|       console.error('[error] (local) ' + err.toString()); |       console.error('[error] (local) ' + err.toString()); | ||||||
|     }); |     }); | ||||||
|   }); |     if (out) { | ||||||
|  |       out.on('error', function (err) { | ||||||
|  |         console.error('[error] (local) ' + err.toString()); | ||||||
|  |       }); | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   if ('-' === opts.localAddress || '|' === opts.localAddress) { | ||||||
|  |     pipeConn(process.stdin, process.stdout); | ||||||
|  |     return; | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   var server = net.createServer(pipeConn); | ||||||
|   server.on('error', function (err) { |   server.on('error', function (err) { | ||||||
|     console.error('[error] ' + err.toString()); |     console.error('[error] ' + err.toString()); | ||||||
|   }); |   }); | ||||||
| @ -35,10 +47,14 @@ function listenForConns(opts) { | |||||||
| 
 | 
 | ||||||
| function testConn(opts) { | function testConn(opts) { | ||||||
|   // Test connection first
 |   // Test connection first
 | ||||||
|   var tlsSock = tls.connect({ |   var tlsOpts = { | ||||||
|     servername: opts.remoteAddr, host: opts.remoteAddr, port: opts.remotePort |     host: opts.remoteAddr, port: opts.remotePort | ||||||
|   , rejectUnauthorized: opts.rejectUnauthorized |   , rejectUnauthorized: opts.rejectUnauthorized | ||||||
|   }, function () { |   }; | ||||||
|  |   if (opts.servername) { | ||||||
|  |     tlsOpts.servername = opts.servername; | ||||||
|  |   } | ||||||
|  |   var tlsSock = tls.connect(tlsOpts, function () { | ||||||
|     tlsSock.end(); |     tlsSock.end(); | ||||||
|     listenForConns(opts); |     listenForConns(opts); | ||||||
|   }); |   }); | ||||||
|  | |||||||
| @ -1,6 +1,6 @@ | |||||||
| { | { | ||||||
|   "name": "sclient", |   "name": "sclient", | ||||||
|   "version": "1.0.4", |   "version": "1.2.0", | ||||||
|   "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://git.coolaj86.com/coolaj86/sclient.js", |   "homepage": "https://git.coolaj86.com/coolaj86/sclient.js", | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user