migrate blocklist to a txt file
this allows easy copy/pasting of existing deny lists which contain comments and blank lines
This commit is contained in:
+21
-14
@@ -7,6 +7,7 @@ exports = module.exports = {
|
||||
|
||||
const assert = require('assert'),
|
||||
BoxError = require('./boxerror.js'),
|
||||
ipaddr = require('ipaddr.js'),
|
||||
path = require('path'),
|
||||
paths = require('./paths.js'),
|
||||
safe = require('safetydance'),
|
||||
@@ -19,27 +20,33 @@ const SET_BLOCKLIST_CMD = path.join(__dirname, 'scripts/setblocklist.sh');
|
||||
function getBlocklist(callback) {
|
||||
assert.strictEqual(typeof callback, 'function');
|
||||
|
||||
const data = safe.fs.readFileSync(paths.FIREWALL_CONFIG_FILE, 'utf8');
|
||||
const config = safe.JSON.parse(data);
|
||||
const blocklist = config && config.blocklist ? config.blocklist : [];
|
||||
|
||||
callback(null, blocklist);
|
||||
const data = safe.fs.readFileSync(paths.FIREWALL_BLOCKLIST_FILE, 'utf8');
|
||||
callback(null, data);
|
||||
}
|
||||
|
||||
function setBlocklist(blocklist, callback) {
|
||||
assert(Array.isArray(blocklist));
|
||||
function setBlocklist(blocklist, auditSource, callback) {
|
||||
assert.strictEqual(typeof blocklist, 'string');
|
||||
assert.strictEqual(typeof auditSource, 'object');
|
||||
assert.strictEqual(typeof callback, 'function');
|
||||
|
||||
if (!blocklist.every(x => validator.isIP(x) || validator.isIPRange(x))) return callback(new BoxError(BoxError.BAD_FIELD, 'blocklist must contain IP or IP range'));
|
||||
const parsedIp = ipaddr.process(auditSource.ip);
|
||||
|
||||
for (const line of blocklist.split('\n')) {
|
||||
if (!line || line.startsWith('#')) continue;
|
||||
const rangeOrIP = line.trim();
|
||||
if (!validator.isIP(rangeOrIP) && !validator.isIPRange(rangeOrIP)) return callback(new BoxError(BoxError.BAD_FIELD, `${rangeOrIP} is not a valid IP or range`));
|
||||
|
||||
if (rangeOrIP.indexOf('/') === -1) {
|
||||
if (auditSource.ip === rangeOrIP) return callback(new BoxError(BoxError.BAD_FIELD, `${rangeOrIP} includes client IP. Cannot block yourself`));
|
||||
} else {
|
||||
const parsedRange = ipaddr.parseCIDR(rangeOrIP);
|
||||
if (parsedIp.match(parsedRange)) return callback(new BoxError(BoxError.BAD_FIELD, `${rangeOrIP} includes client IP. Cannot block yourself`));
|
||||
}
|
||||
}
|
||||
|
||||
if (settings.isDemo()) return callback(new BoxError(BoxError.CONFLICT, 'Not allowed in demo mode'));
|
||||
|
||||
const data = safe.fs.readFileSync(paths.FIREWALL_CONFIG_FILE, 'utf8');
|
||||
const config = safe.JSON.parse(data) || {};
|
||||
|
||||
config.blocklist = blocklist;
|
||||
|
||||
if (!safe.fs.writeFileSync(paths.FIREWALL_CONFIG_FILE, JSON.stringify(config, null, 4), 'utf8')) return callback(new BoxError(BoxError.FS_ERROR, safe.error.message));
|
||||
if (!safe.fs.writeFileSync(paths.FIREWALL_BLOCKLIST_FILE, blocklist, 'utf8')) return callback(new BoxError(BoxError.FS_ERROR, safe.error.message));
|
||||
|
||||
shell.sudo('setBlocklist', [ SET_BLOCKLIST_CMD ], {}, function (error) {
|
||||
if (error) return callback(new BoxError(BoxError.IPTABLES_ERROR, `Error setting blocklist: ${error.message}`));
|
||||
|
||||
@@ -46,6 +46,7 @@ exports = module.exports = {
|
||||
CLOUDRON_AVATAR_FILE: path.join(baseDir(), 'boxdata/avatar.png'),
|
||||
UPDATE_CHECKER_FILE: path.join(baseDir(), 'boxdata/updatechecker.json'),
|
||||
ADDON_TURN_SECRET_FILE: path.join(baseDir(), 'boxdata/addon-turn-secret'),
|
||||
FIREWALL_BLOCKLIST_FILE: path.join(baseDir(), 'boxdata/firewall/blocklist.txt'),
|
||||
FIREWALL_CONFIG_FILE: path.join(baseDir(), 'boxdata/firewall-config.json'),
|
||||
|
||||
LOG_DIR: path.join(baseDir(), 'platformdata/logs'),
|
||||
|
||||
@@ -6,6 +6,7 @@ exports = module.exports = {
|
||||
};
|
||||
|
||||
var assert = require('assert'),
|
||||
auditSource = require('../auditsource.js'),
|
||||
BoxError = require('../boxerror.js'),
|
||||
HttpError = require('connect-lastmile').HttpError,
|
||||
HttpSuccess = require('connect-lastmile').HttpSuccess,
|
||||
@@ -22,12 +23,11 @@ function getBlocklist(req, res, next) {
|
||||
function setBlocklist(req, res, next) {
|
||||
assert.strictEqual(typeof req.body, 'object');
|
||||
|
||||
if (!Array.isArray(req.body.blocklist)) return next(new HttpError(400, 'blocklist is required'));
|
||||
if (!req.body.blocklist.every(x => typeof x === 'string')) return next(new HttpError(400, 'blocklist must be array of strings'));
|
||||
if (typeof req.body.blocklist !== 'string') return next(new HttpError(400, 'blocklist must be a string'));
|
||||
|
||||
req.clearTimeout(); // can take a while if there is a lot of network ranges
|
||||
|
||||
network.setBlocklist(req.body.blocklist, function (error) {
|
||||
network.setBlocklist(req.body.blocklist, auditSource.fromRequest(req), function (error) {
|
||||
if (error) return next(BoxError.toHttpError(error));
|
||||
|
||||
next(new HttpSuccess(200, {}));
|
||||
|
||||
@@ -14,10 +14,12 @@ fi
|
||||
|
||||
ipset flush cloudron_blocklist
|
||||
|
||||
user_firewall_json="/home/yellowtent/boxdata/firewall-config.json"
|
||||
if blocklist=$(node -e "console.log(JSON.parse(fs.readFileSync('${user_firewall_json}', 'utf8')).blocklist.join(' '))" 2>/dev/null); then
|
||||
user_firewall_json="/home/yellowtent/boxdata/firewall/blocklist.txt"
|
||||
|
||||
for ip in ${blocklist}; do
|
||||
ipset add cloudron_blocklist "${ip}"
|
||||
done
|
||||
if [[ -f "${user_firewall_json}" ]]; then
|
||||
while read -r line; do
|
||||
[[ -z "${line}" ]] && continue # ignore empty lines
|
||||
[[ "$line" =~ ^#.*$ ]] && continue # ignore lines starting with #
|
||||
ipset add cloudron_blocklist "${line}"
|
||||
done < "${user_firewall_json}"
|
||||
fi
|
||||
|
||||
Reference in New Issue
Block a user