implemented more dynamic HTTP proxying

This commit is contained in:
tigerbot 2017-05-09 14:16:21 -06:00
parent b3b407d161
commit ab31bae6ff
4 changed files with 77 additions and 42 deletions

View File

@ -19,22 +19,7 @@ module.exports.create = function (deps, config) {
var secureContexts = {};
var tunnelAdminTlsOpts = {};
var tls = require('tls');
function domainMatches(pattern, servername) {
// Everything matches '*'
if (pattern === '*') {
return true;
}
if (/^\*./.test(pattern)) {
// get rid of the leading "*." to more easily check the servername against it
pattern = pattern.slice(2);
return pattern === servername.slice(-pattern.length);
}
// pattern doesn't contains any wildcards, so exact match is required
return pattern === servername;
}
var domainMatches = require('./match-domain').match;
var tcpRouter = {
_map: { }

17
lib/match-domain.js Normal file
View File

@ -0,0 +1,17 @@
'use strict';
module.exports.match = function (pattern, servername) {
// Everything matches '*'
if (pattern === '*') {
return true;
}
if (/^\*./.test(pattern)) {
// get rid of the leading "*." to more easily check the servername against it
pattern = pattern.slice(2);
return pattern === servername.slice(-pattern.length);
}
// pattern doesn't contains any wildcards, so exact match is required
return pattern === servername;
};

View File

@ -1,34 +1,66 @@
'use strict';
module.exports.create = function (deps, conf) {
// This should be able to handle things like default web path (i.e. /srv/www/hostname),
// no-www redirect, and transpilation of static assets (i.e. cached versions of raw html)
// but right now it's a very dumb proxy
var app = require('express')();
var domainMatches = require('../match-domain').match;
function createConnection(conn) {
var opts = conn.__opts;
var newConn = deps.net.createConnection({
port: conf.http.proxy.port
, host: '127.0.0.1'
// We handle both HTTPS and HTTP traffic on the same ports, and we want to redirect
// any unencrypted requests to the same port they came from unless it came in on
// the default HTTP port, in which case there wont be a port specified in the host.
var redirecters = {};
function redirectHttps(req, res, next) {
var port = req.headers.host.split(':')[1];
var redirecter = redirecters[port];
if (!redirecter) {
redirecter = redirecters[port] = require('redirect-https')({port: port});
}
redirecter(req, res, next);
}
, servername: opts.servername
, data: opts.data
, remoteFamily: opts.family || conn.remoteFamily
, remoteAddress: opts.address || conn.remoteAddress
, remotePort: opts.port || conn.remotePort
}, function () {
//console.log("[=>] first packet from tunneler to '" + cid + "' as '" + opts.service + "'", opts.data.byteLength);
// this will happen before 'data' is triggered
//newConn.write(opts.data);
function respond404(req, res) {
res.writeHead(404);
res.end('Not Found');
}
function createProxyRoute(mod) {
// This is the easiest way to override the createConnections function the proxy
// module uses, but take note the since we don't have control over where this is
// called the extra options availabled will be different.
var agent = new require('http').Agent({});
agent.createConnection = deps.net.createConnection;
var proxy = require('http-proxy').createProxyServer({
agent: agent
, target: 'http://' + mod.address
, xfwd: true
, toProxy: true
});
newConn.pipe(conn);
conn.pipe(newConn);
return function (req, res, next) {
var hostname = req.headers.host.split(':')[0];
var relevant = mod.domains.some(function (pattern) {
return domainMatches(pattern, hostname);
});
if (relevant) {
proxy.web(req, res);
} else {
next();
}
};
}
return {
emit: function (type, conn) {
createConnection(conn);
app.use(redirectHttps);
(conf.http.modules || []).forEach(function (mod) {
if (mod.name === 'proxy') {
app.use(createProxyRoute(mod));
}
};
else {
console.warn('unknown HTTP module', mod);
}
});
app.use(respond404);
return require('http').createServer(app);
};

View File

@ -47,6 +47,7 @@
"finalhandler": "^0.4.0",
"greenlock": "git+https://git.daplie.com/Daplie/node-greenlock.git#master",
"greenlock-express": "git+https://git.daplie.com/Daplie/greenlock-express.git#master",
"http-proxy": "^1.16.2",
"httpolyglot": "^0.1.1",
"ipaddr.js": "git+https://github.com/whitequark/ipaddr.js.git#v1.3.0",
"ipify": "^1.1.0",