working cleanup
This commit is contained in:
		
							parent
							
								
									de1bea7b60
								
							
						
					
					
						commit
						30d1ce89fe
					
				| @ -3,6 +3,7 @@ | |||||||
| 'use strict'; | 'use strict'; | ||||||
| 
 | 
 | ||||||
| var pkg = require('../package.json'); | var pkg = require('../package.json'); | ||||||
|  | console.log(pkg.name, pkg.version); | ||||||
| 
 | 
 | ||||||
| var url = require('url'); | var url = require('url'); | ||||||
| var remote = require('../remote.js'); | var remote = require('../remote.js'); | ||||||
| @ -37,7 +38,12 @@ function help() { | |||||||
|   process.exit(0); |   process.exit(0); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| if (-1 === confIndex || -1 !== argv.indexOf('-h') || -1 !== argv.indexOf('--help')) { | if (-1 === confIndex) { | ||||||
|  |   confpath = require('path').join(require('os').homedir(), '.config/telebit/telebit.yml'); | ||||||
|  |   console.info('Using default --config "' + confpath + '"'); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | if (-1 !== argv.indexOf('-h') || -1 !== argv.indexOf('--help')) { | ||||||
|   help(); |   help(); | ||||||
| } | } | ||||||
| if (!confpath || /^--/.test(confpath)) { | if (!confpath || /^--/.test(confpath)) { | ||||||
| @ -74,7 +80,6 @@ require('fs').readFile(confpath, 'utf8', function (err, text) { | |||||||
| }); | }); | ||||||
| 
 | 
 | ||||||
| function connectTunnel() { | function connectTunnel() { | ||||||
|   var services = { https: {}, http: {}, tcp: {} }; |  | ||||||
|   state.net = { |   state.net = { | ||||||
|     createConnection: function (info, cb) { |     createConnection: function (info, cb) { | ||||||
|       // data is the hello packet / first chunk
 |       // data is the hello packet / first chunk
 | ||||||
| @ -86,66 +91,17 @@ function connectTunnel() { | |||||||
|     } |     } | ||||||
|   }; |   }; | ||||||
| 
 | 
 | ||||||
|   // 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
 |  | ||||||
|   if (state.config.http) { |  | ||||||
|     Object.keys(state.config.http).forEach(function (hostname) { |  | ||||||
|       if ('*' === hostname) { |  | ||||||
|         state.config.servernames.forEach(function (servername) { |  | ||||||
|           services.https[servername] = state.config.http[hostname]; |  | ||||||
|           services.http[servername] = 'redirect-https'; |  | ||||||
|         }); |  | ||||||
|         return; |  | ||||||
|       } |  | ||||||
|       services.https[hostname] = state.config.http[hostname]; |  | ||||||
|       services.http[hostname] = 'redirect-https'; |  | ||||||
|     }); |  | ||||||
|   } |  | ||||||
|   /* |  | ||||||
|   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; |  | ||||||
|   }); |  | ||||||
|   */ |  | ||||||
|   state.services = services; |  | ||||||
| 
 |  | ||||||
|   Object.keys(services).forEach(function (protocol) { |  | ||||||
|     var subServices = state.services[protocol]; |  | ||||||
|     Object.keys(subServices).forEach(function (hostname) { |  | ||||||
|       console.info('[local proxy]', protocol + '://' + hostname + ' => ' + subServices[hostname]); |  | ||||||
|     }); |  | ||||||
|   }); |  | ||||||
|   console.info(''); |  | ||||||
| 
 |  | ||||||
|   state.greenlock = state.config.greenlock || {}; |   state.greenlock = state.config.greenlock || {}; | ||||||
|  |   if (!state.config.sortingHat) { | ||||||
|  |     state.config.sortingHat = './lib/sorting-hat.js'; | ||||||
|  |   } | ||||||
|  |   state.config.sortingHat = require('path').resolve(__dirname, '..', state.config.sortingHat); | ||||||
|  | 
 | ||||||
|   // TODO Check undefined vs false for greenlock config
 |   // TODO Check undefined vs false for greenlock config
 | ||||||
|   var tun = remote.connect({ |   var tun = remote.connect({ | ||||||
|     relay: state.config.relay |     relay: state.config.relay | ||||||
|   , config: state.config |   , config: state.config | ||||||
|   , sortingHat: state.config.sortingHat || './lib/sorting-hat.js' |   , sortingHat: state.config.sortingHat | ||||||
|   , locals: state.config.servernames |  | ||||||
|   , services: state.services |  | ||||||
|   , net: state.net |   , net: state.net | ||||||
|   , insecure: state.config.relay_ignore_invalid_certificates |   , insecure: state.config.relay_ignore_invalid_certificates | ||||||
|   , token: state.token |   , token: state.token | ||||||
| @ -157,6 +113,7 @@ function connectTunnel() { | |||||||
|     , configDir: state.greenlock.configDir || '~/acme/etc/' |     , configDir: state.greenlock.configDir || '~/acme/etc/' | ||||||
|     // TODO, store: require(state.greenlock.store.name || 'le-store-certbot').create(state.greenlock.store.options || {})
 |     // TODO, store: require(state.greenlock.store.name || 'le-store-certbot').create(state.greenlock.store.options || {})
 | ||||||
|     , approveDomains: function (opts, certs, cb) { |     , approveDomains: function (opts, certs, cb) { | ||||||
|  |         console.log("trying approve domains"); | ||||||
|         // Certs being renewed are listed in certs.altnames
 |         // Certs being renewed are listed in certs.altnames
 | ||||||
|         if (certs) { |         if (certs) { | ||||||
|           opts.domains = certs.altnames; |           opts.domains = certs.altnames; | ||||||
| @ -164,16 +121,22 @@ function connectTunnel() { | |||||||
|           return; |           return; | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         if (-1 !== state.config.servernames.indexOf(opts.domains[0])) { |         // by virtue of the fact that it's being tunneled through a
 | ||||||
|  |         // trusted source that is already checking, we're good
 | ||||||
|  |         //if (-1 !== state.config.servernames.indexOf(opts.domains[0])) {
 | ||||||
|           opts.email = state.greenlock.email || state.config.email; |           opts.email = state.greenlock.email || state.config.email; | ||||||
|           opts.agreeTos = state.greenlock.agree || state.agreeTos; |           opts.agreeTos = state.greenlock.agree || state.agreeTos; | ||||||
|           cb(null, { options: opts, certs: certs }); |           cb(null, { options: opts, certs: certs }); | ||||||
|           return; |           return; | ||||||
|         } |         //}
 | ||||||
|  | 
 | ||||||
|  |         //cb(new Error("servername not found in allowed list"));
 | ||||||
|       } |       } | ||||||
|     } |     } | ||||||
|   }); |   }); | ||||||
| 
 | 
 | ||||||
|  |   require(state.config.sortingHat).print(state.config); | ||||||
|  | 
 | ||||||
|   function sigHandler() { |   function sigHandler() { | ||||||
|     console.log('SIGINT'); |     console.log('SIGINT'); | ||||||
| 
 | 
 | ||||||
| @ -208,7 +171,7 @@ function rawTunnel() { | |||||||
|   if (!state.config.token) { |   if (!state.config.token) { | ||||||
|     var jwt = require('jsonwebtoken'); |     var jwt = require('jsonwebtoken'); | ||||||
|     var tokenData = { |     var tokenData = { | ||||||
|       domains: state.config.servernames |       domains: Object.keys(state.config.servernames).filter(function (name) { return /\./.test(name); }) | ||||||
|     , aud: aud |     , aud: aud | ||||||
|     , iss: Math.round(Date.now() / 1000) |     , iss: Math.round(Date.now() / 1000) | ||||||
|     }; |     }; | ||||||
|  | |||||||
| @ -1,16 +1,185 @@ | |||||||
|  | module.exports.print = function (config) { | ||||||
|  |   var services = { https: {}, http: {}, tcp: {} }; | ||||||
|  |   // 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
 | ||||||
|  |   if (config.http) { | ||||||
|  |     Object.keys(config.http).forEach(function (hostname) { | ||||||
|  |       if ('*' === hostname) { | ||||||
|  |         config.servernames.forEach(function (servername) { | ||||||
|  |           services.https[servername] = config.http[hostname]; | ||||||
|  |           services.http[servername] = 'redirect-https'; | ||||||
|  |         }); | ||||||
|  |         return; | ||||||
|  |       } | ||||||
|  |       services.https[hostname] = config.http[hostname]; | ||||||
|  |       services.http[hostname] = 'redirect-https'; | ||||||
|  |     }); | ||||||
|  |   } | ||||||
|  |   /* | ||||||
|  |   Object.keys(config.localPorts).forEach(function (port) { | ||||||
|  |     var proto = config.localPorts[port]; | ||||||
|  |     if (!proto) { return; } | ||||||
|  |     if ('http' === proto) { | ||||||
|  |       config.servernames.forEach(function (servername) { | ||||||
|  |         services.http[servername] = port; | ||||||
|  |       }); | ||||||
|  |       return; | ||||||
|  |     } | ||||||
|  |     if ('https' === proto) { | ||||||
|  |       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(services).forEach(function (protocol) { | ||||||
|  |     var subServices = services[protocol]; | ||||||
|  |     Object.keys(subServices).forEach(function (hostname) { | ||||||
|  |       console.info('[local proxy]', protocol + '://' + hostname + ' => ' + subServices[hostname]); | ||||||
|  |     }); | ||||||
|  |   }); | ||||||
|  |   console.info(''); | ||||||
|  | }; | ||||||
|  | 
 | ||||||
| module.exports.assign = function (state, tun, cb) { | module.exports.assign = function (state, tun, cb) { | ||||||
|   var net = state.net || require('net'); |   var net = state.net || require('net'); | ||||||
|   var service = tun.service.toLowerCase(); |  | ||||||
|   var portList = state.services[service]; |  | ||||||
|   var port; |  | ||||||
| 
 | 
 | ||||||
|   if (!tun.name && !tun.serviceport) { |   if (!tun.name && !tun.serviceport) { | ||||||
|     console.log('tun:\n',tun); |     console.log('tun:\n',tun); | ||||||
|     //console.warn(tun.data.toString());
 |     //console.warn(tun.data.toString());
 | ||||||
|     cb(new Error("missing routing information for ':tun_id'")); |     cb(new Error("No routing information for ':tun_id'. Missing both 'name' and 'serviceport'.")); | ||||||
|     return; |     return; | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|  |   if (!state.config.servernames) { | ||||||
|  |     state.config.servernames = {}; | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   var handlers = {}; | ||||||
|  |   handlers.http = function (socket) { | ||||||
|  |     if (!state.greenlock) { | ||||||
|  |       state.greenlock = require('greenlock').create(state.greenlockConfig); | ||||||
|  |     } | ||||||
|  |     if (!state.httpRedirectServer) { | ||||||
|  |       state.redirectHttps = require('redirect-https')(); | ||||||
|  |       state.httpRedirectServer = require('http').createServer(state.greenlock.middleware(state.redirectHttps)); | ||||||
|  |     } | ||||||
|  |     state.httpRedirectServer.emit('connection', socket); | ||||||
|  |   }; | ||||||
|  |   handlers.https = function (tlsSocket) { | ||||||
|  |     if (!state.defaultHttpServer) { | ||||||
|  |       state.defaultHttpServer = require('http').createServer(function (req, res) { | ||||||
|  |         console.log('[hit http/s server]'); | ||||||
|  |         res.end('Hello, Encrypted Tunnel World!'); | ||||||
|  |       }); | ||||||
|  |     } | ||||||
|  |     state.defaultHttpServer.emit('connection', tlsSocket); | ||||||
|  |   }; | ||||||
|  | 
 | ||||||
|  |   if ('http' === tun.service || 'https' === tun.service) { | ||||||
|  |     if (!tun.name) { | ||||||
|  |       cb(new Error("No routing information for ':tun_id'. Service '" + tun.service + "' is missing 'name'.")); | ||||||
|  |       return; | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   function redirectHttp(cb) { | ||||||
|  |     var socketPair = require('socket-pair'); | ||||||
|  |     conn = socketPair.create(function (err, other) { | ||||||
|  |       if (err) { cb(err); return; } | ||||||
|  |       handlers.http(other); | ||||||
|  |       cb(null, conn); | ||||||
|  |     }); | ||||||
|  |     //if (tun.data) { conn.write(tun.data); }
 | ||||||
|  |     return conn; | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   var handled; | ||||||
|  | 
 | ||||||
|  |   if ('http' === tun.service) { | ||||||
|  |     // TODO match *.example.com
 | ||||||
|  |     handled = Object.keys(state.config.servernames).some(function (sn) { | ||||||
|  |       if (sn !== tun.name) { return; } | ||||||
|  | 
 | ||||||
|  |       console.log('Found config match for PLAIN', tun.name); | ||||||
|  |       if (!state.config.servernames[sn]) { return; } | ||||||
|  | 
 | ||||||
|  |       if (false === state.config.servernames[sn].terminate) { | ||||||
|  |         cb(new Error("insecure http not supported yet")); | ||||||
|  |         return true; | ||||||
|  |       } | ||||||
|  | 
 | ||||||
|  |       console.log('Redirecting HTPTP for', tun.name); | ||||||
|  |       redirectHttp(cb); | ||||||
|  |       return true; | ||||||
|  |     }); | ||||||
|  |     if (!handled) { | ||||||
|  |       redirectHttp(cb); | ||||||
|  |     } | ||||||
|  |     return; | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   function terminateTls(cb) { | ||||||
|  |     var socketPair = require('socket-pair'); | ||||||
|  |     conn = socketPair.create(function (err, other) { | ||||||
|  |       if (err) { cb(err); return; } | ||||||
|  | 
 | ||||||
|  |       if (!state.greenlock) { | ||||||
|  |         state.greenlock = require('greenlock').create(state.greenlockConfig); | ||||||
|  |       } | ||||||
|  |       if (!state.terminatorServer) { | ||||||
|  |         state.terminatorServer = require('tls').createServer(state.greenlock.tlsOptions, function (tlsSocket) { | ||||||
|  |           console.log('[hit tls server]'); | ||||||
|  |           if (err) { cb(err); return; } | ||||||
|  |           handlers.https(tlsSocket); | ||||||
|  |         }); | ||||||
|  |       } | ||||||
|  | 
 | ||||||
|  |       console.log('[emitting tls connection]'); | ||||||
|  |       state.terminatorServer.emit('connection', other); | ||||||
|  |       cb(null, conn); | ||||||
|  |     }); | ||||||
|  |     //if (tun.data) { conn.write(tun.data); }
 | ||||||
|  |     return conn; | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   if ('https' === tun.service) { | ||||||
|  |     // TODO match *.example.com
 | ||||||
|  |     handled = Object.keys(state.config.servernames).some(function (sn) { | ||||||
|  |       if (sn !== tun.name) { return; } | ||||||
|  | 
 | ||||||
|  |       console.log('Found config match for TLS', tun.name); | ||||||
|  |       if (!state.config.servernames[sn]) { return; } | ||||||
|  | 
 | ||||||
|  |       if (false === state.config.servernames[sn].terminate) { | ||||||
|  |         cb(new Error("insecure http not supported yet")); | ||||||
|  |         return true; | ||||||
|  |       } | ||||||
|  | 
 | ||||||
|  |       console.log('Terminating TLS for', tun.name); | ||||||
|  |       terminateTls(cb); | ||||||
|  |       return true; | ||||||
|  |     }); | ||||||
|  |     if (!handled) { | ||||||
|  |       terminateTls(cb); | ||||||
|  |     } | ||||||
|  |     return; | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   return; | ||||||
|  |   var portList = state.services[service]; | ||||||
|  |   var port; | ||||||
|   port = portList[tun.name]; |   port = portList[tun.name]; | ||||||
|   if (!port) { |   if (!port) { | ||||||
|     // Check for any wildcard domains, sorted longest to shortest so the one with the
 |     // Check for any wildcard domains, sorted longest to shortest so the one with the
 | ||||||
| @ -48,7 +217,7 @@ module.exports.assign = function (state, tun, cb) { | |||||||
|   function handleNow(socket) { |   function handleNow(socket) { | ||||||
|     var httpServer; |     var httpServer; | ||||||
|     var tlsServer; |     var tlsServer; | ||||||
|     if ('https' === service) { |     if ('https' === tun.service) { | ||||||
|       if (!state.greenlock) { |       if (!state.greenlock) { | ||||||
|         state.greenlock = require('greenlock').create(state.greenlockConfig); |         state.greenlock = require('greenlock').create(state.greenlockConfig); | ||||||
|       } |       } | ||||||
| @ -77,9 +246,7 @@ module.exports.assign = function (state, tun, cb) { | |||||||
|     conn = socketPair.create(function (err, other) { |     conn = socketPair.create(function (err, other) { | ||||||
|       if (err) { console.error('[Error] ' + err.message); } |       if (err) { console.error('[Error] ' + err.message); } | ||||||
|       handleNow(other); |       handleNow(other); | ||||||
|       if (createOpts.data) { |       //if (createOpts.data) { conn.write(createOpts.data); }
 | ||||||
|         conn.write(createOpts.data); |  | ||||||
|       } |  | ||||||
|     }); |     }); | ||||||
|     /* |     /* | ||||||
|     var streamPair = require('stream-pair'); |     var streamPair = require('stream-pair'); | ||||||
| @ -96,9 +263,7 @@ module.exports.assign = function (state, tun, cb) { | |||||||
|       // this will happen before 'data' or 'readable' is triggered
 |       // this will happen before 'data' or 'readable' is triggered
 | ||||||
|       // We use the data from the createOpts object so that the createConnection function has
 |       // We use the data from the createOpts object so that the createConnection function has
 | ||||||
|       // the oppurtunity of removing/changing it if it wants/needs to handle it differently.
 |       // the oppurtunity of removing/changing it if it wants/needs to handle it differently.
 | ||||||
|       if (createOpts.data) { |       //if (createOpts.data) { conn.write(createOpts.data); }
 | ||||||
|         conn.write(createOpts.data); |  | ||||||
|       } |  | ||||||
|     }); |     }); | ||||||
|   } |   } | ||||||
|   cb(null, conn); |   cb(null, conn); | ||||||
|  | |||||||
| @ -52,11 +52,11 @@ | |||||||
|     "greenlock": "^2.2.19", |     "greenlock": "^2.2.19", | ||||||
|     "js-yaml": "^3.11.0", |     "js-yaml": "^3.11.0", | ||||||
|     "jsonwebtoken": "^7.1.9", |     "jsonwebtoken": "^7.1.9", | ||||||
|  |     "proxy-packer": "^1.4.3", | ||||||
|     "recase": "^1.0.4", |     "recase": "^1.0.4", | ||||||
|     "redirect-https": "^1.1.5", |     "redirect-https": "^1.1.5", | ||||||
|     "sni": "^1.0.0", |     "sni": "^1.0.0", | ||||||
|     "socket-pair": "^1.0.3", |     "socket-pair": "^1.0.3", | ||||||
|     "proxy-packer": "^1.4.3", |  | ||||||
|     "ws": "^2.2.3" |     "ws": "^2.2.3" | ||||||
|   } |   } | ||||||
| } | } | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user