60 lines
1.8 KiB
JavaScript
60 lines
1.8 KiB
JavaScript
const fs = require('fs');
|
|
const path = require('path');
|
|
const { suspiciousLogger } = require('../config/logs');
|
|
|
|
const BAN_LEVELS = [10, 30, 60, Infinity];
|
|
const SUSPICIOUS_REQUEST_LIMIT = 5;
|
|
const BAN_FILE_PATH = path.join(__dirname, '..', 'data', 'banUser.json');
|
|
|
|
const logAndBanSuspiciousActivity = async (req, res, next) => {
|
|
const ip = req.headers['cf-connecting-ip'] || req.headers['x-forwarded-for'] || req.connection.remoteAddress;
|
|
const url = `${req.protocol}://${req.get('host')}${req.originalUrl}`;
|
|
|
|
if (req.originalUrl === '/auth/activedirectory', "/favicon.ico" && req.method === 'POST') {
|
|
next();
|
|
return;
|
|
}
|
|
|
|
let bans;
|
|
try {
|
|
if (!fs.existsSync(BAN_FILE_PATH)) {
|
|
fs.writeFileSync(BAN_FILE_PATH, JSON.stringify({}));
|
|
}
|
|
bans = JSON.parse(fs.readFileSync(BAN_FILE_PATH));
|
|
} catch (err) {
|
|
bans = {};
|
|
}
|
|
|
|
let ban = bans[ip];
|
|
|
|
if (ban) {
|
|
const timeSinceLastRequest = Date.now() - ban.lastRequestTime;
|
|
if (timeSinceLastRequest < 60 * 1000) {
|
|
ban.suspiciousRequestCount++;
|
|
} else {
|
|
ban.suspiciousRequestCount = 1;
|
|
}
|
|
if (ban.suspiciousRequestCount >= SUSPICIOUS_REQUEST_LIMIT) {
|
|
ban.level++;
|
|
ban.suspiciousRequestCount = 0;
|
|
ban.banUntil = Date.now() + BAN_LEVELS[ban.level % BAN_LEVELS.length] * 60 * 1000;
|
|
}
|
|
ban.lastRequestTime = Date.now();
|
|
} else {
|
|
bans[ip] = { level: 0, banUntil: Date.now(), suspiciousRequestCount: 1, lastRequestTime: Date.now() };
|
|
ban = bans[ip];
|
|
}
|
|
|
|
fs.writeFileSync(BAN_FILE_PATH, JSON.stringify(bans));
|
|
|
|
if (ban && Date.now() < ban.banUntil) {
|
|
res.status(403).json({ message: 'You are banned. Please try again later.' });
|
|
return;
|
|
}
|
|
|
|
suspiciousLogger.info(`Suspicious request from IP: ${ip} tried to access ${req.method} ${url}`);
|
|
|
|
next();
|
|
};
|
|
|
|
module.exports = { logAndBanSuspiciousActivity }; |