Impliment basic rate limiting

This commit is contained in:
Christopher Cookman 2024-12-23 16:31:17 -07:00
parent 2b306d60b7
commit 9470ded1e8
4 changed files with 50 additions and 2 deletions

View file

@ -77,6 +77,9 @@ app.use((req, res, next) => {
next() next()
}); });
// Rate Limit middleware from scratch
const rateLimit = require('./rateLimit.js');
// The very very few direct routes // The very very few direct routes
app.get("/", (req, res) => { app.get("/", (req, res) => {
const readmePath = path.join(__dirname, 'README.md'); const readmePath = path.join(__dirname, 'README.md');
@ -98,7 +101,7 @@ app.get("/", (req, res) => {
var cached_invite = { code: "", expires: 0 } var cached_invite = { code: "", expires: 0 }
app.get('/discord', async (req, res) => { app.get('/discord', rateLimit.middleware, async (req, res) => {
if (cached_invite.expires > Date.now()) { if (cached_invite.expires > Date.now()) {
return res.redirect(`https://discord.gg/${cached_invite.code}`) return res.redirect(`https://discord.gg/${cached_invite.code}`)
} else { } else {

40
rateLimit.js Normal file
View file

@ -0,0 +1,40 @@
const { message } = require("noblox.js");
if (!global.rateLimitList) {
global.rateLimitList = {};
}
const middleware = (req, res, next) => {
console.log(global.rateLimitList)
// X requests per Y seconds per IP address
const maxRequests = process.env.RATE_LIMIT_MAX || 30;
const timeWindow = process.env.RATE_LIMIT_TIME || 60;
var requestIp = req.ip;
if (process.env.TRUST_PROXY && (req.ip == `::ffff:${process.env.PROXY_IP}` || req.ip == process.env.PROXY_IP)) {
requestIp = req.headers["x-forwarded-for"];
}
if (!global.rateLimitList[requestIp]) {
global.rateLimitList[requestIp] = { requests: 0, lastRequest: Date.now() };
}
if (global.rateLimitList[requestIp].lastRequest + timeWindow * 1000 < Date.now()) {
global.rateLimitList[requestIp] = { requests: 0, lastRequest: Date.now() };
} else {
if (global.rateLimitList[requestIp].requests >= maxRequests) {
return res.status(429).json({ completed: false, success: false, error: "Rate limit exceeded", message: "You have been rate limited. Please try again later.", expires: global.rateLimitList[requestIp].lastRequest + timeWindow * 1000 });
} else {
global.rateLimitList[requestIp].lastRequest = Date.now();
}
}
global.rateLimitList[requestIp].requests++;
next();
}
const getRateLimit = () => {
return global.global.rateLimitList;
}
module.exports = {
middleware,
getRateLimit
}

View file

@ -235,7 +235,9 @@ router.get('/login', (req, res) => {
res.render('admin/login', { env: process.env }); res.render('admin/login', { env: process.env });
}); });
router.post('/login', async (req, res) => { const rateLimit = require('../rateLimit.js');
router.post('/login', rateLimit.middleware, async (req, res) => {
const conn = await pool.getConnection(); const conn = await pool.getConnection();
const username = req.body.username; const username = req.body.username;
const password = req.body.password; const password = req.body.password;

View file

@ -7,6 +7,9 @@ const { execSync } = require('child_process');
// Create a MariaDB connection pool // Create a MariaDB connection pool
const pool = global.db_pool const pool = global.db_pool
const rateLimit = require('../rateLimit.js');
router.use(rateLimit.middleware);
router.get("/health", async (req,res) => { router.get("/health", async (req,res) => {
try { try {
// Get a connection from the pool // Get a connection from the pool