diff --git a/bin/telebit.js b/bin/telebit.js index 2cd9334..f4d6898 100755 --- a/bin/telebit.js +++ b/bin/telebit.js @@ -9,7 +9,6 @@ var remote = require('../remote.js'); var state = {}; var argv = process.argv.slice(2); -//var Greenlock = require('greenlock'); var confIndex = argv.indexOf('--config'); var confpath; @@ -124,6 +123,8 @@ function connectTunnel() { }); console.info(''); + state.greenlock = state.config.greenlock || {}; + // TODO Check undefined vs false for greenlock config var tun = remote.connect({ relay: state.config.relay , locals: state.config.servernames @@ -131,6 +132,29 @@ function connectTunnel() { , net: state.net , insecure: state.config.relay_ignore_invalid_certificates , token: state.token + , greenlockConfig: { + version: state.greenlock.version || 'draft-11' + , server: state.greenlock.server || 'https://acme-v02.api.letsencrypt.org/directory' + , communityMember: state.greenlock.communityMember || state.config.communityMember + , telemetry: state.greenlock.telemetry || state.config.telemetry + , configDir: state.greenlock.configDir || '~/acme/etc/' + // TODO, store: require(state.greenlock.store.name || 'le-store-certbot').create(state.greenlock.store.options || {}) + , approveDomains: function (opts, certs, cb) { + // Certs being renewed are listed in certs.altnames + if (certs) { + opts.domains = certs.altnames; + cb(null, { options: opts, certs: certs }); + return; + } + + if (-1 !== state.config.servernames.indexOf(opts.domains[0])) { + opts.email = state.greenlock.email || state.config.email; + opts.agreeTos = state.greenlock.agree || state.agreeTos; + cb(null, { options: opts, certs: certs }); + return; + } + } + } }); function sigHandler() { diff --git a/package.json b/package.json index 56c613f..da39646 100644 --- a/package.json +++ b/package.json @@ -49,10 +49,12 @@ "dependencies": { "bluebird": "^3.5.1", "commander": "^2.9.0", + "greenlock": "^2.2.19", "js-yaml": "^3.11.0", "jsonwebtoken": "^7.1.9", "recase": "^1.0.4", "sni": "^1.0.0", + "socket-pair": "^1.0.3", "tunnel-packer": "^1.2.0", "ws": "^2.2.3" } diff --git a/remote.js b/remote.js index 9b592db..02b1dcb 100644 --- a/remote.js +++ b/remote.js @@ -320,14 +320,64 @@ function run(copts) { , remoteAddress: opts.address , remotePort: opts.port }; - var conn = net.createConnection(createOpts, function () { - // this will happen before 'data' or 'readable' is triggered - // 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. - if (createOpts.data) { - conn.write(createOpts.data); + var conn; + + function handleNow(socket) { + var httpServer; + var tlsServer; + if ('https' === service) { + if (!copts.greenlock) { + copts.greenlock = require('greenlock').create(copts.greenlockConfig); + } + httpServer = require('http').createServer(function (req, res) { + console.log('[hit http/s server]'); + res.end('Hello, Encrypted Tunnel World!'); + }); + tlsServer = require('tls').createServer(copts.greenlock.tlsOptions, function (tlsSocket) { + console.log('[hit tls server]'); + httpServer.emit('connection', tlsSocket); + }); + tlsServer.emit('connection', socket); + } else { + httpServer = require('http').createServer(copts.greenlock.middleware(function (req, res) { + console.log('[hit pure http server]'); + res.end('Hello, Encrypted Tunnel World!'); + })); + // http://aj.telebit.cloud/.well-known/acme-challenge/blah + httpServer.emit('connection', socket); } - }); + } + if ('aj.telebit.cloud' === servername) { + console.log('NEW CONNECTION to AJ\'s telebit could'); + // For performance it may be better to use socket-pair, needs testing + var socketPair = require('socket-pair'); + conn = socketPair.create(function (err, other) { + if (err) { console.error('[Error] ' + err.message); } + handleNow(other); + if (createOpts.data) { + conn.write(createOpts.data); + } + }); + /* + var streamPair = require('stream-pair'); + var pair = streamPair.create(); + conn = pair.other; + process.nextTick(function () { + if (createOpts.data) { + conn.write(createOpts.data); + } + }); + */ + } else { + conn = net.createConnection(createOpts, function () { + // this will happen before 'data' or 'readable' is triggered + // 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. + if (createOpts.data) { + conn.write(createOpts.data); + } + }); + } clientHandlers.add(conn, cid, opts, servername); }