From 54fe53dbfb7ec0f9a84952eb65e38d1198077c7e Mon Sep 17 00:00:00 2001 From: AJ ONeal Date: Thu, 4 May 2017 23:09:56 -0600 Subject: [PATCH] removed letsencrypt and other --- boot/local-server.js | 59 ---------- boot/master.js | 40 +------ boot/worker.js | 271 ++++++++++++++----------------------------- lib/main.js | 99 +--------------- lib/master.js | 16 ++- lib/sni-server.js | 58 --------- lib/spawn-caddy.js | 159 ------------------------- lib/worker.js | 13 +-- walnut.js | 8 +- 9 files changed, 116 insertions(+), 607 deletions(-) delete mode 100644 boot/local-server.js delete mode 100644 lib/sni-server.js delete mode 100644 lib/spawn-caddy.js diff --git a/boot/local-server.js b/boot/local-server.js deleted file mode 100644 index ae203ee..0000000 --- a/boot/local-server.js +++ /dev/null @@ -1,59 +0,0 @@ -'use strict'; - -// Note the odd use of callbacks (instead of promises) here -// It's to avoid loading bluebird yet (see sni-server.js for explanation) -module.exports.create = function (lex, certPaths, port, conf, serverCallback) { - function initServer(err, server) { - var app; - var promiseApp; - - if (err) { - serverCallback(err); - return; - } - - server.on('error', serverCallback); - server.listen(port, function () { - // is it even theoritically possible for - // a request to come in before this callback has fired? - // I'm assuming this event must fire before any request event - promiseApp = serverCallback(null, server); - }); - /* - server.listen(port, '::::', function () { - // is it even theoritically possible for - // a request to come in before this callback has fired? - // I'm assuming this event must fire before any request event - promiseApp = serverCallback(null, server); - }); - */ - - // Get up and listening as absolutely quickly as possible - function onRequest(req, res) { - // this is a hot piece of code, so we cache the result - if (app) { - app(req, res); - return; - } - - promiseApp.then(function (_app) { - console.log('[Server]', req.method, req.host || req.headers['x-forwarded-host'] || req.headers.host, req.url); - app = _app; - app(req, res); - }); - } - - if (lex) { - var LEX = require('letsencrypt-express'); - server.on('request', LEX.createAcmeResponder(lex, onRequest)); - } else { - server.on('request', onRequest); - } - } - - if (certPaths) { - require('../lib/sni-server').create(lex, certPaths, initServer); - } else { - initServer(null, require('http').createServer()); - } -}; diff --git a/boot/master.js b/boot/master.js index 7a97b83..495732c 100644 --- a/boot/master.js +++ b/boot/master.js @@ -29,39 +29,17 @@ var walnut = tryConf( path.join('..', '..', 'config.walnut') , { externalPort: 443 , externalInsecurePort: 80 - , certspath: path.join(__dirname, '..', '..', 'certs', 'live') } ); -var caddy = tryConf( - path.join('..', '..', 'config.caddy') -, { conf: path.join(__dirname, '..', '..', 'Caddyfile') - , bin: null // '/usr/local/bin/caddy' - , sitespath: null // path.join(__dirname, 'sites-enabled') - , locked: false // true - } -); -var letsencrypt = tryConf( - path.join('..', '..', 'config.letsencrypt') -, { configDir: path.join(__dirname, '..', '..', 'letsencrypt') - , email: null - , agreeTos: false - } -); -var useCaddy = caddy.bin && require('fs').existsSync(caddy.bin); + var info = { type: 'walnut.init' , conf: { - protocol: useCaddy ? 'http' : 'https' - , externalPort: walnut.externalPort - , externalPortInsecure: walnut.externalInsecurePort // TODO externalInsecurePort - , localPort: walnut.localPort || (useCaddy ? 4080 : 443) // system / local network - , insecurePort: walnut.insecurePort || (useCaddy ? 80 : 80) // meh - , certPaths: useCaddy ? null : [ - walnut.certspath - , path.join(letsencrypt.configDir, 'live') - ] - , trustProxy: useCaddy ? true : false - , lexConf: letsencrypt + protocol: 'http' + , externalPort: walnut.externalPort || 443 + , externalPortInsecure: walnut.externalInsecurePort || 80 // TODO externalInsecurePort + , localPort: walnut.localPort || 4080 // system / local network + , trustProxy: true , varpath: path.join(__dirname, '..', '..', 'var') , etcpath: path.join(__dirname, '..', '..', 'etc') } @@ -79,11 +57,6 @@ cluster.on('online', function (worker) { if (state.firstRun) { state.firstRun = false; - if (useCaddy) { - caddy = require('../lib/spawn-caddy').create(caddy); - // relies on { localPort, locked } - caddy.spawn(caddy); - } // TODO dyndns in master? } @@ -94,7 +67,6 @@ cluster.on('online', function (worker) { return; } - state.caddy = caddy; state.workers = workers; // calls init if init has not been called require('../lib/master').touch(info.conf, state).then(function (newConf) { diff --git a/boot/worker.js b/boot/worker.js index 8a599fb..3b1223a 100644 --- a/boot/worker.js +++ b/boot/worker.js @@ -1,168 +1,15 @@ 'use strict'; -module.exports.create = function (opts) { +module.exports.create = function () { var id = '0'; var promiseApp; - function createAndBindInsecure(lex, conf, getOrCreateHttpApp) { - // TODO conditional if 80 is being served by caddy - - var appPromise = null; - var app = null; - var http = require('http'); - var insecureServer = http.createServer(); - - function onRequest(req, res) { - if (app) { - app(req, res); - return; - } - - if (!appPromise) { - res.setHeader('Content-Type', 'application/json; charset=utf-8'); - res.end('{ "error": { "code": "E_SANITY_FAIL", "message": "should have an express app, but didn\'t" } }'); - return; - } - - appPromise.then(function (_app) { - appPromise = null; - app = _app; - app(req, res); - }); - } - - insecureServer.listen(conf.insecurePort, function () { - console.info("#" + id + " Listening on http://" - + insecureServer.address().address + ":" + insecureServer.address().port, '\n'); - appPromise = getOrCreateHttpApp(null, insecureServer); - - if (!appPromise) { - throw new Error('appPromise returned nothing'); - } - }); - - insecureServer.on('request', onRequest); - } - - function walkLe(domainname) { - var PromiseA = require('bluebird'); - if (!domainname) { - return PromiseA.reject(new Error('no domainname given for walkLe')); - } - var fs = PromiseA.promisifyAll(require('fs')); - var path = require('path'); - var parts = domainname.split('.'); //.replace(/^www\./, '').split('.'); - var configname = parts.join('.') + '.json'; - var configpath = path.join(__dirname, '..', '..', 'config', configname); - - if (parts.length < 2) { - return PromiseA.resolve(null); - } - - // TODO configpath a la varpath - return fs.readFileAsync(configpath, 'utf8').then(function (text) { - var data = JSON.parse(text); - data.name = configname; - return data; - }, function (/*err*/) { - parts.shift(); - return walkLe(parts.join('.')); - }); - } - - function createLe(lexConf, conf) { - var LEX = require('letsencrypt-express'); - var lex = LEX.create({ - configDir: lexConf.configDir // i.e. __dirname + '/letsencrypt.config' - , approveRegistration: function (hostname, cb) { - // TODO cache/report unauthorized - if (!hostname) { - cb(new Error("[lex.approveRegistration] undefined hostname"), null); - return; - } - - walkLe(hostname).then(function (leAuth) { - // TODO should still check dns for hostname (and mx for email) - if (leAuth && leAuth.email && leAuth.agreeTos) { - cb(null, { - domains: [hostname] // TODO handle www and bare on the same cert - , email: leAuth.email - , agreeTos: leAuth.agreeTos - }); - } - else { - // TODO report unauthorized - cb(new Error("Valid LetsEncrypt config with email and agreeTos not found for '" + hostname + "'"), null); - } - }); - /* - letsencrypt.getConfig({ domains: [domain] }, function (err, config) { - if (!(config && config.checkpoints >= 0)) { - cb(err, null); - return; - } - - cb(null, { - email: config.email - // can't remember which it is, but the pyconf is different that the regular variable - , agreeTos: config.tos || config.agree || config.agreeTos - , server: config.server || LE.productionServerUrl - , domains: config.domains || [domain] - }); - }); - */ - } - }); - conf.letsencrypt = lex.letsencrypt; - conf.lex = lex; - conf.walkLe = walkLe; - - return lex; - } - - function createAndBindServers(conf, getOrCreateHttpApp) { - var lex; - - if (conf.lexConf) { - lex = createLe(conf.lexConf, conf); - } - - // NOTE that message.conf[x] will be overwritten when the next message comes in - require('./local-server').create(lex, conf.certPaths, conf.localPort, conf, function (err, webserver) { - if (err) { - console.error('[ERROR] worker.js'); - console.error(err.stack); - throw err; - } - - console.info("#" + id + " Listening on " + conf.protocol + "://" + webserver.address().address + ":" + webserver.address().port, '\n'); - - // we don't need time to pass, just to be able to return - process.nextTick(function () { - createAndBindInsecure(lex, conf, getOrCreateHttpApp); - }); - - // we are returning the promise result to the caller - return getOrCreateHttpApp(null, null, webserver, conf); - }); - } - // // Worker Mode // - function waitForConfig(realMessage) { - if ('walnut.init' !== realMessage.type) { - console.warn('[Worker] 0 got unexpected message:'); - console.warn(realMessage); - return; - } - - var conf = realMessage.conf; - process.removeListener('message', waitForConfig); - + function createAndBind(conf) { // NOTE: this callback must return a promise for an express app - - function getExpressApp(err, insecserver, webserver/*, newMessage*/) { + function getOrCreateHttpApp(err, insecserver, webserver/*, newMessage*/) { var PromiseA = require('bluebird'); if (promiseApp) { @@ -198,41 +45,93 @@ module.exports.create = function (opts) { return promiseApp; } - createAndBindServers(conf, getExpressApp); - } - - // - // Standalone Mode - // - if (opts) { - // NOTE: this callback must return a promise for an express app - createAndBindServers(opts, function (err, insecserver, webserver/*, conf*/) { - var PromiseA = require('bluebird'); - - if (promiseApp) { - return promiseApp; + function serverCallback(err, webserver) { + if (err) { + console.error('[ERROR] worker.js'); + console.error(err.stack); + throw err; } - promiseApp = new PromiseA(function (resolve) { - opts.getConfig(function (srvmsg) { - resolve(require('../lib/worker').create(webserver, srvmsg)); - }); - }).then(function (app) { - console.info('[Standalone Ready]'); - return app; - }); + console.info("#" + id + " Listening on " + conf.protocol + "://" + webserver.address().address + ":" + webserver.address().port, '\n'); - return promiseApp; - }); - } else { - // we are in cluster mode, as opposed to standalone mode - id = require('cluster').worker.id.toString(); - // We have to wait to get the configuration from the master process - // before we can start our webserver - console.info('[Worker #' + id + '] online!'); - process.on('message', waitForConfig); + // we are returning the promise result to the caller + return getOrCreateHttpApp(null, null, webserver, conf); + } + + // Note the odd use of callbacks (instead of promises) here + // It's to avoid loading bluebird yet (see sni-server.js for explanation) + function localServerCreate(port) { + function initServer(err, server) { + var app; + var promiseApp; + + if (err) { + serverCallback(err); + return; + } + + server.on('error', serverCallback); + server.listen(port, function () { + // is it even theoritically possible for + // a request to come in before this callback has fired? + // I'm assuming this event must fire before any request event + promiseApp = serverCallback(null, server); + }); + /* + server.listen(port, '::::', function () { + // is it even theoritically possible for + // a request to come in before this callback has fired? + // I'm assuming this event must fire before any request event + promiseApp = serverCallback(null, server); + }); + */ + + // Get up and listening as absolutely quickly as possible + function onRequest(req, res) { + // this is a hot piece of code, so we cache the result + if (app) { + app(req, res); + return; + } + + promiseApp.then(function (_app) { + console.log('[Server]', req.method, req.host || req.headers['x-forwarded-host'] || req.headers.host, req.url); + app = _app; + app(req, res); + }); + } + + server.on('request', onRequest); + } + + initServer(null, require('http').createServer()); + } + + // NOTE that message.conf[x] will be overwritten when the next message comes in + localServerCreate(conf.localPort); } + function waitForConfig(realMessage) { + console.log('realMessage', realMessage); + if ('walnut.init' !== realMessage.type) { + console.warn('[Worker] 0 got unexpected message:'); + console.warn(realMessage); + return; + } + + var conf = realMessage.conf; + process.removeListener('message', waitForConfig); + + createAndBind(conf); + } + + // we are in cluster mode, as opposed to standalone mode + id = require('cluster').worker.id.toString(); + // We have to wait to get the configuration from the master process + // before we can start our webserver + console.info('[Worker #' + id + '] online!'); + process.on('message', waitForConfig); + // // Debugging // diff --git a/lib/main.js b/lib/main.js index 0f4d708..ee74a48 100644 --- a/lib/main.js +++ b/lib/main.js @@ -13,54 +13,8 @@ module.exports.create = function (app, xconfx, apiFactories, apiDeps) { var CORS; var cors; - function redirectHttpsHelper(req, res) { - var host = req.hostname || req.headers.host || ''; - var url = req.url; - - // TODO - // allow exceptions for the case of arduino and whatnot that cannot handle https? - // http://evothings.com/is-it-possible-to-secure-micro-controllers-used-within-iot/ - // needs ECDSA? - - var escapeHtml = require('escape-html'); - var newLocation = 'https://' - + host.replace(/:\d+/, ':' + xconfx.externalPort) + url - ; - var safeLocation = escapeHtml(newLocation); - - var metaRedirect = '' - + '\n' - + '\n' - + ' \n' - + ' \n' - + '\n' - + '\n' - + '

You requested an insecure resource. Please use this instead: \n' - + ' ' + safeLocation + '

\n' - + '\n' - + '\n' - ; - - // DO NOT HTTP REDIRECT - /* - res.setHeader('Location', newLocation); - res.statusCode = 302; - */ - - // BAD NEWS BEARS - // - // When people are experimenting with the API and posting tutorials - // they'll use cURL and they'll forget to prefix with https:// - // If we allow that, then many users will be sending private tokens - // and such with POSTs in clear text and, worse, it will work! - // To minimize this, we give browser users a mostly optimal experience, - // but people experimenting with the API get a message letting them know - // that they're doing it wrong and thus forces them to ensure they encrypt. - res.setHeader('Content-Type', 'text/html; charset=utf-8'); - res.end(metaRedirect); - } - function redirectSetup(reason, req, res/*, next*/) { + console.log('xconfx', xconfx); var url = 'https://cloud.' + xconfx.primaryDomain; if (443 !== xconfx.externalPort) { @@ -74,48 +28,6 @@ module.exports.create = function (app, xconfx, apiFactories, apiDeps) { res.end(); } - function redirectHttps(req, res) { - if (localCache.le[req.hostname]) { - if (localCache.le[req.hostname].conf) { - redirectHttpsHelper(req, res); - return; - } - else { - // TODO needs IPC to expire cache - redirectSetup(req.hostname, req, res); - return; - /* - if (Date.now() - localCache.le[req.hostname].createdAt < (5 * 60 * 1000)) { - // TODO link to dbconf.primaryDomain - res.send({ error: { message: "Security Error: Encryption for '" + req.hostname + "' has not been configured." - + " Please use the management interface to set up ACME / Let's Encrypt (or another solution)." } }); - return; - } - */ - } - } - - return xconfx.walkLe(req.hostname).then(function (leAuth) { - if (!leAuth) { - redirectSetup(req.hostname, req, res); - return; - } - - localCache.le[req.hostname] = { conf: leAuth, createdAt: Date.now() }; - redirectHttps(req, res); - }, function (err) { - console.error('[Error] lib/main.js walkLe'); - if (err.stack) { - console.error(err.stack); - } - else { - console.error(new Error('getstack').stack); - console.error(err); - } - res.send({ error: { message: "failed to get tls certificate for '" + (req.hostname || '') + "'" } }); - }); - } - function disallowSymLinks(req, res) { res.end( "Symbolic Links are not supported on all platforms and are therefore disallowed." @@ -245,15 +157,6 @@ module.exports.create = function (app, xconfx, apiFactories, apiDeps) { var appIdParts = appId.split('#'); var appIdPart; - if (!req.secure) { - // did not come from https - if (/\.(appcache|manifest)\b/.test(req.url)) { - require('./unbrick-appcache').unbrick(req, res); - return; - } - return redirectHttps(req, res); - } - // TODO configuration for allowing www if (/^www\./.test(req.hostname)) { // NOTE: acme responder and appcache unbricker must come before scrubTheDub diff --git a/lib/master.js b/lib/master.js index 916f1a6..ca78a57 100644 --- a/lib/master.js +++ b/lib/master.js @@ -2,17 +2,27 @@ var cluster = require('cluster'); var PromiseA = require('bluebird'); +var path = require('path'); +var os = require('os'); function init(conf, state) { var newConf = {}; + + function rand(n) { + var HEX = 16; + var BASE_36 = 36; + var rnd = require('crypto').randomBytes(n || 16).toString('hex'); + return parseInt(rnd, HEX).toString(BASE_36); + } + if (!conf.ipcKey) { - conf.ipcKey = newConf.ipcKey = require('crypto').randomBytes(16).toString('base64'); + conf.ipcKey = newConf.ipcKey = rand(16); } if (!conf.sqlite3Sock) { - conf.sqlite3Sock = newConf.sqlite3Sock = '/tmp/sqlite3.' + require('crypto').randomBytes(4).toString('hex') + '.sock'; + conf.sqlite3Sock = newConf.sqlite3Sock = path.join(os.tmpdir(), 'sqlite3.' + rand(8) + '.sock'); } if (!conf.memstoreSock) { - conf.memstoreSock = newConf.memstoreSock = '/tmp/memstore.' + require('crypto').randomBytes(4).toString('hex') + '.sock'; + conf.memstoreSock = newConf.memstoreSock = path.join(os.tmpdir(), 'memstore.' + rand(8) + '.sock'); } try { diff --git a/lib/sni-server.js b/lib/sni-server.js deleted file mode 100644 index e1c48e4..0000000 --- a/lib/sni-server.js +++ /dev/null @@ -1,58 +0,0 @@ -'use strict'; - -// Note the odd use of callbacks here. -// We're targetting low-power platforms and so we're trying to -// require everything as lazily as possible until our server -// is actually listening on the socket. Bluebird is heavy. -// Even the built-in modules can take dozens of milliseconds to require -module.exports.create = function (lex, certPaths, serverCallback) { - // Recognize that this secureContexts cache is local to this CPU core - var secureContexts = {}; - var ciphers = 'ECDH+AESGCM:DH+AESGCM:ECDH+AES128:DH+AES:ECDH+3DES:DH+3DES:RSA+AESGCM:RSA+AES:RSA+3DES:!aNULL:!MD5:!DSS:!AES256'; - - function createSecureServer() { - var domainname = 'www.example.com'; - var fs = require('fs'); - var secureOpts = { - // TODO create backup file just in case this one is ever corrupted - // NOTE synchronous is faster in this case of initialization - // NOTE certsPath[0] must be the default (LE) directory (another may be used for OV and EV certs) - key: fs.readFileSync(certPaths[0] + '/' + domainname + '/privkey.pem', 'ascii') - , cert: fs.readFileSync(certPaths[0] + '/' + domainname + '/fullchain.pem', 'ascii') - // https://hynek.me/articles/hardening-your-web-servers-ssl-ciphers/ - // https://nodejs.org/api/tls.html - // removed :ECDH+AES256:DH+AES256 and added :!AES256 because AES-256 wastes CPU - , ciphers: ciphers - , honorCipherOrder: true - }; - - secureContexts['www.example.com'] = require('tls').createSecureContext(secureOpts); - secureContexts['example.com'] = secureContexts['www.example.com']; - - //SNICallback is passed the domain name, see NodeJS docs on TLS - secureOpts.SNICallback = function (domainname, cb) { - // NOTE: '*.proxyable.*' domains will be truncated - require('./load-certs').load(secureContexts, certPaths, domainname).then(function (context) { - cb(null, context); - }, function (err) { - console.error('[SNI Callback]'); - console.error(err.stack); - cb(err); - }); - }; - - serverCallback(null, require('https').createServer(secureOpts)); - } - - function createLeServer() { - lex.httpsOptions.ciphers = ciphers; - lex.httpsOptions.honorCipherOrder = true; - serverCallback(null, require('https').createServer(lex.httpsOptions)); - } - - if (lex) { - createLeServer(); - } else { - createSecureServer(); - } -}; diff --git a/lib/spawn-caddy.js b/lib/spawn-caddy.js deleted file mode 100644 index 195f9d4..0000000 --- a/lib/spawn-caddy.js +++ /dev/null @@ -1,159 +0,0 @@ -'use strict'; - -function tplCaddyfile(caddyConf) { - var contents = []; - - caddyConf.domains.forEach(function (hostname) { - var content = ""; - var pagesname = hostname; - - // TODO prefix - content += "https://" + hostname + " {\n" - + " gzip\n" - + " tls " - + "/srv/walnut/certs/live/" + hostname + "/fullchain.pem " - + "/srv/walnut/certs/live/" + hostname + "/privkey.pem\n" - ; - - if (caddyConf.locked) { - content += " root /srv/walnut/init.public/\n"; - } else { - content += " root " + caddyConf.sitespath + "/" + pagesname + "/\n"; - } - - content += - " proxy /api http://localhost:" + caddyConf.localPort.toString() + " {\n" - + " proxy_header Host {host}\n" - + " proxy_header X-Forwarded-Host {host}\n" - + " proxy_header X-Forwarded-Proto {scheme}\n" - // # TODO internal - + " }\n" - + "}"; - - contents.push(content); - }); - - return contents.join('\n\n'); -} - -module.exports.tplCaddyfile = tplCaddyfile; -module.exports.create = function (caddyConf) { - var spawn = require('child_process').spawn; - var caddyBin = caddyConf.bin; - var caddyfilePath = caddyConf.conf; - // TODO put up a booting / lock screen on boot - // and wait for all to be grabbed from db - // NOTE caddy cannot yet support multiple roots - // (needed for example.com/appname instead of appname.example.com) - var caddy; - var fs = require('fs'); - - // TODO this should be expanded to include proxies a la proxydyn - function writeCaddyfile(caddyConf, cb) { - fs.readdir(caddyConf.sitespath, function (err, nodes) { - if (err) { - if (cb) { - cb(err); - return; - } - console.error('[writeCaddyFile] 0'); - console.error(err.stack); - throw err; - } - - caddyConf.domains = nodes.filter(function (node) { - return /\./.test(node) && !/(^\.)|([\/\:\\])/.test(node); - }); - - var contents = tplCaddyfile(caddyConf); - fs.writeFile(caddyfilePath, contents, 'utf8', function (err) { - if (err) { - if (cb) { - cb(err); - return; - } - console.error('[writeCaddyFile] 1'); - console.error(err.stack); - throw err; - } - - if (cb) { cb(null); } - }); - }); - } - - function spawnCaddy(caddyConf, cb) { - console.log('[CADDY] start'); - writeCaddyfile(caddyfilePath, function (err) { - if (err) { - console.error('[writeCaddyfile]'); - console.error(err.stack); - throw err; - } - if (caddy) { - caddy.kill('SIGUSR1'); - return caddy; - - // TODO caddy.kill('SIGKILL'); if SIGTERM fails - // https://github.com/mholt/caddy/issues/107 - // SIGUSR1 - - //caddy.kill('SIGTERM'); - } - - try { - require('child_process').execSync('killall caddy'); - } catch(e) { - // ignore - // Command failed: killall caddy - // caddy: no process found - } - caddy = spawn(caddyBin, ['-conf', caddyfilePath], { stdio: ['ignore', 'pipe', 'pipe'] }); - caddy.stdout.on('data', function (str) { - console.error('[Caddy]', str.toString('utf8')); - }); - - caddy.stderr.on('data', function (errstr) { - console.error('[Caddy]', errstr.toString('utf8')); - }); - - caddy.on('close', function (code, signal) { - // TODO catch if caddy doesn't exist - console.log('[Caddy]'); - console.log(code, signal); - caddy = null; - setTimeout(function () { - spawnCaddy(caddyConf); - }, 1 * 1000); - }); - - try { - if ('function' === typeof cb) { cb(null, caddy); } - } catch(e) { - console.error('ERROR: [spawn-caddy.js]'); - console.error(e.stack); - } - }); - } - - function sighup() { - if (caddy) { - caddy.kill('SIGUSR1'); - return; - } - - // sudo kill -s SIGUSR1 `cat caddy.pid` - fs.readFileAsync('/srv/walnut/caddy.pid', 'utf8').then(function (pid) { - console.log('[caddy] pid', pid); - caddy = spawn('/bin/kill', ['-s', 'SIGUSR1', pid]); - }); - } - - return { - spawn: spawnCaddy - , update: function (caddyConf) { - return writeCaddyfile(caddyConf, sighup); - } - , sighup: sighup - }; -}; diff --git a/lib/worker.js b/lib/worker.js index 2c606d6..5b73aca 100644 --- a/lib/worker.js +++ b/lib/worker.js @@ -70,11 +70,13 @@ module.exports.create = function (webserver, xconfx, state) { , indices: [ 'createdAt', 'updatedAt' ] } ]; + console.log('config directive', dir); function scopeMemstore(expId) { var scope = expId + '|'; return { getAsync: function (id) { + id = id.replace(/\|/, ); return memstore.getAsync(scope + id); } , setAsync: function (id, data) { @@ -194,20 +196,15 @@ module.exports.create = function (webserver, xconfx, state) { })); app.use('/api', recase); + app.set('trust proxy', ['loopback', 'linklocal', 'uniquelocal']); app.use('/', function (req, res) { - if (!req.secure) { + if (!(req.encrypted || req.secure)) { // did not come from https if (/\.(appcache|manifest)\b/.test(req.url)) { require('./unbrick-appcache').unbrick(req, res); return; } - } - - if (xconfx.lex && /\.well-known\/acme-challenge\//.test(req.url)) { - var LEX = require('letsencrypt-express'); - xconfx.lex.debug = true; - xconfx.acmeResponder = xconfx.acmeResponder || LEX.createAcmeResponder(xconfx.lex/*, next*/); - xconfx.acmeResponder(req, res); + res.end("Connection is not encrypted. That's no bueno or, as we say in Hungarian, nem szabad!"); return; } diff --git a/walnut.js b/walnut.js index 9aea314..eeb2b0f 100644 --- a/walnut.js +++ b/walnut.js @@ -4,6 +4,9 @@ var cluster = require('cluster'); var crypto; var stacks = {}; +function realRandom() { + return parseFloat(('0.' + (parseInt(crypto.randomBytes(8).toString('hex'), 16))).replace(/(^0)|(0$)/g, '')); +} Math.random = function () { var err = new Error("Math.random() was used"); @@ -16,7 +19,8 @@ Math.random = function () { crypto = require('crypto'); } - return parseFloat(('0.' + (parseInt(crypto.randomBytes(8).toString('hex'), 16))).replace(/(^0)|(0$)/g, '')); + Math.random = realRandom; + return realRandom(); }; if (cluster.isMaster) { @@ -26,5 +30,5 @@ if (cluster.isMaster) { alternately we could use this and then check require.main cluster.setupMaster({ exec : "app.js", }); */ - require('./boot/worker').create(null); + require('./boot/worker').create(null, null); }