mirror of
https://github.com/dec0dOS/zero-ui.git
synced 2025-08-19 13:01:30 -07:00
feat: wip implementation of dns: {...} stanza handling
backend/services/network.js implements correct handling of dns: stanza required by ZeroNSd. Unfortunately this breaks frontend. I think this is because of delete statements. Unfortunately I know too little about nodejs to implement a proper solution. I tried mitigating problem using a copy of the data, but that didn't work. Anything else coming to mind seems to ugly to be 'right'.
This commit is contained in:
parent
5ce0bd1009
commit
0b77e9594b
3 changed files with 163 additions and 70 deletions
|
@ -4,7 +4,7 @@ const axios = require("axios");
|
||||||
const api = require("../utils/controller-api");
|
const api = require("../utils/controller-api");
|
||||||
const db = require("../utils/db");
|
const db = require("../utils/db");
|
||||||
const constants = require("../utils/constants");
|
const constants = require("../utils/constants");
|
||||||
const startStopDNS = require("../utils/zns");
|
const zns = require("../utils/zns");
|
||||||
|
|
||||||
async function getNetworkAdditionalData(data) {
|
async function getNetworkAdditionalData(data) {
|
||||||
let additionalData = db
|
let additionalData = db
|
||||||
|
@ -22,11 +22,22 @@ async function getNetworkAdditionalData(data) {
|
||||||
delete data.remoteTraceLevel;
|
delete data.remoteTraceLevel;
|
||||||
delete data.remoteTraceTarget;
|
delete data.remoteTraceTarget;
|
||||||
|
|
||||||
|
let ad = { ...additionalData.value() };
|
||||||
|
data.dns = {
|
||||||
|
domain: ad.dnsDomain,
|
||||||
|
servers: ["pippo"],
|
||||||
|
};
|
||||||
|
if (ad.dnsIP) data.dns["servers"].push(ad.dnsIP);
|
||||||
|
console.log(`*** dns="${JSON.stringify(ad)}" -> ${JSON.stringify(data.dns)}`);
|
||||||
|
delete ad.dnsIP;
|
||||||
|
delete ad.dnsDomain;
|
||||||
|
delete ad.dnsEnable;
|
||||||
|
delete ad.dnsWildcard;
|
||||||
return {
|
return {
|
||||||
id: data.id,
|
id: data.id,
|
||||||
type: "Network",
|
type: "Network",
|
||||||
clock: Math.floor(new Date().getTime() / 1000),
|
clock: Math.floor(new Date().getTime() / 1000),
|
||||||
...additionalData.value(),
|
...ad,
|
||||||
config: data,
|
config: data,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -47,13 +58,11 @@ async function getNetworksData(nwids) {
|
||||||
return [];
|
return [];
|
||||||
});
|
});
|
||||||
|
|
||||||
let data = Promise.all(
|
return Promise.all(
|
||||||
multipleRes.map((el) => {
|
multipleRes.map((el) => {
|
||||||
return getNetworkAdditionalData(el.data);
|
return getNetworkAdditionalData(el.data);
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
|
||||||
return data;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
exports.createNetworkAdditionalData = createNetworkAdditionalData;
|
exports.createNetworkAdditionalData = createNetworkAdditionalData;
|
||||||
|
@ -84,6 +93,12 @@ async function updateNetworkAdditionalData(nwid, data) {
|
||||||
additionalData.rulesSource = data.rulesSource;
|
additionalData.rulesSource = data.rulesSource;
|
||||||
}
|
}
|
||||||
if (data.hasOwnProperty("dnsEnable")) {
|
if (data.hasOwnProperty("dnsEnable")) {
|
||||||
|
if (data.dnsEnable) {
|
||||||
|
//TODO: start ZeroNSd and get its IP address
|
||||||
|
additionalData.dnsIP = "127.0.0.1";
|
||||||
|
} else {
|
||||||
|
additionalData.dnsIP = null;
|
||||||
|
}
|
||||||
additionalData.dnsEnable = data.dnsEnable;
|
additionalData.dnsEnable = data.dnsEnable;
|
||||||
}
|
}
|
||||||
if (data.hasOwnProperty("dnsDomain")) {
|
if (data.hasOwnProperty("dnsDomain")) {
|
||||||
|
@ -101,17 +116,7 @@ async function updateNetworkAdditionalData(nwid, data) {
|
||||||
.write();
|
.write();
|
||||||
|
|
||||||
if (data.hasOwnProperty("dnsEnable")) {
|
if (data.hasOwnProperty("dnsEnable")) {
|
||||||
let token = db.get("users").value()[0];
|
zns.handleNet(db.get("networks").filter({ id: nwid }).value()[0]);
|
||||||
token = token.token;
|
|
||||||
let config = db.get("networks").find({ id: nwid }).value();
|
|
||||||
let ret = startStopDNS(token, config.id, config.additionalConfig);
|
|
||||||
if (ret) {
|
|
||||||
db.get("networks")
|
|
||||||
.filter({ id: nwid })
|
|
||||||
.map("additionalConfig")
|
|
||||||
.map((additionalConfig) => _.assign(additionalConfig, ret))
|
|
||||||
.write();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,64 +1,147 @@
|
||||||
const { spawn } = require("child_process");
|
const path = require("path");
|
||||||
|
const fs = require("fs");
|
||||||
|
|
||||||
function pidIsRunning(pid) {
|
const db = require("../utils/db");
|
||||||
try {
|
const cp = require("child_process");
|
||||||
process.kill(pid, 0);
|
|
||||||
return true;
|
//TODO: does this kind of "optimization" make sense in Node.js?
|
||||||
} catch (e) {
|
let token = null;
|
||||||
return false;
|
function getToken() {
|
||||||
}
|
if (!token)
|
||||||
|
try {
|
||||||
|
token = db.get("users").value()[0].token;
|
||||||
|
} catch {
|
||||||
|
console.warn("*** token retrieval failed");
|
||||||
|
}
|
||||||
|
return token;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function setPid(nwid, pid) {
|
||||||
|
db.get("networks")
|
||||||
|
.filter({ id: nwid })
|
||||||
|
.map("additionalConfig")
|
||||||
|
.map((additionalConfig) => (additionalConfig.pidDNS = pid))
|
||||||
|
.write();
|
||||||
|
}
|
||||||
|
|
||||||
|
const isRunning = (query, pid) => {
|
||||||
|
return new Promise(function (resolve) {
|
||||||
|
//FIXME: Check if pgrep is available
|
||||||
|
cp.exec(`pgrep ${query}`, (err, stdout) => {
|
||||||
|
resolve(stdout.indexOf(`${pid}`) > -1);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
function startDNS(token, nwid, conf) {
|
function startDNS(token, nwid, conf) {
|
||||||
if (conf.hasOwnProperty("pidDNS")) {
|
//FIXME: check it does the right thing when conf.pidDNS is null/undefined
|
||||||
if (pidIsRunning(conf.pidDNS)) {
|
isRunning("zeronsd", conf.pidDNS).then((ok) => {
|
||||||
return null;
|
if (ok) {
|
||||||
|
console.log(
|
||||||
|
`startDNS(${token}, ${nwid}): already active on PID ${conf.pidDNS}`
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
let cmd = "zeronsd";
|
||||||
|
let opts = Array();
|
||||||
|
if (process.geteuid() === 0) {
|
||||||
|
// production in Docker container
|
||||||
|
} else {
|
||||||
|
// we are debugging
|
||||||
|
let myLocal = "/home/mcon/.cargo/bin";
|
||||||
|
let pth = process.env.PATH.split(path.delimiter);
|
||||||
|
if (!pth.includes(myLocal)) pth.push(myLocal);
|
||||||
|
if (
|
||||||
|
!process.env.PATH.split(path.delimiter).some(function (d) {
|
||||||
|
let e = path.resolve(d, cmd);
|
||||||
|
console.log(`*** PATH testing: "${d}" -> "${e}"`);
|
||||||
|
try {
|
||||||
|
fs.accessSync(e, fs.constants.X_OK);
|
||||||
|
console.log(" is executable");
|
||||||
|
cmd = "sudo";
|
||||||
|
opts.push("-E", e);
|
||||||
|
return true;
|
||||||
|
} catch (e) {
|
||||||
|
console.warn(` cannot execute (${e})`);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
})
|
||||||
|
) {
|
||||||
|
console.error(`*** zeronsd not found in PATH (${process.env.PATH})`);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
opts.push("start", "-v", "-v");
|
||||||
|
if (conf.hasOwnProperty("dnsWildcard") && conf.dnsWildcard) {
|
||||||
|
opts.push("-w");
|
||||||
|
}
|
||||||
|
if (conf.hasOwnProperty("dnsDomain") && !!conf.dnsDomain) {
|
||||||
|
opts.push("-d", conf.dnsDomain);
|
||||||
|
}
|
||||||
|
opts.push(nwid);
|
||||||
|
process.env.ZEROTIER_CENTRAL_TOKEN = token;
|
||||||
|
console.log(`*** PATH: "${process.env.PATH}"`);
|
||||||
|
console.log(
|
||||||
|
`*** ZEROTIER_CENTRAL_TOKEN: "${process.env.ZEROTIER_CENTRAL_TOKEN}"`
|
||||||
|
);
|
||||||
|
let dns = cp.spawn(cmd, opts, { detached: true });
|
||||||
|
dns.on("spawn", () => {
|
||||||
|
console.log(
|
||||||
|
`zeronsd successfully spawned [${dns.pid}](${dns.spawnargs})`
|
||||||
|
);
|
||||||
|
setPid(nwid, dns.pid);
|
||||||
|
});
|
||||||
|
dns.stdout.on("data", (data) => {
|
||||||
|
console.log(`zeronsd spawn stdout: ${data}`);
|
||||||
|
});
|
||||||
|
dns.stderr.on("data", (data) => {
|
||||||
|
console.error(`zeronsd spawn stderr: ${data}`);
|
||||||
|
});
|
||||||
|
dns.on("error", (error) => {
|
||||||
|
console.log(`zeronsd spawn ERROR: [${error}](${dns.spawnargs})`);
|
||||||
|
});
|
||||||
|
dns.on("close", (code) => {
|
||||||
|
console.log(`zeronsd exited: [${code}](${dns.spawnargs})`);
|
||||||
|
setPid(nwid, null);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
delete conf.pidDNS;
|
|
||||||
}
|
|
||||||
const opts = Array("start");
|
|
||||||
if (conf.hasOwnProperty("dnsWildcard") && conf.dnsWildcard) {
|
|
||||||
opts.push("-w");
|
|
||||||
}
|
|
||||||
if (conf.hasOwnProperty("dnsDomain") && !!conf.dnsDomain) {
|
|
||||||
opts.push("-d", conf.dnsDomain);
|
|
||||||
}
|
|
||||||
opts.push(nwid);
|
|
||||||
let env = process.env;
|
|
||||||
env.ZEROTIER_CENTRAL_TOKEN = token;
|
|
||||||
console.log(`*** PATH: "${env.PATH}"`);
|
|
||||||
const dns = spawn("zeronsd", opts, {
|
|
||||||
detached: true,
|
|
||||||
env: env,
|
|
||||||
});
|
});
|
||||||
dns.on("spawn", () => {
|
|
||||||
console.log(`zeronsd successfully spawned [${dns.pid}](${dns.spawnargs})`);
|
|
||||||
console.log("*** should update PID ***");
|
|
||||||
});
|
|
||||||
dns.on("error", (error) => {
|
|
||||||
console.log(`zeronsd spawn ERROR: [${error}](${dns.spawnargs})`);
|
|
||||||
});
|
|
||||||
conf.pidDNS = dns.pid;
|
|
||||||
return conf;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function stopDNS(conf) {
|
function stopDNS(nwid, conf) {
|
||||||
if (conf.hasOwnProperty("pidDNS")) {
|
let pid = conf.pidDNS;
|
||||||
try {
|
if (pid) {
|
||||||
process.kill(conf.pidDNS);
|
isRunning("zeronsd", pid).then((ok) => {
|
||||||
} catch (e) {}
|
if (ok) {
|
||||||
delete conf.pidDNS;
|
console.log(`stopDNS(${nwid}): stopping PID ${pid}`);
|
||||||
return conf;
|
try {
|
||||||
}
|
process.kill(pid);
|
||||||
return null;
|
} catch (e) {
|
||||||
}
|
console.error(`stopDNS(${nwid}): stopping PID ${pid} FAILED (${e})`);
|
||||||
|
}
|
||||||
module.exports = function (token, nwid, conf) {
|
} else {
|
||||||
let ret;
|
console.log(`stopDNS(${nwid}): PID ${pid} is stale`);
|
||||||
if (conf.dnsEnable) {
|
}
|
||||||
ret = startDNS(token, nwid, conf);
|
});
|
||||||
|
setPid(nwid, null);
|
||||||
} else {
|
} else {
|
||||||
ret = stopDNS(conf);
|
console.log(`stopDNS(${nwid}): net has no PID`);
|
||||||
}
|
}
|
||||||
return ret;
|
}
|
||||||
};
|
|
||||||
|
exports.handleNet = handleNet;
|
||||||
|
function handleNet(net) {
|
||||||
|
let cfg = net.additionalConfig;
|
||||||
|
if (cfg.dnsEnable) {
|
||||||
|
startDNS(getToken(), net.id, cfg);
|
||||||
|
} else {
|
||||||
|
stopDNS(net.id, cfg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
exports.scan = scan;
|
||||||
|
function scan() {
|
||||||
|
let nets = db.get("networks").value();
|
||||||
|
nets.forEach((net) => {
|
||||||
|
handleNet(net);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
|
@ -41,6 +41,11 @@ function NetworkSettings({ network, setNetwork }) {
|
||||||
sendReq(data);
|
sendReq(data);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
console.log(
|
||||||
|
`*** dns="${JSON.stringify(network)}" -> ${JSON.stringify(
|
||||||
|
network["config"]
|
||||||
|
)}`
|
||||||
|
);
|
||||||
return (
|
return (
|
||||||
<Accordion>
|
<Accordion>
|
||||||
<AccordionSummary expandIcon={<ExpandMoreIcon />}>
|
<AccordionSummary expandIcon={<ExpandMoreIcon />}>
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue