2020-08-31 18:22:33 -07:00
|
|
|
'use strict';
|
|
|
|
|
|
|
|
|
|
exports = module.exports = {
|
|
|
|
|
getBlocklist,
|
2023-05-13 14:59:57 +02:00
|
|
|
setBlocklist,
|
2023-08-02 22:53:29 +05:30
|
|
|
|
|
|
|
|
getDynamicDns,
|
|
|
|
|
setDynamicDns,
|
2020-08-31 18:22:33 -07:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
const assert = require('assert'),
|
|
|
|
|
BoxError = require('./boxerror.js'),
|
2023-08-02 22:53:29 +05:30
|
|
|
cron = require('./cron.js'),
|
2020-09-14 10:29:48 -07:00
|
|
|
ipaddr = require('ipaddr.js'),
|
2020-08-31 18:22:33 -07:00
|
|
|
path = require('path'),
|
|
|
|
|
paths = require('./paths.js'),
|
|
|
|
|
safe = require('safetydance'),
|
2020-09-02 23:04:42 -07:00
|
|
|
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');
|
|
|
|
|
|
2021-08-18 15:31:07 -07:00
|
|
|
async function getBlocklist() {
|
2023-08-02 19:17:22 +05:30
|
|
|
const value = await settings.getBlob(settings.FIREWALL_BLOCKLIST_KEY);
|
|
|
|
|
return value ? value.toString('utf8') : '';
|
2020-08-31 18:22:33 -07:00
|
|
|
}
|
|
|
|
|
|
2021-08-18 15:31:07 -07:00
|
|
|
async function setBlocklist(blocklist, auditSource) {
|
2020-09-14 10:29:48 -07:00
|
|
|
assert.strictEqual(typeof blocklist, 'string');
|
|
|
|
|
assert.strictEqual(typeof auditSource, 'object');
|
2020-08-31 18:22:33 -07:00
|
|
|
|
2020-09-14 10:29:48 -07:00
|
|
|
const parsedIp = ipaddr.process(auditSource.ip);
|
2020-08-31 18:22:33 -07:00
|
|
|
|
2020-09-14 10:29:48 -07:00
|
|
|
for (const line of blocklist.split('\n')) {
|
|
|
|
|
if (!line || line.startsWith('#')) continue;
|
|
|
|
|
const rangeOrIP = line.trim();
|
2022-02-16 12:57:38 -08:00
|
|
|
// this checks for IPv4 and IPv6
|
2021-08-18 15:31:07 -07:00
|
|
|
if (!validator.isIP(rangeOrIP) && !validator.isIPRange(rangeOrIP)) throw new BoxError(BoxError.BAD_FIELD, `${rangeOrIP} is not a valid IP or range`);
|
2020-09-02 23:04:42 -07:00
|
|
|
|
2020-09-14 10:29:48 -07:00
|
|
|
if (rangeOrIP.indexOf('/') === -1) {
|
2021-08-18 15:31:07 -07:00
|
|
|
if (auditSource.ip === rangeOrIP) throw new BoxError(BoxError.BAD_FIELD, `${rangeOrIP} includes client IP. Cannot block yourself`);
|
2020-09-14 10:29:48 -07:00
|
|
|
} else {
|
2021-04-07 17:31:04 +02:00
|
|
|
const parsedRange = ipaddr.parseCIDR(rangeOrIP); // returns [addr, range]
|
2021-08-18 15:31:07 -07:00
|
|
|
if (parsedRange[0].kind() === parsedIp.kind() && parsedIp.match(parsedRange)) throw new BoxError(BoxError.BAD_FIELD, `${rangeOrIP} includes client IP. Cannot block yourself`);
|
2020-09-14 10:29:48 -07:00
|
|
|
}
|
|
|
|
|
}
|
2020-08-31 18:22:33 -07:00
|
|
|
|
2021-08-18 15:31:07 -07:00
|
|
|
if (settings.isDemo()) throw new BoxError(BoxError.CONFLICT, 'Not allowed in demo mode');
|
2021-05-04 15:21:38 -07:00
|
|
|
|
2023-08-02 19:17:22 +05:30
|
|
|
// 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
|
|
|
|
2021-08-18 15:31:07 -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
|
|
|
|
2021-08-18 15:31:07 -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
|
|
|
}
|
2023-08-02 22:53:29 +05:30
|
|
|
|
|
|
|
|
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);
|
|
|
|
|
}
|