move ddns client to own service
This commit is contained in:
parent
0869186ced
commit
951c411107
|
@ -44,7 +44,6 @@ cluster.on('online', function (worker) {
|
||||||
, path.join(__dirname, 'letsencrypt', 'live')
|
, path.join(__dirname, 'letsencrypt', 'live')
|
||||||
];
|
];
|
||||||
var info;
|
var info;
|
||||||
conf.ddns = config.ddns;
|
|
||||||
conf.redirects = config.redirects;
|
conf.redirects = config.redirects;
|
||||||
|
|
||||||
console.info('[MASTER] Worker ' + worker.process.pid + ' is online');
|
console.info('[MASTER] Worker ' + worker.process.pid + ' is online');
|
||||||
|
@ -63,7 +62,6 @@ cluster.on('online', function (worker) {
|
||||||
, ipcKey: null
|
, ipcKey: null
|
||||||
// TODO let this load after server is listening
|
// TODO let this load after server is listening
|
||||||
, redirects: config.redirects
|
, redirects: config.redirects
|
||||||
, ddns: config.ddns
|
|
||||||
, 'org.oauth3.consumer': config['org.oauth3.consumer']
|
, 'org.oauth3.consumer': config['org.oauth3.consumer']
|
||||||
, 'org.oauth3.provider': config['org.oauth3.provider']
|
, 'org.oauth3.provider': config['org.oauth3.provider']
|
||||||
, keys: config.keys
|
, keys: config.keys
|
||||||
|
@ -88,13 +86,10 @@ cluster.on('online', function (worker) {
|
||||||
info.conf.sqlite3Sock = conf.sqlite3Sock;
|
info.conf.sqlite3Sock = conf.sqlite3Sock;
|
||||||
// TODO get this from db config instead
|
// TODO get this from db config instead
|
||||||
var config = require('../../config');
|
var config = require('../../config');
|
||||||
info.conf.primaryNameserver = config.ddns.primaryNameserver;
|
|
||||||
info.conf.nameservers = config.ddns.nameservers;
|
|
||||||
// TODO get this from db config instead
|
// TODO get this from db config instead
|
||||||
info.conf.privkey = config.privkey;
|
info.conf.privkey = config.privkey;
|
||||||
info.conf.pubkey = config.pubkey;
|
info.conf.pubkey = config.pubkey;
|
||||||
info.conf.redirects = config.redirects;
|
info.conf.redirects = config.redirects;
|
||||||
info.conf.ddns = config.ddns;
|
|
||||||
worker.send(info);
|
worker.send(info);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,83 +0,0 @@
|
||||||
'use strict';
|
|
||||||
|
|
||||||
var PromiseA = require('bluebird').Promise;
|
|
||||||
var updateIp = require('./helpers/update-ip.js').update;
|
|
||||||
var request = PromiseA.promisifyAll(require('request'));
|
|
||||||
var requestAsync = PromiseA.promisify(require('request'));
|
|
||||||
var upnpForward = require('./helpers/upnp-forward').upnpForward;
|
|
||||||
var pmpForward = require('./helpers/pmp-forward').pmpForward;
|
|
||||||
var loopbackHttps = require('./loopback-https');
|
|
||||||
//var checkip = require('check-ip-address');
|
|
||||||
|
|
||||||
function openPort(ip, port) {
|
|
||||||
if (!/tcp|https|http/.test(port.protocol || 'tcp')) {
|
|
||||||
throw new Error('not yet supported \'' + port.protocol + '\'');
|
|
||||||
}
|
|
||||||
|
|
||||||
if (false === port.testable) {
|
|
||||||
return PromiseA.resolve();
|
|
||||||
}
|
|
||||||
|
|
||||||
return loopbackHttps.create(ip, port.private, port.public).then(function () {
|
|
||||||
console.log('success');
|
|
||||||
}).catch(function (err) {
|
|
||||||
// TODO test err
|
|
||||||
return upnpForward(port).catch(function (err) {
|
|
||||||
console.error('[ERROR] UPnP Port Forward');
|
|
||||||
console.error(err);
|
|
||||||
// TODO test err
|
|
||||||
return pmpForward(port);
|
|
||||||
}).then(function () {
|
|
||||||
return loopbackHttps.create(ip, port.private, port.public);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// 1. update dyndns
|
|
||||||
// 1.5. check ip every 5 min
|
|
||||||
// 2. loopback test on ip for http / https / ssh
|
|
||||||
// 3. if needed: discover gateway, map ports
|
|
||||||
function beacon(hostnames, ports) {
|
|
||||||
// test with
|
|
||||||
// dig -p 53 @redirect-www.org pi.nadal.daplie.com A
|
|
||||||
return updateIp({
|
|
||||||
updater: 'redirect-www.org'
|
|
||||||
, port: 65443
|
|
||||||
, ddns: hostnames.map(function (hostname) {
|
|
||||||
return { "name": hostname /*, "value": ipaddress, "type": "A"*/ };
|
|
||||||
})
|
|
||||||
}).then(function (data) {
|
|
||||||
var promises = [];
|
|
||||||
|
|
||||||
console.log("Updated DynDNS");
|
|
||||||
console.log(data);
|
|
||||||
|
|
||||||
ports.forEach(function (port) {
|
|
||||||
promises.push(openPort(JSON.parse(data)[0].answers[0] || hostname, port));
|
|
||||||
});
|
|
||||||
|
|
||||||
return PromiseA.all(promises);
|
|
||||||
}).then(function () {
|
|
||||||
console.log('opened ports');
|
|
||||||
});
|
|
||||||
|
|
||||||
/*
|
|
||||||
request.getAsync('http://checkip.hellabit.com').spread(function (resp, data) {
|
|
||||||
console.log("External IP is", data);
|
|
||||||
}).then(function () {
|
|
||||||
return upnpForward().catch(function (err) {
|
|
||||||
console.error('ERROR: UPnP failure:');
|
|
||||||
console.error(err);
|
|
||||||
});
|
|
||||||
}).then(function () {
|
|
||||||
return pmpForward().catch(function (err) {
|
|
||||||
console.error('TODO: Notify user that their router is not compatible');
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
// TODO test roundtrip
|
|
||||||
*/
|
|
||||||
}
|
|
||||||
|
|
||||||
//setInterval(beacon, 5 * 60 * 1000);
|
|
||||||
exports.run = beacon;
|
|
|
@ -1,81 +0,0 @@
|
||||||
'use strict';
|
|
||||||
|
|
||||||
var PromiseA = require('bluebird').Promise;
|
|
||||||
var natpmp = require('nat-pmp');
|
|
||||||
var exec = require('child_process').exec;
|
|
||||||
|
|
||||||
exports.pmpForward = function (port) {
|
|
||||||
return new PromiseA(function (resolve, reject) {
|
|
||||||
exec('ip route show default', function (err, stdout, stderr) {
|
|
||||||
var gw;
|
|
||||||
|
|
||||||
if (err || stderr) { reject(err || stderr); return; }
|
|
||||||
|
|
||||||
// default via 192.168.1.1 dev eth0
|
|
||||||
gw = stdout.replace(/^default via (\d+\.\d+\.\d+\.\d+) dev[\s\S]+/m, '$1');
|
|
||||||
console.log('Possible PMP gateway is', gw);
|
|
||||||
|
|
||||||
// create a "client" instance connecting to your local gateway
|
|
||||||
var client = natpmp.connect(gw);
|
|
||||||
|
|
||||||
function setPortForward() {
|
|
||||||
// setup a new port mapping
|
|
||||||
client.portMapping({
|
|
||||||
private: port.private || port.public
|
|
||||||
, public: port.public || port.private
|
|
||||||
, ttl: port.ttl || 0 // 600
|
|
||||||
}, function (err, info) {
|
|
||||||
if (err) {
|
|
||||||
reject(err);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
console.log(info);
|
|
||||||
// {
|
|
||||||
// type: 'tcp',
|
|
||||||
// epoch: 8922109,
|
|
||||||
// private: 22,
|
|
||||||
// public: 2222,
|
|
||||||
// ...
|
|
||||||
// }
|
|
||||||
resolve();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// explicitly ask for the current external IP address
|
|
||||||
setTimeout(function () {
|
|
||||||
client.externalIp(function (err, info) {
|
|
||||||
if (err) throw err;
|
|
||||||
console.log('Current external IP address: %s', info.ip.join('.'));
|
|
||||||
setPortForward();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
function usage() {
|
|
||||||
console.warn("");
|
|
||||||
console.warn("node helpers/pmp-forward [public port] [private port] [ttl]");
|
|
||||||
console.warn("");
|
|
||||||
}
|
|
||||||
|
|
||||||
function run() {
|
|
||||||
var pubPort = parseInt(process.argv[2], 10) || 0;
|
|
||||||
var privPort = parseInt(process.argv[3], 10) || pubPort;
|
|
||||||
var ttl = parseInt(process.argv[4], 10) || 0;
|
|
||||||
var options = { public: pubPort, private: privPort, ttl: ttl };
|
|
||||||
|
|
||||||
if (!pubPort) {
|
|
||||||
usage();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
exports.pmpForward(options).then(function () {
|
|
||||||
console.log('done');
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
if (require.main === module) {
|
|
||||||
run();
|
|
||||||
}
|
|
|
@ -1,90 +0,0 @@
|
||||||
#!/usr/bin/env node
|
|
||||||
'use strict';
|
|
||||||
|
|
||||||
var PromiseA = require('bluebird').Promise;
|
|
||||||
var https = require('https');
|
|
||||||
var fs = PromiseA.promisifyAll(require('fs'));
|
|
||||||
|
|
||||||
module.exports.update = function (opts) {
|
|
||||||
return new PromiseA(function (resolve, reject) {
|
|
||||||
var options;
|
|
||||||
var hostname = opts.hostname || opts.updater;
|
|
||||||
var port = opts.port;
|
|
||||||
var pathname = opts.pathname;
|
|
||||||
var req;
|
|
||||||
|
|
||||||
if (!hostname) {
|
|
||||||
throw new Error('Please specify a DDNS host as opts.hostname');
|
|
||||||
}
|
|
||||||
if (!pathname) {
|
|
||||||
throw new Error('Please specify the api route as opts.pathname');
|
|
||||||
}
|
|
||||||
|
|
||||||
options = {
|
|
||||||
host: hostname
|
|
||||||
, port: port
|
|
||||||
, method: 'POST'
|
|
||||||
, headers: {
|
|
||||||
'Content-Type': 'application/json'
|
|
||||||
}
|
|
||||||
, path: pathname
|
|
||||||
//, auth: opts.auth || 'admin:secret'
|
|
||||||
};
|
|
||||||
|
|
||||||
if (opts.cacert) {
|
|
||||||
if (!Array.isArray(opts.cacert)) {
|
|
||||||
opts.cacert = [opts.cacert];
|
|
||||||
}
|
|
||||||
options.ca = opts.cacert;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (opts.token || opts.jwt) {
|
|
||||||
options.headers.Authorization = 'Bearer ' + (opts.token || opts.jwt);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (false === opts.cacert) {
|
|
||||||
options.rejectUnauthorized = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
options.ca = (options.ca||[]).map(function (str) {
|
|
||||||
if ('string' === typeof str && str.length < 1000) {
|
|
||||||
str = fs.readFileAsync(str);
|
|
||||||
}
|
|
||||||
return str;
|
|
||||||
});
|
|
||||||
|
|
||||||
return PromiseA.all(options.ca).then(function (cas) {
|
|
||||||
options.ca = cas;
|
|
||||||
options.agent = new https.Agent(options);
|
|
||||||
|
|
||||||
req = https.request(options, function(res) {
|
|
||||||
var textData = '';
|
|
||||||
|
|
||||||
res.on('error', function (err) {
|
|
||||||
reject(err);
|
|
||||||
});
|
|
||||||
res.on('data', function (chunk) {
|
|
||||||
textData += chunk.toString();
|
|
||||||
// console.log(chunk.toString());
|
|
||||||
});
|
|
||||||
res.on('end', function () {
|
|
||||||
var err;
|
|
||||||
try {
|
|
||||||
resolve(JSON.parse(textData));
|
|
||||||
} catch(e) {
|
|
||||||
err = new Error("Unparsable Server Response");
|
|
||||||
err.code = 'E_INVALID_SERVER_RESPONSE';
|
|
||||||
err.data = textData;
|
|
||||||
reject(err);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
req.on('error', function (err) {
|
|
||||||
reject(err);
|
|
||||||
});
|
|
||||||
|
|
||||||
req.end(JSON.stringify(opts.ddns, null, ' '));
|
|
||||||
}, reject);
|
|
||||||
});
|
|
||||||
};
|
|
|
@ -1,81 +0,0 @@
|
||||||
'use strict';
|
|
||||||
|
|
||||||
var PromiseA = require('bluebird').Promise;
|
|
||||||
var natUpnp = require('nat-upnp');
|
|
||||||
|
|
||||||
exports.upnpForward = function (port) {
|
|
||||||
return natUpnp.createClient({ timeout: 1800 }).then(function (client) {
|
|
||||||
return client.portMapping({
|
|
||||||
public: port.public,
|
|
||||||
private: port.private || port.public,
|
|
||||||
ttl: port.ttl || 0
|
|
||||||
})/*.then(function () {
|
|
||||||
var promitter = client.getMappings();
|
|
||||||
|
|
||||||
promitter.on('entry', function (entry, i) {
|
|
||||||
console.log('entry', i);
|
|
||||||
console.log(entry);
|
|
||||||
}).then(function (mappings) {
|
|
||||||
console.log('mappings');
|
|
||||||
console.log(mappings);
|
|
||||||
});
|
|
||||||
|
|
||||||
return promitter;
|
|
||||||
})*/;
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
/*
|
|
||||||
client.portUnmapping({
|
|
||||||
public: 80
|
|
||||||
});
|
|
||||||
|
|
||||||
.findGateway().then(function (stuff) {
|
|
||||||
console.log('[a] gateway');
|
|
||||||
console.log(stuff.gateway);
|
|
||||||
console.log('[a] address');
|
|
||||||
console.log(stuff.address);
|
|
||||||
}).then(function () {
|
|
||||||
return client
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
client.getMappings({ local: true }, function(err, results) {
|
|
||||||
console.log('local mappings', results);
|
|
||||||
});
|
|
||||||
|
|
||||||
client.externalIp(function(err, ip) {
|
|
||||||
console.log('ext-ip', ip);
|
|
||||||
});
|
|
||||||
*/
|
|
||||||
|
|
||||||
function usage() {
|
|
||||||
console.warn("");
|
|
||||||
console.warn("node helpers/upnp-forward [public port] [private port] [ttl]");
|
|
||||||
console.warn("");
|
|
||||||
}
|
|
||||||
|
|
||||||
function run() {
|
|
||||||
var pubPort = parseInt(process.argv[2], 10) || 0;
|
|
||||||
var privPort = parseInt(process.argv[3], 10) || pubPort;
|
|
||||||
var ttl = parseInt(process.argv[4], 10) || 0;
|
|
||||||
var options = { public: pubPort, private: privPort, ttl: ttl };
|
|
||||||
|
|
||||||
if (!pubPort) {
|
|
||||||
usage();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
exports.upnpForward(options).then(function () {
|
|
||||||
console.log('done');
|
|
||||||
}).catch(function (err) {
|
|
||||||
console.error('ERROR');
|
|
||||||
console.error(err);
|
|
||||||
throw err;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
if (require.main === module) {
|
|
||||||
run();
|
|
||||||
return;
|
|
||||||
}
|
|
|
@ -1,124 +0,0 @@
|
||||||
'use strict';
|
|
||||||
|
|
||||||
var https = require('https');
|
|
||||||
var path = require('path');
|
|
||||||
var fs = require('fs');
|
|
||||||
var PromiseA = global.Promise || require('bluebird').Promise;
|
|
||||||
|
|
||||||
exports.create = function (ip, localPort, externalPort) {
|
|
||||||
return new PromiseA(function (resolve, reject) {
|
|
||||||
var token = Math.random().toString(16).split('.')[1];
|
|
||||||
var tokenPath = Math.random().toString(16).split('.')[1];
|
|
||||||
var options;
|
|
||||||
var server;
|
|
||||||
var options;
|
|
||||||
var certsPath = path.join(__dirname, 'certs', 'server');
|
|
||||||
var caCertsPath = path.join(__dirname, 'certs', 'ca');
|
|
||||||
|
|
||||||
|
|
||||||
function testConnection() {
|
|
||||||
var awesome = false;
|
|
||||||
var timetok;
|
|
||||||
var webreq;
|
|
||||||
var options = {
|
|
||||||
// not hostname because we set headers.host on our own
|
|
||||||
host: ip
|
|
||||||
, headers: {
|
|
||||||
// whatever's on the fake cert
|
|
||||||
'Host': 'redirect-www.org'
|
|
||||||
}
|
|
||||||
, port: externalPort
|
|
||||||
, path: '/' + tokenPath
|
|
||||||
, ca: fs.readFileSync(path.join(caCertsPath, 'my-root-ca.crt.pem'))
|
|
||||||
};
|
|
||||||
options.agent = new https.Agent(options);
|
|
||||||
|
|
||||||
timetok = setTimeout(function () {
|
|
||||||
reject(new Error("timed out while testing NAT loopback for port " + externalPort));
|
|
||||||
}, 2000);
|
|
||||||
|
|
||||||
function finishHim(err) {
|
|
||||||
clearTimeout(timetok);
|
|
||||||
server.close(function () {
|
|
||||||
if (!err && awesome) {
|
|
||||||
resolve();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
if (err || !awesome) {
|
|
||||||
if (err) {
|
|
||||||
reject(err);
|
|
||||||
}
|
|
||||||
else if (!awesome) {
|
|
||||||
reject(new Error("loopback failed. Why? here's my best guess: "
|
|
||||||
+ "the ssl cert matched, so you've probably got two boxes and this isn't the right one"));
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
webreq = https.request(options, function(res) {
|
|
||||||
res.on('data', function (resToken) {
|
|
||||||
if (resToken.toString() === token) {
|
|
||||||
awesome = true;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
res.on('error', function (err) {
|
|
||||||
console.error('[ERROR] https.request.response');
|
|
||||||
console.error(err);
|
|
||||||
finishHim(new Error("loopback failed. Why? here's my best guess: "
|
|
||||||
+ "the connection was interrupted"));
|
|
||||||
});
|
|
||||||
res.on('end', function () {
|
|
||||||
finishHim();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
webreq.on('error', function (err) {
|
|
||||||
console.error('[ERROR] https.request');
|
|
||||||
console.error(err);
|
|
||||||
if (/ssl|cert|chain/i.test(err.message || err.toString())) {
|
|
||||||
finishHim(new Error("loopback failed. Why? here's my best guess: "
|
|
||||||
+ "the ssl cert validation may have failed (might port-forward to the wrong box)"));
|
|
||||||
} else {
|
|
||||||
finishHim(new Error("loopback failed. Why? here's my best guess: "
|
|
||||||
+ "port forwarding isn't configured for " + ip + ":" + externalPort + " to " + localPort));
|
|
||||||
}
|
|
||||||
});
|
|
||||||
webreq.end();
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
// SSL Certificates
|
|
||||||
//
|
|
||||||
options = {
|
|
||||||
key: fs.readFileSync(path.join(certsPath, 'my-server.key.pem'))
|
|
||||||
, ca: [ fs.readFileSync(path.join(caCertsPath, 'my-root-ca.crt.pem')) ]
|
|
||||||
, cert: fs.readFileSync(path.join(certsPath, 'my-server.crt.pem'))
|
|
||||||
, requestCert: false
|
|
||||||
, rejectUnauthorized: false
|
|
||||||
};
|
|
||||||
|
|
||||||
//
|
|
||||||
// Serve an Express App securely with HTTPS
|
|
||||||
//
|
|
||||||
server = https.createServer(options);
|
|
||||||
function listen(app) {
|
|
||||||
server.on('request', app);
|
|
||||||
server.listen(localPort, function () {
|
|
||||||
localPort = server.address().port;
|
|
||||||
setTimeout(testConnection, 2000);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
listen(function (req, res) {
|
|
||||||
if (('/' + tokenPath) === req.url) {
|
|
||||||
res.end(token);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
res.end('loopback failure');
|
|
||||||
});
|
|
||||||
});
|
|
||||||
};
|
|
|
@ -1,82 +0,0 @@
|
||||||
'use strict';
|
|
||||||
|
|
||||||
var updateIp = require('../holepunch/helpers/update-ip.js').update;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* @param {string[]} hostnames - A list of hostnames
|
|
||||||
* @param {Object[]} addresses - A list of { address: <ip-address>, family: <4|6> }
|
|
||||||
*/
|
|
||||||
function update(services, hostnames, addresses, ddnsToken) {
|
|
||||||
// TODO use not-yet-built API to get and store tokens
|
|
||||||
// TODO use API to add and remove nameservers
|
|
||||||
var answers = [];
|
|
||||||
var promises;
|
|
||||||
var results = [];
|
|
||||||
var PromiseA;
|
|
||||||
|
|
||||||
hostnames.forEach(function (hostname) {
|
|
||||||
addresses.forEach(function (address) {
|
|
||||||
var answer = {
|
|
||||||
"name": hostname
|
|
||||||
, "value": address.address
|
|
||||||
, "type": null
|
|
||||||
, "priority": null
|
|
||||||
// token = require('../dyndns-token.js').token;
|
|
||||||
, "token": ddnsToken
|
|
||||||
};
|
|
||||||
|
|
||||||
if (4 === address.family) {
|
|
||||||
answer.type = 'A';
|
|
||||||
}
|
|
||||||
else if (6 === address.family) {
|
|
||||||
answer.type = 'AAAA';
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
console.error('[ERROR] unspported address:');
|
|
||||||
console.error(address);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
answers.push(answer);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
promises = services.map(function (service, i) {
|
|
||||||
return updateIp({
|
|
||||||
hostname: service.hostname
|
|
||||||
, port: service.port
|
|
||||||
, pathname: service.pathname
|
|
||||||
, cacert: service.cacert
|
|
||||||
, token: ddnsToken
|
|
||||||
, ddns: answers
|
|
||||||
}).then(function (data) {
|
|
||||||
results[i] = { service: service, data: data };
|
|
||||||
return data;
|
|
||||||
}).error(function (err) {
|
|
||||||
results[i] = { service: service, error: err };
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
PromiseA = require('bluebird').Promise;
|
|
||||||
return PromiseA.all(promises).then(function () {
|
|
||||||
return results;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
module.exports.update = function (services, hostnames, ddnsToken) {
|
|
||||||
return require('./ip-checker').getExternalAddresses().then(function (result) {
|
|
||||||
//console.log(Object.keys(allMap), result);
|
|
||||||
//console.log(hostnames)
|
|
||||||
//console.log(result.addresses);
|
|
||||||
console.log('[IP CHECKER] hostnames.length', hostnames.length);
|
|
||||||
console.log('[IP CHECKER] result.addresses.length', result.addresses.length);
|
|
||||||
return update(services, hostnames, result.addresses, ddnsToken);
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
if (require.main === module) {
|
|
||||||
module.exports.update().then(function (results) {
|
|
||||||
console.log('results');
|
|
||||||
console.log(results);
|
|
||||||
});
|
|
||||||
}
|
|
|
@ -1,126 +0,0 @@
|
||||||
"use strict";
|
|
||||||
|
|
||||||
var PromiseA = require('bluebird').Promise;
|
|
||||||
var ifaces = require('os').networkInterfaces();
|
|
||||||
var dns = PromiseA.promisifyAll(require('dns'));
|
|
||||||
var https = require('https');
|
|
||||||
|
|
||||||
function getExternalAddresses() {
|
|
||||||
var iftypes = {};
|
|
||||||
|
|
||||||
Object.keys(ifaces).forEach(function (ifname) {
|
|
||||||
ifaces[ifname].forEach(function (iface) {
|
|
||||||
if (iface.internal) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
/*
|
|
||||||
if (/^(::|f[cde])/.test(iface.address)) {
|
|
||||||
console.log('non-public ipv6');
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
iftypes[iface.family] = true;
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
var now = Date.now();
|
|
||||||
|
|
||||||
return PromiseA.all([
|
|
||||||
dns.lookupAsync('api.ipify.org', { family: 4/*, all: true*/ }).then(function (ans) {
|
|
||||||
iftypes.IPv4 = { address: ans[0], family: ans[1], time: Date.now() - now };
|
|
||||||
}).error(function () {
|
|
||||||
//console.log('no ipv4', Date.now() - now);
|
|
||||||
iftypes.IPv4 = false;
|
|
||||||
})
|
|
||||||
, dns.lookupAsync('api.ipify.org', { family: 6/*, all: true*/ }).then(function (ans) {
|
|
||||||
iftypes.IPv6 = { address: ans[0], family: ans[1], time: Date.now() - now };
|
|
||||||
}).error(function () {
|
|
||||||
//console.log('no ipv6', Date.now() - now);
|
|
||||||
iftypes.IPv6 = false;
|
|
||||||
})
|
|
||||||
]).then(function () {
|
|
||||||
var requests = [];
|
|
||||||
|
|
||||||
if (iftypes.IPv4) {
|
|
||||||
requests.push(new PromiseA(function (resolve) {
|
|
||||||
var req = https.request({
|
|
||||||
method: 'GET'
|
|
||||||
, hostname: iftypes.IPv4.address
|
|
||||||
, port: 443
|
|
||||||
, headers: {
|
|
||||||
Host: 'api.ipify.org'
|
|
||||||
}
|
|
||||||
, path: '/'
|
|
||||||
//, family: 4
|
|
||||||
// TODO , localAddress: <<external_ipv4>>
|
|
||||||
}, function (res) {
|
|
||||||
var result = '';
|
|
||||||
|
|
||||||
res.on('error', function (/*err*/) {
|
|
||||||
resolve(null);
|
|
||||||
});
|
|
||||||
|
|
||||||
res.on('data', function (chunk) {
|
|
||||||
result += chunk.toString('utf8');
|
|
||||||
});
|
|
||||||
res.on('end', function () {
|
|
||||||
resolve({ address: result, family: 4/*, wan: result === iftypes.IPv4.localAddress*/, time: iftypes.IPv4.time });
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
req.on('error', function () {
|
|
||||||
resolve(null);
|
|
||||||
});
|
|
||||||
req.end();
|
|
||||||
}));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (iftypes.IPv6) {
|
|
||||||
requests.push(new PromiseA(function (resolve) {
|
|
||||||
var req = https.request({
|
|
||||||
method: 'GET'
|
|
||||||
, hostname: iftypes.IPv6.address
|
|
||||||
, port: 443
|
|
||||||
, headers: {
|
|
||||||
Host: 'api.ipify.org'
|
|
||||||
}
|
|
||||||
, path: '/'
|
|
||||||
//, family: 6
|
|
||||||
// TODO , localAddress: <<external_ipv6>>
|
|
||||||
}, function (res) {
|
|
||||||
var result = '';
|
|
||||||
|
|
||||||
res.on('error', function (/*err*/) {
|
|
||||||
resolve(null);
|
|
||||||
});
|
|
||||||
|
|
||||||
res.on('data', function (chunk) {
|
|
||||||
result += chunk.toString('utf8');
|
|
||||||
});
|
|
||||||
res.on('end', function () {
|
|
||||||
resolve({ address: result, family: 6/*, wan: result === iftypes.IPv6.localAaddress*/, time: iftypes.IPv4.time });
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
req.on('error', function () {
|
|
||||||
resolve(null);
|
|
||||||
});
|
|
||||||
req.end();
|
|
||||||
}));
|
|
||||||
}
|
|
||||||
|
|
||||||
return PromiseA.all(requests).then(function (ips) {
|
|
||||||
ips = ips.filter(function (ip) {
|
|
||||||
return ip;
|
|
||||||
});
|
|
||||||
|
|
||||||
return {
|
|
||||||
addresses: ips
|
|
||||||
, time: Date.now() - now
|
|
||||||
};
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
exports.getExternalAddresses = getExternalAddresses;
|
|
|
@ -4,42 +4,10 @@ var cluster = require('cluster');
|
||||||
var PromiseA = require('bluebird');
|
var PromiseA = require('bluebird');
|
||||||
var memstore;
|
var memstore;
|
||||||
var sqlstore;
|
var sqlstore;
|
||||||
var config;
|
|
||||||
// TODO
|
// TODO
|
||||||
// var rootMasterKey;
|
// var rootMasterKey;
|
||||||
|
|
||||||
function updateIps() {
|
|
||||||
console.log('[UPDATE IP]');
|
|
||||||
var allMap = {};
|
|
||||||
var hostnames = config.redirects.reduce(function (all, redirect) {
|
|
||||||
if (redirect.ip && !allMap[redirect.id]) {
|
|
||||||
allMap[redirect.id] = true;
|
|
||||||
all.push(redirect.id);
|
|
||||||
}
|
|
||||||
|
|
||||||
return all;
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
require('./ddns-updater').update(
|
|
||||||
config.ddns.services
|
|
||||||
, hostnames
|
|
||||||
, config.ddns.token
|
|
||||||
).then(function (results) {
|
|
||||||
results.forEach(function (result) {
|
|
||||||
if (result.error) {
|
|
||||||
console.error(result);
|
|
||||||
} else {
|
|
||||||
console.log('[SUCCESS]', result.service.hostname);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}).error(function (err) {
|
|
||||||
console.error('[UPDATE IP] ERROR');
|
|
||||||
console.error(err);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
function init(conf/*, state*/) {
|
function init(conf/*, state*/) {
|
||||||
config = conf;
|
|
||||||
if (!conf.ipcKey) {
|
if (!conf.ipcKey) {
|
||||||
conf.ipcKey = require('crypto').randomBytes(16).toString('base64');
|
conf.ipcKey = require('crypto').randomBytes(16).toString('base64');
|
||||||
}
|
}
|
||||||
|
@ -101,11 +69,6 @@ function init(conf/*, state*/) {
|
||||||
*/
|
*/
|
||||||
});
|
});
|
||||||
|
|
||||||
// TODO check the IP every 5 minutes and update it every hour
|
|
||||||
setInterval(updateIps, 60 * 60 * 1000);
|
|
||||||
// we don't want this to load right away (extra procesing time)
|
|
||||||
setTimeout(updateIps, 1);
|
|
||||||
|
|
||||||
return promise;
|
return promise;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -172,8 +172,6 @@ module.exports.create = function (webserver, info, state) {
|
||||||
, vhostPatterns: null
|
, vhostPatterns: null
|
||||||
, server: webserver
|
, server: webserver
|
||||||
, externalPort: info.conf.externalPort
|
, externalPort: info.conf.externalPort
|
||||||
, primaryNameserver: info.conf.primaryNameserver
|
|
||||||
, nameservers: info.conf.nameservers
|
|
||||||
, privkey: info.conf.privkey
|
, privkey: info.conf.privkey
|
||||||
, pubkey: info.conf.pubkey
|
, pubkey: info.conf.pubkey
|
||||||
, redirects: info.conf.redirects
|
, redirects: info.conf.redirects
|
||||||
|
|
Loading…
Reference in New Issue