mirror of
https://github.com/Ylianst/MeshCentral.git
synced 2024-11-22 22:17:31 +03:00
Added bad login IP address limitation.
This commit is contained in:
parent
dfbd933dc7
commit
c9dc923db1
16
db.js
16
db.js
@ -677,7 +677,13 @@ module.exports.CreateDB = function (parent, func) {
|
|||||||
// TODO: Starting in MongoDB 4.0.3, you should use countDocuments() instead of count() that is deprecated. We should detect MongoDB version and switch.
|
// TODO: Starting in MongoDB 4.0.3, you should use countDocuments() instead of count() that is deprecated. We should detect MongoDB version and switch.
|
||||||
// https://docs.mongodb.com/manual/reference/method/db.collection.countDocuments/
|
// https://docs.mongodb.com/manual/reference/method/db.collection.countDocuments/
|
||||||
//obj.isMaxType = function (max, type, domainid, func) { if (max == null) { func(false); } else { obj.file.countDocuments({ type: type, domain: domainid }, function (err, count) { func((err != null) || (count > max)); }); } }
|
//obj.isMaxType = function (max, type, domainid, func) { if (max == null) { func(false); } else { obj.file.countDocuments({ type: type, domain: domainid }, function (err, count) { func((err != null) || (count > max)); }); } }
|
||||||
obj.isMaxType = function (max, type, domainid, func) { if (max == null) { func(false); } else { obj.file.count({ type: type, domain: domainid }, function (err, count) { func((err != null) || (count > max), count); }); } }
|
obj.isMaxType = function (max, type, domainid, func) {
|
||||||
|
if (obj.eventsfile.countDocuments) {
|
||||||
|
if (max == null) { func(false); } else { obj.file.countDocuments({ type: type, domain: domainid }, function (err, count) { func((err != null) || (count > max), count); }); }
|
||||||
|
} else {
|
||||||
|
if (max == null) { func(false); } else { obj.file.count({ type: type, domain: domainid }, function (err, count) { func((err != null) || (count > max), count); }); }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Database actions on the events collection
|
// Database actions on the events collection
|
||||||
obj.GetAllEvents = function (func) { obj.eventsfile.find({}).toArray(func); };
|
obj.GetAllEvents = function (func) { obj.eventsfile.find({}).toArray(func); };
|
||||||
@ -693,7 +699,13 @@ module.exports.CreateDB = function (parent, func) {
|
|||||||
obj.GetNodeEventsSelfWithLimit = function (nodeid, domain, userid, limit, func) { obj.eventsfile.find({ domain: domain, nodeid: nodeid, userid: { $in: [userid, null] } }).project({ type: 0, etype: 0, _id: 0, domain: 0, ids: 0, node: 0, nodeid: 0 }).sort({ time: -1 }).limit(limit).toArray(func); };
|
obj.GetNodeEventsSelfWithLimit = function (nodeid, domain, userid, limit, func) { obj.eventsfile.find({ domain: domain, nodeid: nodeid, userid: { $in: [userid, null] } }).project({ type: 0, etype: 0, _id: 0, domain: 0, ids: 0, node: 0, nodeid: 0 }).sort({ time: -1 }).limit(limit).toArray(func); };
|
||||||
obj.RemoveAllEvents = function (domain) { obj.eventsfile.deleteMany({ domain: domain }, { multi: true }); };
|
obj.RemoveAllEvents = function (domain) { obj.eventsfile.deleteMany({ domain: domain }, { multi: true }); };
|
||||||
obj.RemoveAllNodeEvents = function (domain, nodeid) { obj.eventsfile.deleteMany({ domain: domain, nodeid: nodeid }, { multi: true }); };
|
obj.RemoveAllNodeEvents = function (domain, nodeid) { obj.eventsfile.deleteMany({ domain: domain, nodeid: nodeid }, { multi: true }); };
|
||||||
obj.GetFailedLoginCount = function (username, domainid, lastlogin, func) { obj.eventsfile.count({ action: 'authfail', username: username, domain: domainid, time: { "$gte": lastlogin } }, function (err, count) { func((err == null)?count:0); }); }
|
obj.GetFailedLoginCount = function (username, domainid, lastlogin, func) {
|
||||||
|
if (obj.eventsfile.countDocuments) {
|
||||||
|
obj.eventsfile.countDocuments({ action: 'authfail', username: username, domain: domainid, time: { "$gte": lastlogin } }, function (err, count) { func((err == null) ? count : 0); });
|
||||||
|
} else {
|
||||||
|
obj.eventsfile.count({ action: 'authfail', username: username, domain: domainid, time: { "$gte": lastlogin } }, function (err, count) { func((err == null) ? count : 0); });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Database actions on the power collection
|
// Database actions on the power collection
|
||||||
obj.getAllPower = function (func) { obj.powerfile.find({}).toArray(func); };
|
obj.getAllPower = function (func) { obj.powerfile.find({}).toArray(func); };
|
||||||
|
@ -223,7 +223,6 @@ module.exports.CreateLetsEncrypt = function (parent) {
|
|||||||
var somethingIsinFolder = false;
|
var somethingIsinFolder = false;
|
||||||
try {
|
try {
|
||||||
var filesinFolder = require('fs').readdirSync(obj.runAsProduction ? obj.configPath : obj.configPathStaging);
|
var filesinFolder = require('fs').readdirSync(obj.runAsProduction ? obj.configPath : obj.configPathStaging);
|
||||||
console.log('filesinFolder', filesinFolder);
|
|
||||||
somethingIsinFolder = (filesinFolder.indexOf(obj.runAsProduction ? 'live' : 'staging') != -1);
|
somethingIsinFolder = (filesinFolder.indexOf(obj.runAsProduction ? 'live' : 'staging') != -1);
|
||||||
} catch (ex) { console.log(ex); }
|
} catch (ex) { console.log(ex); }
|
||||||
|
|
||||||
|
14
meshuser.js
14
meshuser.js
@ -689,14 +689,20 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use
|
|||||||
case 'help': {
|
case 'help': {
|
||||||
r = 'Available commands: help, info, versions, args, resetserver, showconfig, usersessions, tasklimiter, setmaxtasks, cores,\r\n'
|
r = 'Available commands: help, info, versions, args, resetserver, showconfig, usersessions, tasklimiter, setmaxtasks, cores,\r\n'
|
||||||
r += 'migrationagents, agentstats, webstats, mpsstats, swarmstats, acceleratorsstats, updatecheck, serverupdate, nodeconfig,\r\n';
|
r += 'migrationagents, agentstats, webstats, mpsstats, swarmstats, acceleratorsstats, updatecheck, serverupdate, nodeconfig,\r\n';
|
||||||
r += 'heapdump, relays, autobackup, backupconfig, dupagents, dispatchtable.';
|
r += 'heapdump, relays, autobackup, backupconfig, dupagents, dispatchtable, badlogins.';
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 'badlogins': {
|
||||||
|
r = "Max is " + parent.parent.config.settings.maxinvalidlogin.count + " bad login(s) in " + parent.parent.config.settings.maxinvalidlogin.time + " minute(s).\r\n";
|
||||||
|
var badLoginCount = 0;
|
||||||
|
parent.cleanBadLoginTable();
|
||||||
|
for (var i in parent.badLoginTable) { badLoginCount++; r += (i + ' - ' + parent.badLoginTable[i].length + " entries\r\n"); }
|
||||||
|
if (badLoginCount == 0) { r += 'No bad logins.'; }
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 'dispatchtable': {
|
case 'dispatchtable': {
|
||||||
r = '';
|
r = '';
|
||||||
for (var i in parent.parent.eventsDispatch) {
|
for (var i in parent.parent.eventsDispatch) { r += (i + ', ' + parent.parent.eventsDispatch[i].length + '\r\n'); }
|
||||||
r += (i + ', ' + parent.parent.eventsDispatch[i].length + '\r\n');
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 'dupagents': {
|
case 'dupagents': {
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "meshcentral",
|
"name": "meshcentral",
|
||||||
"version": "0.4.4-l",
|
"version": "0.4.4-m",
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"Remote Management",
|
"Remote Management",
|
||||||
"Intel AMT",
|
"Intel AMT",
|
||||||
|
@ -58,7 +58,9 @@
|
|||||||
},
|
},
|
||||||
"_Redirects": {
|
"_Redirects": {
|
||||||
"meshcommander": "https://www.meshcommander.com/"
|
"meshcommander": "https://www.meshcommander.com/"
|
||||||
}
|
},
|
||||||
|
"__MaxInvalidLogin": "Time in minutes, max amount of bad logins from a source IP in the time before logins are rejected.",
|
||||||
|
"MaxInvalidLogin": { "time": 10, "count": 10 }
|
||||||
},
|
},
|
||||||
"_domains": {
|
"_domains": {
|
||||||
"": {
|
"": {
|
||||||
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@ -270,7 +270,7 @@
|
|||||||
// Display the right server message
|
// Display the right server message
|
||||||
var messageid = parseInt('{{{messageid}}}');
|
var messageid = parseInt('{{{messageid}}}');
|
||||||
var okmessages = ['', "Hold on, reset mail sent."];
|
var okmessages = ['', "Hold on, reset mail sent."];
|
||||||
var failmessages = ["Unable to create account.", "Account limit reached.", "Existing account with this email address.", "Invalid account creation token.", "Username already exists.", "Password rejected, use a different one.", "Invalid email.", "Account not found.", "Invalid token, try again.", "Unable to sent email.", "Account locked.", "Access denied.", "Login failed, check username and password.", "Password change requested."];
|
var failmessages = ["Unable to create account.", "Account limit reached.", "Existing account with this email address.", "Invalid account creation token.", "Username already exists.", "Password rejected, use a different one.", "Invalid email.", "Account not found.", "Invalid token, try again.", "Unable to sent email.", "Account locked.", "Access denied.", "Login failed, check username and password.", "Password change requested.", "IP address blocked, try again later."];
|
||||||
if (messageid > 0) {
|
if (messageid > 0) {
|
||||||
var msg = '';
|
var msg = '';
|
||||||
if ((messageid < 100) && (messageid < okmessages.length)) { msg = okmessages[messageid]; }
|
if ((messageid < 100) && (messageid < okmessages.length)) { msg = okmessages[messageid]; }
|
||||||
|
@ -267,7 +267,7 @@
|
|||||||
// Display the right server message
|
// Display the right server message
|
||||||
var messageid = parseInt('{{{messageid}}}');
|
var messageid = parseInt('{{{messageid}}}');
|
||||||
var okmessages = ['', "Hold on, reset mail sent."];
|
var okmessages = ['', "Hold on, reset mail sent."];
|
||||||
var failmessages = ["Unable to create account.", "Account limit reached.", "Existing account with this email address.", "Invalid account creation token.", "Username already exists.", "Password rejected, use a different one.", "Invalid email.", "Account not found.", "Invalid token, try again.", "Unable to sent email.", "Account locked.", "Access denied.", "Login failed, check username and password.", "Password change requested."];
|
var failmessages = ["Unable to create account.", "Account limit reached.", "Existing account with this email address.", "Invalid account creation token.", "Username already exists.", "Password rejected, use a different one.", "Invalid email.", "Account not found.", "Invalid token, try again.", "Unable to sent email.", "Account locked.", "Access denied.", "Login failed, check username and password.", "Password change requested.", "IP address blocked, try again later."];
|
||||||
if (messageid > 0) {
|
if (messageid > 0) {
|
||||||
var msg = '';
|
var msg = '';
|
||||||
if ((messageid < 100) && (messageid < okmessages.length)) { msg = okmessages[messageid]; }
|
if ((messageid < 100) && (messageid < okmessages.length)) { msg = okmessages[messageid]; }
|
||||||
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@ -268,7 +268,7 @@
|
|||||||
// Display the right server message
|
// Display the right server message
|
||||||
var messageid = parseInt('{{{messageid}}}');
|
var messageid = parseInt('{{{messageid}}}');
|
||||||
var okmessages = ['', "Hold on, reset mail sent."];
|
var okmessages = ['', "Hold on, reset mail sent."];
|
||||||
var failmessages = ["Unable to create account.", "Account limit reached.", "Existing account with this email address.", "Invalid account creation token.", "Username already exists.", "Password rejected, use a different one.", "Invalid email.", "Account not found.", "Invalid token, try again.", "Unable to sent email.", "Account locked.", "Access denied.", "Login failed, check username and password.", "Password change requested."];
|
var failmessages = ["Unable to create account.", "Account limit reached.", "Existing account with this email address.", "Invalid account creation token.", "Username already exists.", "Password rejected, use a different one.", "Invalid email.", "Account not found.", "Invalid token, try again.", "Unable to sent email.", "Account locked.", "Access denied.", "Login failed, check username and password.", "Password change requested.", "IP address blocked, try again later."];
|
||||||
if (messageid > 0) {
|
if (messageid > 0) {
|
||||||
var msg = '';
|
var msg = '';
|
||||||
if ((messageid < 100) && (messageid < okmessages.length)) { msg = okmessages[messageid]; }
|
if ((messageid < 100) && (messageid < okmessages.length)) { msg = okmessages[messageid]; }
|
||||||
|
@ -265,7 +265,7 @@
|
|||||||
// Display the right server message
|
// Display the right server message
|
||||||
var messageid = parseInt('{{{messageid}}}');
|
var messageid = parseInt('{{{messageid}}}');
|
||||||
var okmessages = ['', "Hold on, reset mail sent."];
|
var okmessages = ['', "Hold on, reset mail sent."];
|
||||||
var failmessages = ["Unable to create account.", "Account limit reached.", "Existing account with this email address.", "Invalid account creation token.", "Username already exists.", "Password rejected, use a different one.", "Invalid email.", "Account not found.", "Invalid token, try again.", "Unable to sent email.", "Account locked.", "Access denied.", "Login failed, check username and password.", "Password change requested."];
|
var failmessages = ["Unable to create account.", "Account limit reached.", "Existing account with this email address.", "Invalid account creation token.", "Username already exists.", "Password rejected, use a different one.", "Invalid email.", "Account not found.", "Invalid token, try again.", "Unable to sent email.", "Account locked.", "Access denied.", "Login failed, check username and password.", "Password change requested.", "IP address blocked, try again later."];
|
||||||
if (messageid > 0) {
|
if (messageid > 0) {
|
||||||
var msg = '';
|
var msg = '';
|
||||||
if ((messageid < 100) && (messageid < okmessages.length)) { msg = okmessages[messageid]; }
|
if ((messageid < 100) && (messageid < okmessages.length)) { msg = okmessages[messageid]; }
|
||||||
|
48
webserver.js
48
webserver.js
@ -639,6 +639,16 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) {
|
|||||||
const domain = checkUserIpAddress(req, res);
|
const domain = checkUserIpAddress(req, res);
|
||||||
if (domain == null) { parent.debug('web', 'handleLoginRequest: invalid domain'); res.sendStatus(404); return; }
|
if (domain == null) { parent.debug('web', 'handleLoginRequest: invalid domain'); res.sendStatus(404); return; }
|
||||||
|
|
||||||
|
// Check if this is a banned ip address
|
||||||
|
if (obj.checkAllowLogin(req) == false) {
|
||||||
|
// Wait and redirect the user
|
||||||
|
setTimeout(function () {
|
||||||
|
req.session.messageid = 114; // IP address blocked, try again later.
|
||||||
|
if (direct === true) { handleRootRequestEx(req, res, domain); } else { res.redirect(domain.url + getQueryPortion(req)); }
|
||||||
|
}, 2000 + (obj.crypto.randomBytes(2).readUInt16BE(0) % 4095));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// Normally, use the body username/password. If this is a token, use the username/password in the session.
|
// Normally, use the body username/password. If this is a token, use the username/password in the session.
|
||||||
var xusername = req.body.username, xpassword = req.body.password;
|
var xusername = req.body.username, xpassword = req.body.password;
|
||||||
if ((xusername == null) && (xpassword == null) && (req.body.token != null)) { xusername = req.session.tokenusername; xpassword = req.session.tokenpassword; }
|
if ((xusername == null) && (xpassword == null) && (req.body.token != null)) { xusername = req.session.tokenusername; xpassword = req.session.tokenpassword; }
|
||||||
@ -660,6 +670,7 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) {
|
|||||||
req.session.messageid = 108; // Invalid token, try again.
|
req.session.messageid = 108; // Invalid token, try again.
|
||||||
parent.debug('web', 'handleLoginRequest: invalid 2FA token');
|
parent.debug('web', 'handleLoginRequest: invalid 2FA token');
|
||||||
obj.parent.DispatchEvent(['*', 'server-users', 'user/' + domain.id + '/' + user.name], obj, { action: 'authfail', username: user.name, userid: 'user/' + domain.id + '/' + user.name, domain: domain.id, msg: 'User login attempt with incorrect 2nd factor from ' + cleanRemoteAddr(req.ip) });
|
obj.parent.DispatchEvent(['*', 'server-users', 'user/' + domain.id + '/' + user.name], obj, { action: 'authfail', username: user.name, userid: 'user/' + domain.id + '/' + user.name, domain: domain.id, msg: 'User login attempt with incorrect 2nd factor from ' + cleanRemoteAddr(req.ip) });
|
||||||
|
obj.setbadLogin(req);
|
||||||
} else {
|
} else {
|
||||||
parent.debug('web', 'handleLoginRequest: 2FA token required');
|
parent.debug('web', 'handleLoginRequest: 2FA token required');
|
||||||
}
|
}
|
||||||
@ -693,10 +704,12 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) {
|
|||||||
parent.debug('web', 'handleLoginRequest: login failed, locked account');
|
parent.debug('web', 'handleLoginRequest: login failed, locked account');
|
||||||
req.session.messageid = 110; // Account locked.
|
req.session.messageid = 110; // Account locked.
|
||||||
obj.parent.DispatchEvent(['*', 'server-users', xuserid], obj, { action: 'authfail', userid: xuserid, username: xusername, domain: domain.id, msg: 'User login attempt on locked account from ' + cleanRemoteAddr(req.ip) });
|
obj.parent.DispatchEvent(['*', 'server-users', xuserid], obj, { action: 'authfail', userid: xuserid, username: xusername, domain: domain.id, msg: 'User login attempt on locked account from ' + cleanRemoteAddr(req.ip) });
|
||||||
|
obj.setbadLogin(req);
|
||||||
} else {
|
} else {
|
||||||
parent.debug('web', 'handleLoginRequest: login failed, bad username and password');
|
parent.debug('web', 'handleLoginRequest: login failed, bad username and password');
|
||||||
req.session.messageid = 112; // Login failed, check username and password.
|
req.session.messageid = 112; // Login failed, check username and password.
|
||||||
obj.parent.DispatchEvent(['*', 'server-users', xuserid], obj, { action: 'authfail', userid: xuserid, username: xusername, domain: domain.id, msg: 'Invalid user login attempt from ' + cleanRemoteAddr(req.ip) });
|
obj.parent.DispatchEvent(['*', 'server-users', xuserid], obj, { action: 'authfail', userid: xuserid, username: xusername, domain: domain.id, msg: 'Invalid user login attempt from ' + cleanRemoteAddr(req.ip) });
|
||||||
|
obj.setbadLogin(req);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1015,6 +1028,7 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) {
|
|||||||
if ((req.body.token != null) || (req.body.hwtoken != null)) {
|
if ((req.body.token != null) || (req.body.hwtoken != null)) {
|
||||||
req.session.messageid = 108; // Invalid token, try again.
|
req.session.messageid = 108; // Invalid token, try again.
|
||||||
obj.parent.DispatchEvent(['*', 'server-users', 'user/' + domain.id + '/' + user.name], obj, { action: 'authfail', username: user.name, userid: 'user/' + domain.id + '/' + user.name, domain: domain.id, msg: 'User login attempt with incorrect 2nd factor from ' + cleanRemoteAddr(req.ip) });
|
obj.parent.DispatchEvent(['*', 'server-users', 'user/' + domain.id + '/' + user.name], obj, { action: 'authfail', username: user.name, userid: 'user/' + domain.id + '/' + user.name, domain: domain.id, msg: 'User login attempt with incorrect 2nd factor from ' + cleanRemoteAddr(req.ip) });
|
||||||
|
obj.setbadLogin(req);
|
||||||
}
|
}
|
||||||
req.session.loginmode = '5';
|
req.session.loginmode = '5';
|
||||||
req.session.tokenemail = email;
|
req.session.tokenemail = email;
|
||||||
@ -3434,6 +3448,8 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) {
|
|||||||
|
|
||||||
// Authenticates a session and forwards
|
// Authenticates a session and forwards
|
||||||
function PerformWSSessionAuth(ws, req, noAuthOk, func) {
|
function PerformWSSessionAuth(ws, req, noAuthOk, func) {
|
||||||
|
// Check if this is a banned ip address
|
||||||
|
if (obj.checkAllowLogin(req) == false) { try { ws.send(JSON.stringify({ action: 'close', cause: 'banned', msg: 'banned-1' })); ws.close(); } catch (e) { } return; }
|
||||||
try {
|
try {
|
||||||
// Hold this websocket until we are ready.
|
// Hold this websocket until we are ready.
|
||||||
ws._socket.pause();
|
ws._socket.pause();
|
||||||
@ -3476,6 +3492,7 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) {
|
|||||||
// If not authenticated, close the websocket connection
|
// If not authenticated, close the websocket connection
|
||||||
parent.debug('web', 'ERR: Websocket bad user/pass auth');
|
parent.debug('web', 'ERR: Websocket bad user/pass auth');
|
||||||
//obj.parent.DispatchEvent(['*', 'server-users', 'user/' + domain.id + '/' + obj.args.user.toLowerCase()], obj, { action: 'authfail', userid: 'user/' + domain.id + '/' + obj.args.user.toLowerCase(), username: obj.args.user, domain: domain.id, msg: 'Invalid user login attempt from ' + cleanRemoteAddr(req.ip) });
|
//obj.parent.DispatchEvent(['*', 'server-users', 'user/' + domain.id + '/' + obj.args.user.toLowerCase()], obj, { action: 'authfail', userid: 'user/' + domain.id + '/' + obj.args.user.toLowerCase(), username: obj.args.user, domain: domain.id, msg: 'Invalid user login attempt from ' + cleanRemoteAddr(req.ip) });
|
||||||
|
//obj.setbadLogin(req);
|
||||||
try { ws.send(JSON.stringify({ action: 'close', cause: 'noauth', msg: 'noauth-2' })); ws.close(); } catch (e) { }
|
try { ws.send(JSON.stringify({ action: 'close', cause: 'noauth', msg: 'noauth-2' })); ws.close(); } catch (e) { }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -4014,5 +4031,36 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) {
|
|||||||
} catch (ex) { console.log(ex); func(fd, tag); }
|
} catch (ex) { console.log(ex); func(fd, tag); }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// This is the invalid login throttling code
|
||||||
|
obj.badLoginTable = {};
|
||||||
|
obj.badLoginTableLastClean = 0;
|
||||||
|
if (parent.config.settings == null) { parent.config.settings = {}; }
|
||||||
|
if (parent.config.settings.maxinvalidlogin == null) { parent.config.settings.maxinvalidlogin = { time: 10, count: 10 }; }
|
||||||
|
if (typeof parent.config.settings.maxinvalidlogin.time != 'number') { parent.config.settings.maxinvalidlogin.time = 10; }
|
||||||
|
if (typeof parent.config.settings.maxinvalidlogin.count != 'number') { parent.config.settings.maxinvalidlogin.count = 10; }
|
||||||
|
obj.setbadLogin = function (ip) { // Set an IP address that just did a bad login request
|
||||||
|
if (typeof ip == 'object') { ip = cleanRemoteAddr(ip.ip); }
|
||||||
|
if (++obj.badLoginTableLastClean > 100) { obj.cleanBadLoginTable(); }
|
||||||
|
if (obj.badLoginTable[ip] == null) { obj.badLoginTable[ip] = [Date.now()]; } else { obj.badLoginTable[ip].push(Date.now()); }
|
||||||
|
}
|
||||||
|
obj.checkAllowLogin = function (ip) { // Check if an IP address is allowed to login
|
||||||
|
if (typeof ip == 'object') { ip = cleanRemoteAddr(ip.ip); }
|
||||||
|
var cutoffTime = Date.now() - (parent.config.settings.maxinvalidlogin.time * 60000); // Time in minutes
|
||||||
|
var ipTable = obj.badLoginTable[ip];
|
||||||
|
if (ipTable == null) return true;
|
||||||
|
while ((ipTable.length > 0) && (ipTable[0] < cutoffTime)) { ipTable.shift(); }
|
||||||
|
if (ipTable.length == 0) { delete obj.badLoginTable[ip]; return true; }
|
||||||
|
return (ipTable.length < parent.config.settings.maxinvalidlogin.count); // No more than x bad logins in x minutes
|
||||||
|
}
|
||||||
|
obj.cleanBadLoginTable = function () { // Clean up the IP address login blockage table, we do this occasionaly.
|
||||||
|
var cutoffTime = Date.now() - (parent.config.settings.maxinvalidlogin.time * 60000); // Time in minutes
|
||||||
|
for (var i in ipTable) {
|
||||||
|
var ipTable = obj.badLoginTable[ip];
|
||||||
|
while ((ipTable.length > 0) && (ipTable[0] < cutoffTime)) { ipTable.shift(); }
|
||||||
|
if (ipTable.length == 0) { delete obj.badLoginTable[ip]; }
|
||||||
|
}
|
||||||
|
obj.badLoginTableLastClean = 0;
|
||||||
|
}
|
||||||
|
|
||||||
return obj;
|
return obj;
|
||||||
};
|
};
|
Loading…
Reference in New Issue
Block a user