'use strict'; module.exports.create = function (deps, config) { if (!config.tunnelServer || !Array.isArray(config.tunnelServer.servernames) || !config.tunnelServer.secret) { return { isAdminDomain: function () { return false; } , isClientDomain: function () { return false; } }; } var tunnelOpts = Object.assign({}, config.tunnelServer); // This function should not be called because connections to the admin domains // should already be decrypted, and connections to non-client domains should never // be given to us in the first place. tunnelOpts.httpsTunnel = function (servername, conn) { console.error('tunnel server received encrypted connection to', servername); conn.end(); }; tunnelOpts.httpsInvalid = tunnelOpts.httpsTunnel; // This function should not be called because ACME challenges should be handled // before admin domain connections are given to us, and the only non-encrypted // client connections that should be given to us are ACME challenges. tunnelOpts.handleHttp = function (servername, conn) { console.error('tunnel server received un-encrypted connection to', servername); conn.end([ 'HTTP/1.1 404 Not Found' , 'Date: ' + (new Date()).toUTCString() , 'Connection: close' , 'Content-Type: text/html' , 'Content-Length: 9' , '' , 'Not Found' ].join('\r\n')); }; tunnelOpts.handleInsecureHttp = tunnelOpts.handleHttp; var tunnelServer = require('stunneld').create(tunnelOpts); var httpServer = require('http').createServer(function (req, res) { // status code 426 = Upgrade Required res.statusCode = 426; res.setHeader('Content-Type', 'application/json'); res.end(JSON.stringify({error: { message: 'Only websockets accepted for tunnel server' }})); }); var wsServer = new (require('ws').Server)({ server: httpServer }); wsServer.on('connection', tunnelServer.ws); return { isAdminDomain: function (domain) { return config.tunnelServer.servernames.indexOf(domain) !== -1; } , handleAdminConn: function (conn) { httpServer.emit('connection', conn); } , isClientDomain: tunnelServer.isClientDomain , handleClientConn: tunnelServer.tcp }; };