check external ips

This commit is contained in:
AJ ONeal 2016-09-13 17:08:08 -06:00
parent 0df58dc2c6
commit 3a1efa7cdf
3 changed files with 206 additions and 78 deletions

View File

@ -2,7 +2,10 @@
var os = require('os'); var os = require('os');
module.exports.find = function () { module.exports.find = function (opts) {
opts = opts || {};
opts.externals = opts.externals || [];
var ifaceMap = os.networkInterfaces(); var ifaceMap = os.networkInterfaces();
var newMap = {}; var newMap = {};
@ -10,7 +13,12 @@ module.exports.find = function () {
var ifaces = ifaceMap[iname]; var ifaces = ifaceMap[iname];
ifaces = ifaces.filter(function (iface) { ifaces = ifaces.filter(function (iface) {
return !iface.internal && !/^fe80/.test(iface.address) && !/^[0:]+$/.test(iface.mac); return opts.externals.some(function (ip) {
if (ip.address === iface.address) {
ip.external = true;
return true;
}
}) || (!iface.internal && !/^fe80/.test(iface.address) && !/^[0:]+$/.test(iface.mac));
}); });
if (!ifaces.length) { if (!ifaces.length) {

View File

@ -39,6 +39,7 @@
"homepage": "https://github.com/Daplie/serve-https#readme", "homepage": "https://github.com/Daplie/serve-https#readme",
"dependencies": { "dependencies": {
"finalhandler": "^0.4.0", "finalhandler": "^0.4.0",
"ipify": "^1.1.0",
"livereload": "^0.4.0", "livereload": "^0.4.0",
"localhost.daplie.com-certificates": "^1.2.0", "localhost.daplie.com-certificates": "^1.2.0",
"minimist": "^1.1.1", "minimist": "^1.1.1",

245
serve.js
View File

@ -1,87 +1,86 @@
#!/usr/bin/env node #!/usr/bin/env node
'use strict'; 'use strict';
var PromiseA = global.Promise; // require('bluebird');
var https = require('https'); var https = require('https');
var http = require('http'); var http = require('http');
var fs = require('fs'); var fs = require('fs');
var path = require('path'); var path = require('path');
var portFallback = 8443;
var insecurePortFallback = 4080;
function showError(err, port) {
if ('EACCES' === err.code) {
console.error(err);
console.warn("You do not have permission to use '" + port + "'.");
console.warn("You can probably fix that by running as Administrator or root.");
}
else if ('EADDRINUSE' === err.code) {
console.warn("Another server is already running on '" + port + "'.");
console.warn("You can probably fix that by rebooting your comupter (or stopping it if you know what it is).");
}
}
function createInsecureServer(port, pubdir, opts) { function createInsecureServer(port, pubdir, opts) {
return new PromiseA(function (resolve) {
var server = http.createServer(); var server = http.createServer();
server.on('error', function (err) { server.on('error', function (err) {
console.error(err); if (opts.errorInsecurePort || opts.manualInsecurePort) {
showError(err, port);
process.exit(1); process.exit(1);
return;
}
opts.errorInsecurePort = err.toString();
return createInsecureServer(insecurePortFallback, pubdir, opts).then(resolve);
}); });
server.on('request', require('redirect-https')({ server.on('request', require('redirect-https')({
port: port port: opts.port
})); }));
server.listen(opts.insecurePort, function () { server.listen(port, function () {
var msg = 'Serving ' + pubdir + ' at http://' + opts.servername; opts.insecurePort = port;
var p = server.address().port; resolve();
if (80 !== p) { });
msg += ':' + p;
}
console.info(msg);
}); });
} }
function createServer(port, pubdir, content, opts) { function createServer(port, pubdir, content, opts) {
return new PromiseA(function (resolve) {
var server = https.createServer(opts); var server = https.createServer(opts);
var app = require('./app'); var app = require('./app');
var directive = { public: pubdir, content: content, livereload: opts.livereload var directive = { public: pubdir, content: content, livereload: opts.livereload
, servername: opts.servername, expressApp: opts.expressApp }; , servername: opts.servername, expressApp: opts.expressApp };
server.on('error', function (err) {
if (opts.errorPort || opts.manualPort) {
showError(err, port);
process.exit(1);
return;
}
opts.errorPort = err.toString();
return createServer(portFallback, pubdir, content, opts).then(resolve);
});
server.listen(port, function () {
opts.port = port;
var livereload = require('livereload'); var livereload = require('livereload');
var server2 = livereload.createServer({ https: opts }); var server2 = livereload.createServer({ https: opts });
server2.watch(pubdir); server2.watch(pubdir);
if (opts.insecurePort) { if ('false' !== opts.insecurePort) {
createInsecureServer(port, pubdir, opts); return createInsecureServer(opts.insecurePort, pubdir, opts).then(resolve);
} else {
resolve();
} }
server.on('error', function (err) {
console.error(err);
process.exit(1);
});
server.listen(port, function () {
var msg = 'Serving ' + pubdir + ' at ';
var httpsUrl = 'https://' + opts.servername;
var p = server.address().port;
if (443 !== p) {
httpsUrl += ':' + p;
}
console.info('');
console.info(msg);
console.info('');
console.info('\t' + httpsUrl);
Object.keys(opts.ifaces).forEach(function (iname) {
var iface = opts.ifaces[iname];
if (iface.ipv4.length) {
console.info('');
console.info(iname + ':');
httpsUrl = 'https://' + iface.ipv4[0].address;
if (443 !== p) {
httpsUrl += ':' + p;
}
console.info('\t' + httpsUrl);
httpsUrl = 'https://[' + iface.ipv6[0].address + ']';
if (443 !== p) {
httpsUrl += ':' + p;
}
if (iface.ipv6.length) {
console.info('\t' + httpsUrl);
}
}
});
console.info('');
}); });
if ('function' === typeof app) { if ('function' === typeof app) {
@ -90,36 +89,54 @@ function createServer(port, pubdir, content, opts) {
app = app.create(directive); app = app.create(directive);
} }
return Promise.resolve(app).then(function (app) { server.on('request', function (req, res) {
server.on('request', app); if ('function' === typeof app) {
app(req, res);
return;
}
res.end('not ready');
});
return PromiseA.resolve(app).then(function (_app) {
app = _app;
});
}); });
} }
module.exports.createServer = createServer; module.exports.createServer = createServer;
function run() { function run() {
var defaultServername = 'localhost.daplie.com';
var minimist = require('minimist'); var minimist = require('minimist');
var argv = minimist(process.argv.slice(2)); var argv = minimist(process.argv.slice(2));
var port = argv.p || argv.port || argv._[0] || 8443; var port = argv.p || argv.port || argv._[0] || 443;
var livereload = argv.livereload; var livereload = argv.livereload;
var pubdir = path.resolve(argv.d || argv._[1] || process.cwd()); var pubdir = path.resolve(argv.d || argv._[1] || process.cwd());
var content = argv.c; var content = argv.c;
var letsencryptHost = argv['letsencrypt-certs']; var letsencryptHost = argv['letsencrypt-certs'];
var tls = require('tls'); var tls = require('tls');
// letsencrypt
var email = argv.email;
var agreeTos = argv.agreeTos || argv['agree-tos'];
var cert = require('localhost.daplie.com-certificates'); var cert = require('localhost.daplie.com-certificates');
var opts = { var opts = {
ifaces: require('./local-ip.js').find() key: cert.key
, key: cert.key
, cert: cert.cert , cert: cert.cert
//, ca: cert.ca //, ca: cert.ca
, SNICallback: function (servername, cb) {
cb(null, tls.createSecureContext(opts)); , email: email
return; , agreeTos: agreeTos
}
}; };
var peerCa; var peerCa;
opts.SNICallback = function (servername, cb) {
cb(null, tls.createSecureContext(opts));
return;
};
if (letsencryptHost) { if (letsencryptHost) {
argv.key = argv.key || '/etc/letsencrypt/live/' + letsencryptHost + '/privkey.pem'; argv.key = argv.key || '/etc/letsencrypt/live/' + letsencryptHost + '/privkey.pem';
argv.cert = argv.cert || '/etc/letsencrypt/live/' + letsencryptHost + '/fullchain.pem'; argv.cert = argv.cert || '/etc/letsencrypt/live/' + letsencryptHost + '/fullchain.pem';
@ -174,18 +191,120 @@ function run() {
} }
} }
opts.servername = 'localhost.daplie.com'; opts.servername = defaultServername;
if (argv.servername) { if (argv.servername) {
opts.servername = argv.servername; opts.servername = argv.servername;
} }
opts.insecurePort = argv.i || argv['insecure-port']; if (argv.p || argv.port || argv._[0]) {
opts.manualPort = true;
}
if (argv.i || argv['insecure-port']) {
opts.manualInsecurePort = true;
}
opts.insecurePort = argv.i || argv['insecure-port'] || 80;
opts.livereload = livereload; opts.livereload = livereload;
if (argv['express-app']) { if (argv['express-app']) {
opts.expressApp = require(path.resolve(process.cwd(), argv['express-app'])); opts.expressApp = require(path.resolve(process.cwd(), argv['express-app']));
} }
createServer(port, pubdir, content, opts); return createServer(port, pubdir, content, opts).then(function () {
var msg;
var p;
var httpsUrl;
var promise;
// Port
msg = 'Serving ' + pubdir + ' at ';
httpsUrl = 'https://' + opts.servername;
p = opts.port;
if (443 !== p) {
httpsUrl += ':' + p;
}
console.info('');
console.info(msg);
console.info('');
console.info('\t' + httpsUrl);
// Insecure Port
p = '';
if (80 !== p) {
p = ':' + opts.insecurePort;
}
msg = '\thttp://' + opts.servername + p + ' (redirecting to https)';
console.info(msg);
console.info('');
if (!(argv.servername && defaultServername !== argv.servername && !(argv.key && argv.cert))) {
// ifaces
opts.ifaces = require('./local-ip.js').find();
promise = PromiseA.resolve();
} else {
console.info("Attempting to resolve external connection for '" + argv.servername + "'");
try {
promise = require('./match-ips.js').match(argv.servername, opts);
} catch(e) {
console.warn("Upgrade to version 2.x to use automatic certificate issuance for '" + argv.servername + "'");
promise = PromiseA.resolve();
}
}
return promise.then(function (matchingIps) {
if (matchingIps) {
if (!matchingIps.length) {
console.log("Neither the attached nor external interfaces match '" + argv.servername + "'");
}
opts.matchingIps = matchingIps || [];
}
if (opts.matchingIps.length) {
console.info('');
console.info('External IPs:');
console.info('');
opts.matchingIps.forEach(function (ip) {
if ('IPv4' === ip.family) {
httpsUrl = 'https://' + ip.address;
if (443 !== opts.port) {
httpsUrl += ':' + opts.port;
}
console.info('\t' + httpsUrl);
}
else {
httpsUrl = 'https://[' + ip.address + ']';
if (443 !== opts.port) {
httpsUrl += ':' + opts.port;
}
console.info('\t' + httpsUrl);
}
});
}
Object.keys(opts.ifaces).forEach(function (iname) {
var iface = opts.ifaces[iname];
if (iface.ipv4.length) {
console.info('');
console.info(iname + ':');
httpsUrl = 'https://' + iface.ipv4[0].address;
if (443 !== opts.port) {
httpsUrl += ':' + opts.port;
}
console.info('\t' + httpsUrl);
httpsUrl = 'https://[' + iface.ipv6[0].address + ']';
if (443 !== opts.port) {
httpsUrl += ':' + opts.port;
}
if (iface.ipv6.length) {
console.info('\t' + httpsUrl);
}
}
});
console.info('');
});
});
} }
if (require.main === module) { if (require.main === module) {