forked from coolaj86/telebit.js
		
	progress towards telebit
This commit is contained in:
		
							parent
							
								
									ca2e825fe7
								
							
						
					
					
						commit
						e8c580d115
					
				
							
								
								
									
										55
									
								
								README.md
									
									
									
									
									
								
							
							
						
						
									
										55
									
								
								README.md
									
									
									
									
									
								
							| @ -91,16 +91,10 @@ email: 'jon@example.com'          # must be valid (for certificate recovery and | ||||
| agree_tos: true                   # agree to the Telebit, Greenlock, and Let's Encrypt TOSes | ||||
| community_member: true            # receive infrequent relevant but non-critical updates | ||||
| telemetry: true                   # contribute to project telemetric data | ||||
| secret: ''                        # JWT authorization secret. Generate like so: | ||||
|                                   #   node -e "console.log(crypto.randomBytes(16).toString('hex'))" | ||||
| remote_options: | ||||
|   https_redirect: false           # don't redirect http to https remotely | ||||
| secret: ''                        # Secret with which to sign Tokens for authorization | ||||
| token: ''                         # A signed Token for authorization | ||||
| servernames:                      # servernames that will be forwarded here | ||||
|   - example.com | ||||
| local_ports:                      # ports to forward | ||||
|   3000: 'http' | ||||
|   8443: 'https' | ||||
|   5050: true | ||||
| ``` | ||||
| 
 | ||||
| <!-- | ||||
| @ -152,8 +146,8 @@ You can **integrate telebit.js into your existing codebase** or use the **standa | ||||
| Telebit CLI | ||||
| ----------- | ||||
| 
 | ||||
| Installs as `stunnel.js` with the alias `jstunnel` | ||||
| (for those that regularly use `stunnel` but still like commandline completion). | ||||
| Installs Telebit Remote as `telebit` | ||||
| (for those that regularly use `telebit` but still like commandline completion). | ||||
| 
 | ||||
| ### Install | ||||
| 
 | ||||
| @ -162,44 +156,44 @@ npm install -g telebit | ||||
| ``` | ||||
| 
 | ||||
| ```bash | ||||
| npm install -g 'git+https://git@git.coolaj86.com/coolaj86/tunnel-client.js.git#v1' | ||||
| npm install -g 'https://git.coolaj86.com/coolaj86/telebit.js.git#v1' | ||||
| ``` | ||||
| 
 | ||||
| Or if you want to bow down to the kings of the centralized dictator-net: | ||||
| 
 | ||||
| How to use `stunnel.js` with your own instance of `stunneld.js`: | ||||
| How to use Telebit Remote with your own instance of Telebit Relay: | ||||
| 
 | ||||
| ```bash | ||||
| stunnel.js \ | ||||
| telebit \ | ||||
|   --locals <<external domain name>> \ | ||||
|   --stunneld wss://<<tunnel domain>>:<<tunnel port>> \ | ||||
|   --relay wss://<<tunnel domain>>:<<tunnel port>> \ | ||||
|   --secret <<128-bit hex key>> | ||||
| ``` | ||||
| 
 | ||||
| ```bash | ||||
| stunnel.js --locals john.example.com --stunneld wss://tunnel.example.com:443 --secret abc123 | ||||
| telebit --locals john.example.com --relay wss://tunnel.example.com:443 --secret abc123 | ||||
| ``` | ||||
| 
 | ||||
| ```bash | ||||
| stunnel.js \ | ||||
| telebit \ | ||||
|   --locals <<protocol>>:<<external domain name>>:<<local port>> \ | ||||
|   --stunneld wss://<<tunnel domain>>:<<tunnel port>> \ | ||||
|   --relay wss://<<tunnel domain>>:<<tunnel port>> \ | ||||
|   --secret <<128-bit hex key>> | ||||
| ``` | ||||
| 
 | ||||
| ```bash | ||||
| stunnel.js \ | ||||
| telebit \ | ||||
|   --locals http:john.example.com:3000,https:john.example.com \ | ||||
|   --stunneld wss://tunnel.example.com:443 \ | ||||
|   --relay wss://tunnel.example.com:443 \ | ||||
|   --secret abc123 | ||||
| ``` | ||||
| 
 | ||||
| ``` | ||||
| --secret          the same secret used by stunneld (used for authentication) | ||||
| --secret          the same secret used by the Telebit Relay (for authentication) | ||||
| --locals          comma separated list of <proto>:<servername>:<port> to which | ||||
|                   incoming http and https should be forwarded | ||||
| --stunneld        the domain or ip address at which you are running stunneld.js | ||||
| -k, --insecure    ignore invalid ssl certificates from stunneld | ||||
| --relay        the domain or ip address at which you are running Telebit Relay | ||||
| -k, --insecure    ignore invalid ssl certificates from relay | ||||
| ``` | ||||
| 
 | ||||
| Node.js Library | ||||
| @ -208,10 +202,10 @@ Node.js Library | ||||
| ### Example | ||||
| 
 | ||||
| ```javascript | ||||
| var stunnel = require('stunnel'); | ||||
| var Telebit = require('telebit'); | ||||
| 
 | ||||
| stunnel.connect({ | ||||
|   stunneld: 'wss://tunnel.example.com' | ||||
| Telebit.connect({ | ||||
|   relay: 'wss://tunnel.example.com' | ||||
| , token: '...' | ||||
| , locals: [ | ||||
|     // defaults to sending http to local port 80 and https to local port 443 | ||||
| @ -251,7 +245,7 @@ local handler and the tunnel handler. | ||||
| You could do a little magic like this: | ||||
| 
 | ||||
| ```js | ||||
| stunnel.connect({ | ||||
| Telebit.connect({ | ||||
|   // ... | ||||
| , net: { | ||||
|   createConnection: function (info, cb) { | ||||
| @ -286,6 +280,15 @@ stunnel.connect({ | ||||
| }); | ||||
| ``` | ||||
| 
 | ||||
| TODO | ||||
| ==== | ||||
| 
 | ||||
| Install for user | ||||
|   * https://wiki.archlinux.org/index.php/Systemd/User | ||||
|   * https://developer.apple.com/library/content/documentation/MacOSX/Conceptual/BPSystemStartup/Chapters/CreatingLaunchdJobs.html | ||||
|     * `sudo launchctl load -w ~/Library/LaunchAgents/cloud.telebit.remote` | ||||
|     * https://serverfault.com/questions/194832/how-to-start-stop-restart-launchd-services-from-the-command-line | ||||
| 
 | ||||
| Browser Library | ||||
| ======= | ||||
| 
 | ||||
|  | ||||
							
								
								
									
										203
									
								
								bin/telebit.js
									
									
									
									
									
								
							
							
						
						
									
										203
									
								
								bin/telebit.js
									
									
									
									
									
								
							| @ -4,9 +4,43 @@ | ||||
| 
 | ||||
| var pkg = require('../package.json'); | ||||
| 
 | ||||
| var program = require('commander'); | ||||
| var url = require('url'); | ||||
| var stunnel = require('../wsclient.js'); | ||||
| var remote = require('../wsclient.js'); | ||||
| 
 | ||||
| var argv = process.argv.slice(2); | ||||
| //var Greenlock = require('greenlock');
 | ||||
| 
 | ||||
| var confIndex = argv.indexOf('--config'); | ||||
| var confpath; | ||||
| if (-1 === confIndex) { | ||||
|   confIndex = argv.indexOf('-c'); | ||||
| } | ||||
| confpath = argv[confIndex + 1]; | ||||
| 
 | ||||
| function help() { | ||||
|   console.info(''); | ||||
|   console.info('Usage:'); | ||||
|   console.info(''); | ||||
|   console.info('\ttelebit --config <path>'); | ||||
|   console.info(''); | ||||
|   console.info('Example:'); | ||||
|   console.info(''); | ||||
|   console.info('\ttelebit --config /etc/telebit/telebit.yml'); | ||||
|   console.info(''); | ||||
|   console.info('Config:'); | ||||
|   console.info(''); | ||||
|   console.info('\tSee https://git.coolaj86.com/coolaj86/telebit.js'); | ||||
|   console.info(''); | ||||
|   console.info(''); | ||||
|   process.exit(0); | ||||
| } | ||||
| 
 | ||||
| if (-1 === confIndex || -1 !== argv.indexOf('-h') || -1 !== argv.indexOf('--help')) { | ||||
|   help(); | ||||
| } | ||||
| if (!confpath || /^--/.test(confpath)) { | ||||
|   help(); | ||||
| } | ||||
| 
 | ||||
| var domainsMap = {}; | ||||
| var services = {}; | ||||
| @ -114,6 +148,78 @@ function collectProxies(val, memo) { | ||||
|   return memo; | ||||
| } | ||||
| 
 | ||||
| function connectTunnel() { | ||||
|   var state = {}; | ||||
|   var services = { https: {}, http: {}, tcp: {} }; | ||||
|   state.net = { | ||||
|     createConnection: function (info, cb) { | ||||
|       // data is the hello packet / first chunk
 | ||||
|       // info = { data, servername, port, host, remoteFamily, remoteAddress, remotePort }
 | ||||
|       var net = require('net'); | ||||
|       // socket = { write, push, end, events: [ 'readable', 'data', 'error', 'end' ] };
 | ||||
|       var socket = net.createConnection({ port: info.port, host: info.host }, cb); | ||||
|       return socket; | ||||
|     } | ||||
|   }; | ||||
| 
 | ||||
|   // Note: the remote needs to know:
 | ||||
|   //   what servernames to forward
 | ||||
|   //   what ports to forward
 | ||||
|   //   what udp ports to forward
 | ||||
|   //   redirect http to https automatically
 | ||||
|   //   redirect www to nowww automatically
 | ||||
|   Object.keys(state.config.localPorts).forEach(function (port) { | ||||
|     var proto = state.config.localPorts[port]; | ||||
|     if (!proto) { return; } | ||||
|     if ('http' === proto) { | ||||
|       state.config.servernames.forEach(function (servername) { | ||||
|         services.http[servername] = port; | ||||
|       }); | ||||
|       return; | ||||
|     } | ||||
|     if ('https' === proto) { | ||||
|       state.config.servernames.forEach(function (servername) { | ||||
|         services.https[servername] = port; | ||||
|       }); | ||||
|       return; | ||||
|     } | ||||
|     if (true === proto) { proto = 'tcp'; } | ||||
|     if ('tcp' !== proto) { throw new Error("unsupported protocol '" + proto + "'"); } | ||||
|     //services[proxy.protocol]['*'] = proxy.port;
 | ||||
|     //services[proxy.protocol][proxy.hostname] = proxy.port;
 | ||||
|     services[proto]['*'] = port; | ||||
|   }); | ||||
| 
 | ||||
|   Object.keys(program.services).forEach(function (protocol) { | ||||
|     var subServices = program.services[protocol]; | ||||
|     Object.keys(subServices).forEach(function (hostname) { | ||||
|       console.info('[local proxy]', protocol + '://' + hostname + ' => ' + subServices[hostname]); | ||||
|     }); | ||||
|   }); | ||||
|   console.info(''); | ||||
| 
 | ||||
|   var tun = remote.connect({ | ||||
|     relay: state.config.relay | ||||
|   , locals: state.config.servernames | ||||
|   , services: state.services | ||||
|   , net: state.net | ||||
|   , insecure: state.config.relay_ignore_invalid_certificates | ||||
|   , token: state.config.token | ||||
|   }); | ||||
| 
 | ||||
|   function sigHandler() { | ||||
|     console.log('SIGINT'); | ||||
| 
 | ||||
|     // We want to handle cleanup properly unless something is broken in our cleanup process
 | ||||
|     // that prevents us from exitting, in which case we want the user to be able to send
 | ||||
|     // the signal again and exit the way it normally would.
 | ||||
|     process.removeListener('SIGINT', sigHandler); | ||||
|     tun.end(); | ||||
|   } | ||||
|   process.on('SIGINT', sigHandler); | ||||
| } | ||||
| 
 | ||||
| var program = require('commander'); | ||||
| program | ||||
|   .version(pkg.version) | ||||
|   //.command('jsurl <url>')
 | ||||
| @ -134,63 +240,22 @@ program | ||||
|   .parse(process.argv) | ||||
|   ; | ||||
| 
 | ||||
| function connectTunnel() { | ||||
|   program.net = { | ||||
|     createConnection: function (info, cb) { | ||||
|       // data is the hello packet / first chunk
 | ||||
|       // info = { data, servername, port, host, remoteFamily, remoteAddress, remotePort }
 | ||||
|       var net = require('net'); | ||||
|       // socket = { write, push, end, events: [ 'readable', 'data', 'error', 'end' ] };
 | ||||
|       var socket = net.createConnection({ port: info.port, host: info.host }, cb); | ||||
|       return socket; | ||||
|     } | ||||
|   }; | ||||
| 
 | ||||
|   Object.keys(program.services).forEach(function (protocol) { | ||||
|     var subServices = program.services[protocol]; | ||||
|     Object.keys(subServices).forEach(function (hostname) { | ||||
|       console.info('[local proxy]', protocol + '://' + hostname + ' => ' + subServices[hostname]); | ||||
|     }); | ||||
|   }); | ||||
|   console.info(''); | ||||
| 
 | ||||
|   var tun = stunnel.connect({ | ||||
|     stunneld: program.stunneld | ||||
|   , locals: program.locals | ||||
|   , services: program.services | ||||
|   , net: program.net | ||||
|   , insecure: program.insecure | ||||
|   , token: program.token | ||||
|   }); | ||||
| 
 | ||||
|   function sigHandler() { | ||||
|     console.log('SIGINT'); | ||||
| 
 | ||||
|     // We want to handle cleanup properly unless something is broken in our cleanup process
 | ||||
|     // that prevents us from exitting, in which case we want the user to be able to send
 | ||||
|     // the signal again and exit the way it normally would.
 | ||||
|     process.removeListener('SIGINT', sigHandler); | ||||
|     tun.end(); | ||||
|   } | ||||
|   process.on('SIGINT', sigHandler); | ||||
| } | ||||
| 
 | ||||
| function rawTunnel() { | ||||
|   program.stunneld = program.stunneld || 'wss://tunnel.daplie.com'; | ||||
|   program.relay = program.relay || 'wss://telebit.cloud'; | ||||
| 
 | ||||
|   if (!(program.secret || program.token)) { | ||||
|     console.error("You must use --secret or --token with --stunneld"); | ||||
|     console.error("You must use --secret or --token with --relay"); | ||||
|     process.exit(1); | ||||
|     return; | ||||
|   } | ||||
| 
 | ||||
|   var location = url.parse(program.stunneld); | ||||
|   var location = url.parse(program.relay); | ||||
|   if (!location.protocol || /\./.test(location.protocol)) { | ||||
|     program.stunneld = 'wss://' + program.stunneld; | ||||
|     location = url.parse(program.stunneld); | ||||
|     program.relay = 'wss://' + program.relay; | ||||
|     location = url.parse(program.relay); | ||||
|   } | ||||
|   var aud = location.hostname + (location.port ? ':' + location.port : ''); | ||||
|   program.stunneld = location.protocol + '//' + aud; | ||||
|   program.relay = location.protocol + '//' + aud; | ||||
| 
 | ||||
|   if (!program.token) { | ||||
|     var jwt = require('jsonwebtoken'); | ||||
| @ -205,41 +270,6 @@ function rawTunnel() { | ||||
|   connectTunnel(); | ||||
| } | ||||
| 
 | ||||
| function daplieTunnel() { | ||||
|   //var OAUTH3 = require('oauth3.js');
 | ||||
|   var Oauth3Cli = require('oauth3.js/bin/oauth3.js'); | ||||
|   require('oauth3.js/oauth3.tunnel.js'); | ||||
|   return Oauth3Cli.login({ | ||||
|     email: program.email | ||||
|   , providerUri: program.oauth3Url || 'oauth3.org' | ||||
|   }).then(function (oauth3) { | ||||
|     var data = { device: null, domains: [] }; | ||||
|     var domains = Object.keys(domainsMap).filter(Boolean); | ||||
|     if (program.device) { | ||||
|       // TODO use device API to select device by id
 | ||||
|       data.device = { hostname: program.device }; | ||||
|       if (true === program.device) { | ||||
|         data.device.hostname = require('os').hostname(); | ||||
|         console.log("Using device hostname '" + data.device.hostname + "'"); | ||||
|       } | ||||
|     } | ||||
|     if (domains.length) { | ||||
|       data.domains = domains; | ||||
|     } | ||||
|     return oauth3.api('tunnel.token', { data: data }).then(function (results) { | ||||
|       var token = new Buffer(results.jwt.split('.')[1], 'base64').toString('utf8'); | ||||
|       console.info(''); | ||||
|       console.info('tunnel token issued:'); | ||||
|       console.info(token); | ||||
|       console.info(''); | ||||
|       program.token = results.jwt; | ||||
|       program.stunneld = results.tunnelUrl || ('wss://' + token.aud + '/'); | ||||
| 
 | ||||
|       connectTunnel(); | ||||
|     }); | ||||
|   }); | ||||
| } | ||||
| 
 | ||||
| program.locals = (program.locals || []).concat(program.domains || []); | ||||
| program.locals.forEach(function (proxy) { | ||||
|   // Create a map from which we can derive a list of all domains we want forwarded to us.
 | ||||
| @ -282,11 +312,6 @@ services.http['*'] = services.http['*'] || services.https['*']; | ||||
| 
 | ||||
| program.services = services; | ||||
| 
 | ||||
| if (!(program.secret || program.token) && !program.stunneld) { | ||||
|   daplieTunnel(); | ||||
| } | ||||
| else { | ||||
| rawTunnel(); | ||||
| } | ||||
| 
 | ||||
| }()); | ||||
|  | ||||
							
								
								
									
										66
									
								
								dist/etc/systemd/system/telebitd.service
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										66
									
								
								dist/etc/systemd/system/telebitd.service
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @ -0,0 +1,66 @@ | ||||
| # Pre-req | ||||
| # sudo adduser telebit --home /opt/telebit | ||||
| # sudo mkdir -p /opt/telebit/ | ||||
| # sudo chown -R telebit:telebit /opt/telebit/ | ||||
| 
 | ||||
| [Unit] | ||||
| Description=Telebit Relay | ||||
| Documentation=https://git.coolaj86.com/coolaj86/telebit.js/ | ||||
| After=network-online.target | ||||
| Wants=network-online.target systemd-networkd-wait-online.service | ||||
| 
 | ||||
| [Service] | ||||
| # Restart on crash (bad signal), but not on 'clean' failure (error exit code) | ||||
| # Allow up to 3 restarts within 10 seconds | ||||
| # (it's unlikely that a user or properly-running script will do this) | ||||
| Restart=on-abnormal | ||||
| StartLimitInterval=10 | ||||
| StartLimitBurst=3 | ||||
| 
 | ||||
| # User and group the process will run as | ||||
| # (git is the de facto standard on most systems) | ||||
| User=telebit | ||||
| Group=telebit | ||||
| 
 | ||||
| WorkingDirectory=/opt/telebit | ||||
| # custom directory cannot be set and will be the place where gitea exists, not the working directory | ||||
| ExecStart=/opt/telebit/bin/node /opt/telebit/bin/telebit.js --config /etc/telebit/telebit.yml | ||||
| ExecReload=/bin/kill -USR1 $MAINPID | ||||
| 
 | ||||
| # Limit the number of file descriptors and processes; see `man systemd.exec` for more limit settings. | ||||
| # Unmodified gitea is not expected to use more than this. | ||||
| LimitNOFILE=1048576 | ||||
| LimitNPROC=64 | ||||
| 
 | ||||
| # Use private /tmp and /var/tmp, which are discarded after gitea stops. | ||||
| PrivateTmp=true | ||||
| # Use a minimal /dev | ||||
| PrivateDevices=true | ||||
| # Hide /home, /root, and /run/user. Nobody will steal your SSH-keys. | ||||
| ProtectHome=true | ||||
| # Make /usr, /boot, /etc and possibly some more folders read-only. | ||||
| ProtectSystem=full | ||||
| # ... except /opt/gitea because we want a place for the database | ||||
| # and /var/log/gitea because we want a place where logs can go. | ||||
| # This merely retains r/w access rights, it does not add any new. | ||||
| # Must still be writable on the host! | ||||
| ReadWriteDirectories=/opt/telebit /etc/telebit | ||||
| 
 | ||||
| # Note: in v231 and above ReadWritePaths has been renamed to ReadWriteDirectories | ||||
| ; ReadWritePaths=/opt/telebit /etc/telebit | ||||
| 
 | ||||
| # The following additional security directives only work with systemd v229 or later. | ||||
| # They further retrict privileges that can be gained by gitea. | ||||
| # Note that you may have to add capabilities required by any plugins in use. | ||||
| CapabilityBoundingSet=CAP_NET_BIND_SERVICE | ||||
| AmbientCapabilities=CAP_NET_BIND_SERVICE | ||||
| NoNewPrivileges=true | ||||
| 
 | ||||
| # Caveat: Some features may need additional capabilities. | ||||
| # For example an "upload" may need CAP_LEASE | ||||
| ; CapabilityBoundingSet=CAP_NET_BIND_SERVICE CAP_LEASE | ||||
| ; AmbientCapabilities=CAP_NET_BIND_SERVICE CAP_LEASE | ||||
| ; NoNewPrivileges=true | ||||
| 
 | ||||
| [Install] | ||||
| WantedBy=multi-user.target | ||||
							
								
								
									
										16
									
								
								examples/telebit.yml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										16
									
								
								examples/telebit.yml
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,16 @@ | ||||
| email: 'jon@example.com'       # must be valid (for certificate recovery and security alerts) | ||||
| agree_tos: true                # agree to the Telebit, Greenlock, and Let's Encrypt TOSes | ||||
| community_member: true         # receive infrequent relevant updates | ||||
| telemetry: true                # contribute to project telemetric data | ||||
| relay: wss://telebit.cloud     # Which Telebit Relay to use | ||||
| secret: ''                     # Token or Secret to use for authorization | ||||
| token: ''                      # Token or Secret to use for authorization | ||||
| remote_options: | ||||
|   https_redirect: true         # redirect http to https remotely (default) | ||||
| servernames:                   # hostnames that direct to the Telebit Relay admin console | ||||
|   - example.com | ||||
|   - example.net | ||||
| local_ports:                      # ports to forward | ||||
|   3000: 'http' | ||||
|   8443: 'https' | ||||
|   5050: true | ||||
							
								
								
									
										8
									
								
								examples/telebit.yml.tpl
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										8
									
								
								examples/telebit.yml.tpl
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,8 @@ | ||||
| agree_tos: true                # agree to the Telebit, Greenlock, and Let's Encrypt TOSes | ||||
| community_member: true         # receive infrequent relevant updates | ||||
| telemetry: true                # contribute to project telemetric data | ||||
| remote_options: | ||||
|   https_redirect: true         # redirect http to https remotely (default) | ||||
| local_ports:                      # ports to forward | ||||
|   3001: 'http' | ||||
|   9443: 'https' | ||||
							
								
								
									
										249
									
								
								installer/get.sh
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										249
									
								
								installer/get.sh
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,249 @@ | ||||
| #!/bin/bash | ||||
| #<pre><code> | ||||
| 
 | ||||
| # This is a 3 step process | ||||
| #   1. First we need to figure out whether to use wget or curl for fetching remote files | ||||
| #   2. Next we need to figure out whether to use unzip or tar for downloading releases | ||||
| #   3. We need to actually install the stuff | ||||
| 
 | ||||
| set -e | ||||
| set -u | ||||
| 
 | ||||
| ############################### | ||||
| #                             # | ||||
| #         http_get            # | ||||
| # boilerplate for curl / wget # | ||||
| #                             # | ||||
| ############################### | ||||
| 
 | ||||
| # See https://git.coolaj86.com/coolaj86/snippets/blob/master/bash/http-get.sh | ||||
| 
 | ||||
| _my_http_get="" | ||||
| _my_http_opts="" | ||||
| _my_http_out="" | ||||
| 
 | ||||
| detect_http_get() | ||||
| { | ||||
|   set +e | ||||
|   if type -p curl >/dev/null 2>&1; then | ||||
|     _my_http_get="curl" | ||||
|     _my_http_opts="-fsSL" | ||||
|     _my_http_out="-o" | ||||
|   elif type -p wget >/dev/null 2>&1; then | ||||
|     _my_http_get="wget" | ||||
|     _my_http_opts="--quiet" | ||||
|     _my_http_out="-O" | ||||
|   else | ||||
|     echo "Aborted, could not find curl or wget" | ||||
|     return 7 | ||||
|   fi | ||||
|   set -e | ||||
| } | ||||
| 
 | ||||
| http_get() | ||||
| { | ||||
|   $_my_http_get $_my_http_opts $_my_http_out "$2" "$1" | ||||
|   touch "$2" | ||||
| } | ||||
| 
 | ||||
| http_bash() | ||||
| { | ||||
|   _http_url=$1 | ||||
|   my_args=${2:-} | ||||
|   rm -rf my-tmp-runner.sh | ||||
|   $_my_http_get $_my_http_opts $_my_http_out my-tmp-runner.sh "$_http_url"; bash my-tmp-runner.sh $my_args; rm my-tmp-runner.sh | ||||
| } | ||||
| 
 | ||||
| detect_http_get | ||||
| 
 | ||||
| ############################### | ||||
| ##       END HTTP_GET        ## | ||||
| ############################### | ||||
| 
 | ||||
| my_email=${1:-} | ||||
| my_relay=${2:-} | ||||
| my_servernames=${3:-} | ||||
| my_secret=${4:-} | ||||
| my_user="telebit" | ||||
| my_app="telebit" | ||||
| my_bin="telebit.js" | ||||
| my_name="Telebit Remote" | ||||
| my_repo="telebit.js" | ||||
| 
 | ||||
| if [ -z "${my_email}" ]; then | ||||
|   echo "" | ||||
|   echo "" | ||||
|   echo "Telebit uses Greenlock for free automated ssl through Let's Encrypt." | ||||
|   echo "" | ||||
|   echo "To accept the Terms of Service for Telebit, Greenlock and Let's Encrypt," | ||||
|   echo "please enter your email." | ||||
|   echo "" | ||||
|   read -p "email: " my_email | ||||
|   echo "" | ||||
|   # UX - just want a smooth transition | ||||
|   sleep 0.5 | ||||
| fi | ||||
| 
 | ||||
| if [ -z "${my_relay}" ]; then | ||||
|   echo "What relay will you be using?" | ||||
|   echo "" | ||||
|   read -p "relay (ex: wss://telebit.cloud): " my_relay | ||||
|   echo "" | ||||
|   # UX - just want a smooth transition | ||||
|   sleep 0.5 | ||||
| fi | ||||
| 
 | ||||
| if [ -z "${my_servernames}" ]; then | ||||
|   echo "What servername(s) will you be relaying here?" | ||||
|   echo "" | ||||
|   read -p "domain (ex: example.com,example.net): " my_servernames | ||||
|   echo "" | ||||
|   # UX - just want a smooth transition | ||||
|   sleep 0.5 | ||||
| fi | ||||
| 
 | ||||
| if [ -z "${my_secret}" ]; then | ||||
|   echo "What's your authorization for the relay server?" | ||||
|   echo "" | ||||
|   read -p "auth: " my_secret | ||||
|   echo "" | ||||
|   # UX - just want a smooth transition | ||||
|   sleep 0.5 | ||||
| fi | ||||
| 
 | ||||
| echo "" | ||||
| 
 | ||||
| if [ -z "${TELEBIT_PATH:-}" ]; then | ||||
|   echo 'TELEBIT_PATH="'${TELEBIT_PATH:-}'"' | ||||
|   TELEBIT_PATH=/opt/$my_app | ||||
| fi | ||||
| 
 | ||||
| echo "Installing $my_name to '$TELEBIT_PATH'" | ||||
| 
 | ||||
| echo "Installing node.js dependencies into $TELEBIT_PATH" | ||||
| # v10.2+ has much needed networking fixes, but breaks ursa. v9.x has severe networking bugs. v8.x has working ursa, but requires tls workarounds" | ||||
| NODEJS_VER="${NODEJS_VER:-v10}" | ||||
| export NODEJS_VER | ||||
| export NODE_PATH="$TELEBIT_PATH/lib/node_modules" | ||||
| export NPM_CONFIG_PREFIX="$TELEBIT_PATH" | ||||
| export PATH="$TELEBIT_PATH/bin:$PATH" | ||||
| sleep 1 | ||||
| http_bash https://git.coolaj86.com/coolaj86/node-installer.sh/raw/branch/master/install.sh --no-dev-deps >/dev/null 2>/dev/null | ||||
| 
 | ||||
| my_tree="master" | ||||
| my_node="$TELEBIT_PATH/bin/node" | ||||
| my_secret=$($my_node -e "console.info(crypto.randomBytes(16).toString('hex'))") | ||||
| my_npm="$my_node $TELEBIT_PATH/bin/npm" | ||||
| my_tmp="$TELEBIT_PATH/tmp" | ||||
| mkdir -p $my_tmp | ||||
| 
 | ||||
| echo "sudo mkdir -p '$TELEBIT_PATH'" | ||||
| sudo mkdir -p "$TELEBIT_PATH" | ||||
| echo "sudo mkdir -p '/etc/$my_user/'" | ||||
| sudo mkdir -p "/etc/$my_user/" | ||||
| 
 | ||||
| set +e | ||||
| #https://git.coolaj86.com/coolaj86/telebit.js.git | ||||
| #https://git.coolaj86.com/coolaj86/telebit.js/archive/:tree:.tar.gz | ||||
| #https://git.coolaj86.com/coolaj86/telebit.js/archive/:tree:.zip | ||||
| my_unzip=$(type -p unzip) | ||||
| my_tar=$(type -p tar) | ||||
| if [ -n "$my_unzip" ]; then | ||||
|   rm -f $my_tmp/$my_app-$my_tree.zip | ||||
|   http_get https://git.coolaj86.com/coolaj86/$my_repo/archive/$my_tree.zip $my_tmp/$my_app-$my_tree.zip | ||||
|   # -o means overwrite, and there is no option to strip | ||||
|   $my_unzip -o $my_tmp/$my_app-$my_tree.zip -d $TELEBIT_PATH/ > /dev/null 2>&1 | ||||
|   cp -ar  $TELEBIT_PATH/$my_repo/* $TELEBIT_PATH/ > /dev/null | ||||
|   rm -rf $TELEBIT_PATH/$my_bin | ||||
| elif [ -n "$my_tar" ]; then | ||||
|   rm -f $my_tmp/$my_app-$my_tree.tar.gz | ||||
|   http_get https://git.coolaj86.com/coolaj86/$my_repo/archive/$my_tree.tar.gz $my_tmp/$my_app-$my_tree.tar.gz | ||||
|   ls -lah $my_tmp/$my_app-$my_tree.tar.gz | ||||
|   $my_tar -xzf $my_tmp/$my_app-$my_tree.tar.gz --strip 1 -C $TELEBIT_PATH/ | ||||
| else | ||||
|   echo "Neither tar nor unzip found. Abort." | ||||
|   exit 13 | ||||
| fi | ||||
| set -e | ||||
| 
 | ||||
| pushd $TELEBIT_PATH >/dev/null | ||||
|   $my_npm install >/dev/null 2>/dev/null | ||||
| popd >/dev/null | ||||
| 
 | ||||
| cat << EOF > $TELEBIT_PATH/bin/$my_app | ||||
| #!/bin/bash | ||||
| $my_node $TELEBIT_PATH/bin/$my_bin | ||||
| EOF | ||||
| chmod a+x $TELEBIT_PATH/bin/$my_app | ||||
| echo "sudo ln -sf $TELEBIT_PATH/bin/$my_app /usr/local/bin/$my_app" | ||||
| sudo ln -sf $TELEBIT_PATH/bin/$my_app /usr/local/bin/$my_app | ||||
| 
 | ||||
| set +e | ||||
| if type -p setcap >/dev/null 2>&1; then | ||||
|   #echo "Setting permissions to allow $my_app to run on port 80 and port 443 without sudo or root" | ||||
|   echo "sudo setcap cap_net_bind_service=+ep $TELEBIT_PATH/bin/node" | ||||
|   sudo setcap cap_net_bind_service=+ep $TELEBIT_PATH/bin/node | ||||
| fi | ||||
| set -e | ||||
| 
 | ||||
| if [ -z "$(cat /etc/passwd | grep $my_user)" ]; then | ||||
|   echo "sudo adduser --home $TELEBIT_PATH --gecos '' --disabled-password $my_user" | ||||
|   sudo adduser --home $TELEBIT_PATH --gecos '' --disabled-password $my_user >/dev/null 2>&1 | ||||
| fi | ||||
| 
 | ||||
| if [ ! -f "/etc/$my_user/$my_app.yml" ]; then | ||||
|   echo "### Creating config file from template. sudo may be required" | ||||
|   #echo "sudo rsync -a examples/$my_app.yml /etc/$my_user/$my_app.yml" | ||||
|   sudo bash -c "echo 'email: $my_email' >> /etc/$my_user/$my_app.yml" | ||||
|   sudo bash -c "echo 'secret: $my_secret' >> /etc/$my_user/$my_app.yml" | ||||
|   sudo bash -c "echo 'servernames: [ $my_servernames ]' >> /etc/$my_user/$my_app.yml" | ||||
|   sudo bash -c "cat examples/$my_app.yml.tpl >> /etc/$my_user/$my_app.yml" | ||||
| fi | ||||
| 
 | ||||
| echo "sudo chown -R $my_user '$TELEBIT_PATH' '/etc/$my_user'" | ||||
| sudo chown -R $my_user "$TELEBIT_PATH" "/etc/$my_user" | ||||
| 
 | ||||
| echo "### Adding $my_app is a system service" | ||||
| echo "sudo rsync -a $TELEBIT_PATH/dist/etc/systemd/system/$my_app.service /etc/systemd/system/$my_app.service" | ||||
| sudo rsync -a $TELEBIT_PATH/dist/etc/systemd/system/$my_app.service /etc/systemd/system/$my_app.service | ||||
| sudo systemctl daemon-reload | ||||
| echo "sudo systemctl enable $my_app" | ||||
| sudo systemctl enable $my_app | ||||
| echo "sudo systemctl start $my_app" | ||||
| sudo systemctl restart $my_app | ||||
| 
 | ||||
| sleep 1 | ||||
| echo "" | ||||
| echo "" | ||||
| echo "" | ||||
| echo "==============================================" | ||||
| echo "  Privacy Settings in Config" | ||||
| echo "==============================================" | ||||
| echo "" | ||||
| echo "The example config file /etc/$my_user/$my_app.yml opts-in to" | ||||
| echo "contributing telemetrics and receiving infrequent relevant updates" | ||||
| echo "(probably once per quarter or less) such as important notes on" | ||||
| echo "a new release, an important API change, etc. No spam." | ||||
| echo "" | ||||
| echo "Please edit the config file to meet your needs before starting." | ||||
| echo "" | ||||
| sleep 2 | ||||
| 
 | ||||
| echo "" | ||||
| echo "" | ||||
| echo "==============================================" | ||||
| echo "Installed successfully. Last steps:" | ||||
| echo "==============================================" | ||||
| echo "" | ||||
| echo "Edit the config and restart, if desired:" | ||||
| echo "" | ||||
| echo "    sudo vim /etc/$my_user/$my_app.yml" | ||||
| echo "    sudo systemctl restart $my_app" | ||||
| echo "" | ||||
| echo "Or disabled the service and start manually:" | ||||
| echo "" | ||||
| echo "    sudo systemctl stop $my_app" | ||||
| echo "    sudo systemctl disable $my_app" | ||||
| echo "    $my_app --config /etc/$my_user/$my_app.yml" | ||||
| echo "" | ||||
| sleep 1 | ||||
| @ -415,7 +415,7 @@ function run(copts) { | ||||
|     } | ||||
| 
 | ||||
|   , onOpen: function () { | ||||
|       console.info("[open] connected to '" + copts.stunneld + "'"); | ||||
|       console.info("[open] connected to '" + copts.relay + "'"); | ||||
|       wsHandlers.refreshTimeout(); | ||||
|       timeoutId = setTimeout(wsHandlers.checkTimeout, activityTimeout); | ||||
| 
 | ||||
| @ -500,8 +500,8 @@ function run(copts) { | ||||
|     timeoutId = null; | ||||
|     var machine = require('tunnel-packer').create(packerHandlers); | ||||
| 
 | ||||
|     console.info("[connect] '" + copts.stunneld + "'"); | ||||
|     var tunnelUrl = copts.stunneld.replace(/\/$/, '') + '/?access_token=' + tokens[0]; | ||||
|     console.info("[connect] '" + copts.relay + "'"); | ||||
|     var tunnelUrl = copts.relay.replace(/\/$/, '') + '/?access_token=' + tokens[0]; | ||||
|     wstunneler = new WebSocket(tunnelUrl, { rejectUnauthorized: !copts.insecure }); | ||||
|     wstunneler.on('open', wsHandlers.onOpen); | ||||
|     wstunneler.on('close', wsHandlers.onClose); | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user