Compare commits
	
		
			No commits in common. "bb018c538dbb3a492fbe5796e3a8d15e52294b6d" and "d700b514941a69291e86d1d644a22859ae27fc71" have entirely different histories.
		
	
	
		
			bb018c538d
			...
			d700b51494
		
	
		
							
								
								
									
										6
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										6
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							| @ -1,10 +1,4 @@ | ||||
| node_modules.* | ||||
| include | ||||
| bin/node | ||||
| bin/npm | ||||
| bin/npx | ||||
| share | ||||
| etc | ||||
| 
 | ||||
| # Logs | ||||
| logs | ||||
|  | ||||
							
								
								
									
										35
									
								
								README.md
									
									
									
									
									
								
							
							
						
						
									
										35
									
								
								README.md
									
									
									
									
									
								
							| @ -63,41 +63,6 @@ Windows & Node.js | ||||
| 
 | ||||
| There is [a bug](https://github.com/nodejs/node/issues/20241) in node v9.x that causes telebit-relay to crash. | ||||
| 
 | ||||
| Manually Install | ||||
| ----------- | ||||
| 
 | ||||
| ```bash | ||||
| git clone https://git.coolaj86.com/coolaj86/telebit-relay.js.git telebit-relay | ||||
| 
 | ||||
| # we're very picky to due to bugs in various versions of v8, v9, and v10 | ||||
| export NODEJS_VER="v10.2.1" | ||||
| 
 | ||||
| # We can keep everything self-contained | ||||
| export NPM_CONFIG_PREFIX=/opt/telebit-relay | ||||
| export NODE_PATH=/opt/telebit-relay/lib/node_modules | ||||
| 
 | ||||
| curl -fsSL https://bit.ly/node-installer | bash -s -- --no-dev-deps | ||||
| 
 | ||||
| pushd /opt/telebit-relay | ||||
|   bin/node bin/npm install | ||||
|   rsync -a examples/telebit-relay.yml etc/telebit-relay.yml | ||||
|   rsync -a dist/etc/systemd/system/telebit-relay.service /etc/systemd/system/telebit-relay.service | ||||
| popd | ||||
| 
 | ||||
| # IMPORTANT: Season the config file to taste | ||||
| # IMPORTANT: change your email address and domain | ||||
| edit /opt/telebit-relay/etc/telebit-relay.yml | ||||
| 
 | ||||
| adduser --home /opt/telebit-relay --gecos '' --disabled-password telebit >/dev/null 2>&1 | ||||
| sudo chown -R telebit:telebit /opt/telebit-relay/ | ||||
| 
 | ||||
| systemctl daemon-reload | ||||
| systemctl restart telebit-relay | ||||
| 
 | ||||
| systemctl status telebit-relay | ||||
| journalctl -xefu telebit-relay | ||||
| ``` | ||||
| 
 | ||||
| Usage | ||||
| ==== | ||||
| 
 | ||||
|  | ||||
| @ -1,7 +0,0 @@ | ||||
| { "terms_of_service": ":hostname/tos/" | ||||
| , "api_host": ":hostname" | ||||
| , "tunnel": { | ||||
|     "method": "wss" | ||||
|   , "pathname": "" | ||||
|   } | ||||
| } | ||||
| @ -134,7 +134,7 @@ function applyConfig(config) { | ||||
|     // TODO specify extensions in config file
 | ||||
|     state.extensions = require('../lib/extensions'); | ||||
|   } catch(e) { | ||||
|     if ('ENOENT' !== e.code || state.debug) { console.log('[DEBUG] no extensions loaded', e); } | ||||
|     if (state.debug) { console.log('[DEBUG] no extensions loaded', e); } | ||||
|     state.extensions = {}; | ||||
|   } | ||||
|   require('../lib/handlers').create(state); // adds directly to config for now...
 | ||||
|  | ||||
| @ -2,8 +2,6 @@ email: 'jon@example.com'       # must be valid (for certificate recovery and sec | ||||
| 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 | ||||
| webmin_domain: example.com | ||||
| shared_domain: xm.pl | ||||
| servernames:                   # hostnames that direct to the Telebit Relay admin console | ||||
|   - telebit.example.com | ||||
|   - telebit.example.net | ||||
| @ -68,7 +68,6 @@ my_app="telebit-relay" | ||||
| my_bin="telebit-relay.js" | ||||
| my_name="Telebit Relay" | ||||
| my_repo="telebit-relay.js" | ||||
| exec 3<>/dev/tty | ||||
| 
 | ||||
| if [ -z "${my_email}" ]; then | ||||
|   echo "" | ||||
| @ -78,7 +77,7 @@ if [ -z "${my_email}" ]; then | ||||
|   echo "To accept the Terms of Service for Telebit, Greenlock and Let's Encrypt," | ||||
|   echo "please enter your email." | ||||
|   echo "" | ||||
|   read -u 3 -p "email: " my_email | ||||
|   read -p "email: " my_email | ||||
|   echo "" | ||||
|   # UX - just want a smooth transition | ||||
|   sleep 0.5 | ||||
| @ -87,7 +86,7 @@ fi | ||||
| if [ -z "${my_servername}" ]; then | ||||
|   echo "What is the domain of this server (for admin interface)?" | ||||
|   echo "" | ||||
|   read -u 3 -p "domain (ex: telebit-relay.example.com): " my_servername | ||||
|   read -p "domain (ex: telebit-relay.example.com): " my_servername | ||||
|   echo "" | ||||
|   # UX - just want a smooth transition | ||||
|   sleep 0.5 | ||||
| @ -121,8 +120,8 @@ mkdir -p $my_tmp | ||||
| 
 | ||||
| echo "sudo mkdir -p '$TELEBIT_RELAY_PATH'" | ||||
| sudo mkdir -p "$TELEBIT_RELAY_PATH" | ||||
| echo "sudo mkdir -p '$TELEBIT_RELAY_PATH/etc'" | ||||
| sudo mkdir -p "$TELEBIT_RELAY_PATH/etc/" | ||||
| echo "sudo mkdir -p '/opt/$my_app/etc'" | ||||
| sudo mkdir -p "/opt/$my_app/etc/" | ||||
| 
 | ||||
| set +e | ||||
| #https://git.coolaj86.com/coolaj86/telebit-relay.js.git | ||||
| @ -173,17 +172,17 @@ if [ -z "$(cat /etc/passwd | grep $my_user)" ]; then | ||||
|   sudo adduser --home $TELEBIT_RELAY_PATH --gecos '' --disabled-password $my_user >/dev/null 2>&1 | ||||
| fi | ||||
| 
 | ||||
| if [ ! -f "$TELEBIT_RELAY_PATH/etc/$my_app.yml" ]; then | ||||
| if [ ! -f "/opt/$my_app/etc/$my_app.yml" ]; then | ||||
|   echo "### Creating config file from template. sudo may be required" | ||||
|   #echo "sudo rsync -a examples/$my_app.yml $TELEBIT_RELAY_PATH/etc/$my_app.yml" | ||||
|   sudo bash -c "echo 'email: $my_email' >> $TELEBIT_RELAY_PATH/etc/$my_app.yml" | ||||
|   sudo bash -c "echo 'secret: $my_secret' >> $TELEBIT_RELAY_PATH/etc/$my_app.yml" | ||||
|   sudo bash -c "echo 'servernames: [ $my_servername ]' >> $TELEBIT_RELAY_PATH/etc/$my_app.yml" | ||||
|   sudo bash -c "cat $TELEBIT_RELAY_PATH/examples/$my_app.yml.tpl >> $TELEBIT_RELAY_PATH/etc/$my_app.yml" | ||||
|   #echo "sudo rsync -a examples/$my_app.yml /opt/$my_app/etc/$my_app.yml" | ||||
|   sudo bash -c "echo 'email: $my_email' >> /opt/$my_app/etc/$my_app.yml" | ||||
|   sudo bash -c "echo 'secret: $my_secret' >> /opt/$my_app/etc/$my_app.yml" | ||||
|   sudo bash -c "echo 'servernames: [ $my_servername ]' >> /opt/$my_app/etc/$my_app.yml" | ||||
|   sudo bash -c "cat examples/$my_app.yml.tpl >> /opt/$my_app/etc/$my_app.yml" | ||||
| fi | ||||
| 
 | ||||
| echo "sudo chown -R $my_user '$TELEBIT_RELAY_PATH'" | ||||
| sudo chown -R $my_user "$TELEBIT_RELAY_PATH" | ||||
| echo "sudo chown -R $my_user '$TELEBIT_RELAY_PATH' '/opt/$my_app/etc'" | ||||
| sudo chown -R $my_user "$TELEBIT_RELAY_PATH" "/opt/$my_app/etc" | ||||
| 
 | ||||
| echo "### Adding $my_app is a system service" | ||||
| echo "sudo rsync -a $TELEBIT_RELAY_PATH/dist/etc/systemd/system/$my_app.service /etc/systemd/system/$my_app.service" | ||||
| @ -202,7 +201,7 @@ echo "==============================================" | ||||
| echo "  Privacy Settings in Config" | ||||
| echo "==============================================" | ||||
| echo "" | ||||
| echo "The example config file $TELEBIT_RELAY_PATH/etc/$my_app.yml opts-in to" | ||||
| echo "The example config file /opt/$my_app/etc/$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." | ||||
| @ -219,13 +218,13 @@ echo "==============================================" | ||||
| echo "" | ||||
| echo "Edit the config and restart, if desired:" | ||||
| echo "" | ||||
| echo "    sudo vim $TELEBIT_RELAY_PATH/etc/$my_app.yml" | ||||
| echo "    sudo vim /opt/$my_app/etc/$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 $TELEBIT_RELAY_PATH/etc/$my_app.yml" | ||||
| echo "    $my_app --config /opt/$my_app/etc/$my_app.yml" | ||||
| echo "" | ||||
| sleep 1 | ||||
|  | ||||
| @ -52,7 +52,7 @@ module.exports.create = function (state) { | ||||
|     || redirectHttpsAndClose | ||||
|   ); | ||||
|   state.handleInsecureHttp = function (servername, socket) { | ||||
|     console.log("[handlers] insecure http for '" + servername + "'"); | ||||
|     console.log("handleInsecureHttp('" + servername + "', socket)"); | ||||
|     socket.__my_servername = servername; | ||||
|     state.httpInsecureServer.emit('connection', socket); | ||||
|   }; | ||||
|  | ||||
| @ -2,55 +2,42 @@ | ||||
| 
 | ||||
| var Packer = require('proxy-packer'); | ||||
| 
 | ||||
| module.exports = function pipeWs(servername, service, srv, conn, serviceport) { | ||||
| module.exports = function pipeWs(servername, service, conn, remote, serviceport) { | ||||
|   var browserAddr = Packer.socketToAddr(conn); | ||||
|   var cid = Packer.addrToId(browserAddr); | ||||
|   browserAddr.service = service; | ||||
|   browserAddr.serviceport = serviceport; | ||||
|   browserAddr.name = servername; | ||||
|   conn.tunnelCid = cid; | ||||
|   var rid = Packer.socketToId(srv.upgradeReq.socket); | ||||
|   var rid = Packer.socketToId(remote.upgradeReq.socket); | ||||
| 
 | ||||
|   //if (state.debug) { console.log('[pipeWs] client', cid, '=> remote', rid, 'for', servername, 'via', service); }
 | ||||
| 
 | ||||
|   function sendWs(data, serviceOverride) { | ||||
|     if (srv.ws && (!conn.tunnelClosing || serviceOverride)) { | ||||
|     if (remote.ws && (!conn.tunnelClosing || serviceOverride)) { | ||||
|       try { | ||||
|         if (data && !Buffer.isBuffer(data)) { | ||||
|           data = Buffer.from(JSON.stringify(data)); | ||||
|         } | ||||
|         srv.ws.send(Packer.packHeader(browserAddr, data, serviceOverride), { binary: true }); | ||||
|         if (data) { | ||||
|           srv.ws.send(data, { binary: true }); | ||||
|         } | ||||
|         remote.ws.send(Packer.pack(browserAddr, data, serviceOverride), { binary: true }); | ||||
|         // If we can't send data over the websocket as fast as this connection can send it to us
 | ||||
|         // (or there are a lot of connections trying to send over the same websocket) then we
 | ||||
|         // need to pause the connection for a little. We pause all connections if any are paused
 | ||||
|         // to make things more fair so a connection doesn't get stuck waiting for everyone else
 | ||||
|         // to finish because it got caught on the boundary. Also if serviceOverride is set it
 | ||||
|         // means the connection is over, so no need to pause it.
 | ||||
|         if (!serviceOverride && (srv.pausedConns.length || srv.ws.bufferedAmount > 1024*1024)) { | ||||
|         if (!serviceOverride && (remote.pausedConns.length || remote.ws.bufferedAmount > 1024*1024)) { | ||||
|           // console.log('pausing', cid, 'to allow web socket to catch up');
 | ||||
|           conn.pause(); | ||||
|           srv.pausedConns.push(conn); | ||||
|           remote.pausedConns.push(conn); | ||||
|         } | ||||
|       } catch (err) { | ||||
|         console.warn('[pipeWs] srv', rid, ' => client', cid, 'error sending websocket message', err); | ||||
|         console.warn('[pipeWs] remote', rid, ' => client', cid, 'error sending websocket message', err); | ||||
|       } | ||||
|     } | ||||
|   } | ||||
| 
 | ||||
|   srv.clients[cid] = conn; | ||||
|   conn.servername = servername; | ||||
|   conn.serviceport = serviceport; | ||||
|   conn.service = service; | ||||
|   remote.clients[cid] = conn; | ||||
| 
 | ||||
|   // send peek at data too?
 | ||||
|   srv.ws.send(Packer.packHeader(browserAddr, null, 'connection'), { binary: true }); | ||||
| 
 | ||||
|   // TODO convert to read stream?
 | ||||
|   conn.on('data', function (chunk) { | ||||
|     //if (state.debug) { console.log('[pipeWs] client', cid, ' => srv', rid, chunk.byteLength, 'bytes'); }
 | ||||
|     //if (state.debug) { console.log('[pipeWs] client', cid, ' => remote', rid, chunk.byteLength, 'bytes'); }
 | ||||
|     sendWs(chunk); | ||||
|   }); | ||||
| 
 | ||||
| @ -61,7 +48,7 @@ module.exports = function pipeWs(servername, service, srv, conn, serviceport) { | ||||
|   conn.on('close', function (hadErr) { | ||||
|     //if (state.debug) { console.log('[pipeWs] client', cid, 'closing'); }
 | ||||
|     sendWs(null, hadErr ? 'error': 'end'); | ||||
|     delete srv.clients[cid]; | ||||
|     delete remote.clients[cid]; | ||||
|   }); | ||||
| 
 | ||||
| }; | ||||
|  | ||||
							
								
								
									
										951
									
								
								lib/relay.js
									
									
									
									
									
								
							
							
						
						
									
										951
									
								
								lib/relay.js
									
									
									
									
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| @ -19,11 +19,6 @@ module.exports.createTcpConnectionHandler = function (state) { | ||||
| 
 | ||||
|     //return;
 | ||||
|     conn.once('data', function (firstChunk) { | ||||
|       var service = 'tcp'; | ||||
|       var servername; | ||||
|       var str; | ||||
|       var m; | ||||
| 
 | ||||
|       conn.pause(); | ||||
|       conn.unshift(firstChunk); | ||||
| 
 | ||||
| @ -36,13 +31,18 @@ module.exports.createTcpConnectionHandler = function (state) { | ||||
|       // defer after return (instead of being in many places)
 | ||||
|       function deferData(fn) { | ||||
|         if (fn) { | ||||
|           state[fn](servername, conn); | ||||
|           state[fn](servername, conn) | ||||
|         } | ||||
|         process.nextTick(function () { | ||||
|           conn.resume(); | ||||
|         }); | ||||
|       } | ||||
| 
 | ||||
|       var service = 'tcp'; | ||||
|       var servername; | ||||
|       var str; | ||||
|       var m; | ||||
| 
 | ||||
|       function tryTls() { | ||||
|         var vhost; | ||||
| 
 | ||||
| @ -76,9 +76,9 @@ module.exports.createTcpConnectionHandler = function (state) { | ||||
|             return; | ||||
|           } | ||||
| 
 | ||||
|           if (state.debug) { console.log("pipeWs(servername, service, deviceLists['" + servername + "'], socket)"); } | ||||
|           if (state.debug) { console.log("pipeWs(servername, service, socket, deviceLists['" + servername + "'])"); } | ||||
|           deferData(); | ||||
|           pipeWs(servername, service, nextDevice, conn, serviceport); | ||||
|           pipeWs(servername, service, conn, nextDevice, serviceport); | ||||
|         } | ||||
| 
 | ||||
|         // TODO don't run an fs check if we already know this is working elsewhere
 | ||||
| @ -90,7 +90,7 @@ module.exports.createTcpConnectionHandler = function (state) { | ||||
|           //return;
 | ||||
|           require('fs').readdir(vhost, function (err, nodes) { | ||||
|             if (state.debug && err) { console.log("VHOST error", err); } | ||||
|             if (err || !nodes) { run(); return; } | ||||
|             if (err) { run(); return; }  | ||||
|             //if (nodes) { deferData('httpsVhost'); return; }
 | ||||
|             deferData('httpsVhost'); | ||||
|           }); | ||||
| @ -131,7 +131,7 @@ module.exports.createTcpConnectionHandler = function (state) { | ||||
|             // HTTP
 | ||||
|             if (Devices.exist(state.deviceLists, servername)) { | ||||
|               deferData(); | ||||
|               pipeWs(servername, service, Devices.next(state.deviceLists, servername), conn, serviceport); | ||||
|               pipeWs(servername, service, conn, Devices.next(state.deviceLists, servername), serviceport); | ||||
|               return; | ||||
|             } | ||||
|             deferData('handleHttp'); | ||||
|  | ||||
| @ -1,6 +1,6 @@ | ||||
| { | ||||
|   "name": "telebit-relay", | ||||
|   "version": "0.20.0", | ||||
|   "version": "0.12.1", | ||||
|   "description": "Friends don't let friends localhost. Expose your bits with a secure connection even from behind NAT, Firewalls, in a box, with a fox, on a train or in a plane... or a Raspberry Pi in your closet. An attempt to create a better localtunnel.me server, a more open ngrok. Uses Automated HTTPS (Free SSL) via ServerName Indication (SNI). Can also tunnel tls and plain tcp.", | ||||
|   "main": "lib/relay.js", | ||||
|   "bin": { | ||||
| @ -43,15 +43,15 @@ | ||||
|     "greenlock": "^2.2.4", | ||||
|     "human-readable-ids": "^1.0.4", | ||||
|     "js-yaml": "^3.11.0", | ||||
|     "jsonwebtoken": "^8.3.0", | ||||
|     "proxy-packer": "^2.0.0", | ||||
|     "jsonwebtoken": "^8.2.1", | ||||
|     "proxy-packer": "^1.4.3", | ||||
|     "recase": "^1.0.4", | ||||
|     "redirect-https": "^1.1.5", | ||||
|     "serve-static": "^1.13.2", | ||||
|     "sni": "^1.0.0", | ||||
|     "ws": "^5.1.1" | ||||
|   }, | ||||
|   "engineStrict": true, | ||||
|   "engineStrict" : true, | ||||
|   "engines": { | ||||
|     "node": "10.2.1" | ||||
|   } | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user