feat: #7743 meta/blacklist

v1.18.x
Barış Soner Uşaklı 6 years ago
parent 3dd806dcb8
commit fcf8fd51cb

@ -1,73 +1,54 @@
'use strict'; 'use strict';
var ipaddr = require('ipaddr.js'); const ipaddr = require('ipaddr.js');
var winston = require('winston'); const winston = require('winston');
var async = require('async'); const _ = require('lodash');
var _ = require('lodash');
const db = require('../database');
var db = require('../database'); const pubsub = require('../pubsub');
var pubsub = require('../pubsub'); const plugins = require('../plugins');
var plugins = require('../plugins'); const analytics = require('../analytics');
var analytics = require('../analytics');
const Blacklist = module.exports;
var Blacklist = module.exports; Blacklist._rules = {};
Blacklist._rules = [];
Blacklist.load = async function () {
Blacklist.load = function (callback) { let rules = await Blacklist.get();
callback = callback || function () {}; rules = Blacklist.validate(rules);
async.waterfall([
Blacklist.get,
Blacklist.validate,
function (rules, next) {
winston.verbose('[meta/blacklist] Loading ' + rules.valid.length + ' blacklist rule(s)' + (rules.duplicateCount > 0 ? ', ignored ' + rules.duplicateCount + ' duplicate(s)' : ''));
if (rules.invalid.length) {
winston.warn('[meta/blacklist] ' + rules.invalid.length + ' invalid blacklist rule(s) were ignored.');
}
Blacklist._rules = { winston.verbose('[meta/blacklist] Loading ' + rules.valid.length + ' blacklist rule(s)' + (rules.duplicateCount > 0 ? ', ignored ' + rules.duplicateCount + ' duplicate(s)' : ''));
ipv4: rules.ipv4, if (rules.invalid.length) {
ipv6: rules.ipv6, winston.warn('[meta/blacklist] ' + rules.invalid.length + ' invalid blacklist rule(s) were ignored.');
cidr: rules.cidr, }
cidr6: rules.cidr6,
}; Blacklist._rules = {
next(); ipv4: rules.ipv4,
}, ipv6: rules.ipv6,
], callback); cidr: rules.cidr,
cidr6: rules.cidr6,
};
}; };
pubsub.on('blacklist:reload', Blacklist.load); pubsub.on('blacklist:reload', Blacklist.load);
Blacklist.save = function (rules, callback) { Blacklist.save = async function (rules) {
async.waterfall([ await db.setObject('ip-blacklist-rules', { rules: rules });
function (next) { await Blacklist.load();
db.setObject('ip-blacklist-rules', { rules: rules }, next); pubsub.publish('blacklist:reload');
},
function (next) {
Blacklist.load(next);
pubsub.publish('blacklist:reload');
},
], callback);
}; };
Blacklist.get = function (callback) { Blacklist.get = async function () {
async.waterfall([ const data = await db.getObject('ip-blacklist-rules');
function (next) { return data && data.rules;
db.getObject('ip-blacklist-rules', next);
},
function (data, next) {
next(null, data && data.rules);
},
], callback);
}; };
Blacklist.test = function (clientIp, callback) { Blacklist.test = async function (clientIp) {
// Some handy test addresses // Some handy test addresses
// clientIp = '2001:db8:85a3:0:0:8a2e:370:7334'; // IPv6 // clientIp = '2001:db8:85a3:0:0:8a2e:370:7334'; // IPv6
// clientIp = '127.0.15.1'; // IPv4 // clientIp = '127.0.15.1'; // IPv4
// clientIp = '127.0.15.1:3443'; // IPv4 with port strip port to not fail // clientIp = '127.0.15.1:3443'; // IPv4 with port strip port to not fail
if (!clientIp) { if (!clientIp) {
return setImmediate(callback); return;
} }
clientIp = clientIp.split(':').length === 2 ? clientIp.split(':')[0] : clientIp; clientIp = clientIp.split(':').length === 2 ? clientIp.split(':')[0] : clientIp;
@ -76,7 +57,7 @@ Blacklist.test = function (clientIp, callback) {
addr = ipaddr.parse(clientIp); addr = ipaddr.parse(clientIp);
} catch (err) { } catch (err) {
winston.error('[meta/blacklist] Error parsing client IP : ' + clientIp); winston.error('[meta/blacklist] Error parsing client IP : ' + clientIp);
return callback(err); throw err;
} }
if ( if (
@ -90,26 +71,23 @@ Blacklist.test = function (clientIp, callback) {
return addr.match(cidr); return addr.match(cidr);
}) // not in a blacklisted IPv4 or IPv6 cidr range }) // not in a blacklisted IPv4 or IPv6 cidr range
) { ) {
plugins.fireHook('filter:blacklist.test', { // To return test failure, pass back an error in callback try {
ip: clientIp, // To return test failure, pass back an error in callback
}, function (err) { await plugins.fireHook('filter:blacklist.test', { ip: clientIp });
if (err) { } catch (err) {
analytics.increment('blacklist'); analytics.increment('blacklist');
} throw err;
}
callback(err);
});
} else { } else {
var err = new Error('[[error:blacklisted-ip]]'); var err = new Error('[[error:blacklisted-ip]]');
err.code = 'blacklisted-ip'; err.code = 'blacklisted-ip';
analytics.increment('blacklist'); analytics.increment('blacklist');
throw err;
setImmediate(callback, err);
} }
}; };
Blacklist.validate = function (rules, callback) { Blacklist.validate = function (rules) {
rules = (rules || '').split('\n'); rules = (rules || '').split('\n');
var ipv4 = []; var ipv4 = [];
var ipv6 = []; var ipv6 = [];
@ -170,7 +148,7 @@ Blacklist.validate = function (rules, callback) {
return false; return false;
}); });
callback(null, { return {
numRules: rules.length + invalid.length, numRules: rules.length + invalid.length,
ipv4: ipv4, ipv4: ipv4,
ipv6: ipv6, ipv6: ipv6,
@ -178,25 +156,17 @@ Blacklist.validate = function (rules, callback) {
valid: rules, valid: rules,
invalid: invalid, invalid: invalid,
duplicateCount: duplicateCount, duplicateCount: duplicateCount,
}); };
}; };
Blacklist.addRule = function (rule, callback) { Blacklist.addRule = async function (rule) {
var valid; var valid;
async.waterfall([ const result = Blacklist.validate(rule);
function (next) { valid = result.valid;
Blacklist.validate(rule, next); if (!valid.length) {
}, throw new Error('[[error:invalid-rule]]');
function (result, next) { }
valid = result.valid; let rules = await Blacklist.get();
if (!valid.length) { rules = rules + '\n' + valid[0];
return next(new Error('[[error:invalid-rule]]')); await Blacklist.save(rules);
}
Blacklist.get(next);
},
function (rules, next) {
rules = rules + '\n' + valid[0];
Blacklist.save(rules, next);
},
], callback);
}; };

@ -10,7 +10,8 @@ var events = require('../events');
var SocketBlacklist = module.exports; var SocketBlacklist = module.exports;
SocketBlacklist.validate = function (socket, data, callback) { SocketBlacklist.validate = function (socket, data, callback) {
meta.blacklist.validate(data.rules, callback); const rules = meta.blacklist.validate(data.rules);
callback(null, rules);
}; };
SocketBlacklist.save = function (socket, rules, callback) { SocketBlacklist.save = function (socket, rules, callback) {

@ -123,8 +123,12 @@ function initializeNodeBB(callback) {
routes(app, middleware, next); routes(app, middleware, next);
}, },
meta.sounds.addUploads, meta.sounds.addUploads,
meta.blacklist.load, function (next) {
flags.init, meta.blacklist.load(next);
},
function (next) {
flags.init(next);
},
], function (err) { ], function (err) {
callback(err); callback(err);
}); });

Loading…
Cancel
Save