Files
cloudron-box/src/network.js

72 lines
2.8 KiB
JavaScript
Raw Normal View History

2020-08-31 18:22:33 -07:00
'use strict';
exports = module.exports = {
getBlocklist,
setBlocklist,
getDynamicDns,
setDynamicDns,
2020-08-31 18:22:33 -07:00
};
const assert = require('assert'),
BoxError = require('./boxerror.js'),
cron = require('./cron.js'),
ipaddr = require('ipaddr.js'),
2020-08-31 18:22:33 -07:00
path = require('path'),
paths = require('./paths.js'),
safe = require('safetydance'),
settings = require('./settings.js'),
2020-08-31 18:22:33 -07:00
shell = require('./shell.js'),
validator = require('validator');
const SET_BLOCKLIST_CMD = path.join(__dirname, 'scripts/setblocklist.sh');
async function getBlocklist() {
const value = await settings.getBlob(settings.FIREWALL_BLOCKLIST_KEY);
return value ? value.toString('utf8') : '';
2020-08-31 18:22:33 -07:00
}
async function setBlocklist(blocklist, auditSource) {
assert.strictEqual(typeof blocklist, 'string');
assert.strictEqual(typeof auditSource, 'object');
2020-08-31 18:22:33 -07:00
const parsedIp = ipaddr.process(auditSource.ip);
2020-08-31 18:22:33 -07:00
for (const line of blocklist.split('\n')) {
if (!line || line.startsWith('#')) continue;
const rangeOrIP = line.trim();
// this checks for IPv4 and IPv6
if (!validator.isIP(rangeOrIP) && !validator.isIPRange(rangeOrIP)) throw new BoxError(BoxError.BAD_FIELD, `${rangeOrIP} is not a valid IP or range`);
if (rangeOrIP.indexOf('/') === -1) {
if (auditSource.ip === rangeOrIP) throw new BoxError(BoxError.BAD_FIELD, `${rangeOrIP} includes client IP. Cannot block yourself`);
} else {
const parsedRange = ipaddr.parseCIDR(rangeOrIP); // returns [addr, range]
if (parsedRange[0].kind() === parsedIp.kind() && parsedIp.match(parsedRange)) throw new BoxError(BoxError.BAD_FIELD, `${rangeOrIP} includes client IP. Cannot block yourself`);
}
}
2020-08-31 18:22:33 -07:00
if (settings.isDemo()) throw new BoxError(BoxError.CONFLICT, 'Not allowed in demo mode');
// store in blob since the value field is TEXT and has 16kb size limit
await settings.setBlob(settings.FIREWALL_BLOCKLIST_KEY, Buffer.from(blocklist));
2020-08-31 18:22:33 -07:00
// this is done only because it's easier for the shell script and the firewall service to get the value
if (!safe.fs.writeFileSync(paths.FIREWALL_BLOCKLIST_FILE, blocklist + '\n', 'utf8')) throw new BoxError(BoxError.FS_ERROR, safe.error.message);
2020-08-31 18:22:33 -07:00
const [error] = await safe(shell.promises.sudo('setBlocklist', [ SET_BLOCKLIST_CMD ], {}));
if (error) throw new BoxError(BoxError.IPTABLES_ERROR, `Error setting blocklist: ${error.message}`);
2020-08-31 18:22:33 -07:00
}
async function getDynamicDns() {
const enabled = await settings.get(settings.DYNAMIC_DNS_KEY);
return enabled ? !!enabled : false; // db holds string values only
}
async function setDynamicDns(enabled) {
assert.strictEqual(typeof enabled, 'boolean');
await settings.set(settings.DYNAMIC_DNS_KEY, enabled ? 'enabled' : ''); // db holds string values only
cron.dynamicDnsChanged(enabled);
}