From 235d836f5b70971da38ca4e960d4eb8cf9124b07 Mon Sep 17 00:00:00 2001 From: xangelo Date: Fri, 25 Aug 2023 10:39:45 -0400 Subject: [PATCH] fix: rate limit fights! You can only start 1 fight every 2 seconds. --- package-lock.json | 18 ++++++++++++++++++ package.json | 1 + src/server/api.ts | 14 +++++++++++++- 3 files changed, 32 insertions(+), 1 deletion(-) diff --git a/package-lock.json b/package-lock.json index 88e09fe..a371720 100644 --- a/package-lock.json +++ b/package-lock.json @@ -18,6 +18,7 @@ "csv-parse": "^5.4.0", "dotenv": "^16.0.3", "express": "^4.18.2", + "express-rate-limit": "^6.9.0", "ioredis": "^5.3.2", "knex": "^2.4.2", "lodash": "^4.17.21", @@ -6615,6 +6616,17 @@ "node": ">= 0.10.0" } }, + "node_modules/express-rate-limit": { + "version": "6.9.0", + "resolved": "https://registry.npmjs.org/express-rate-limit/-/express-rate-limit-6.9.0.tgz", + "integrity": "sha512-AnISR3V8qy4gpKM62/TzYdoFO9NV84fBx0POXzTryHU/qGUJBWuVGd+JhbvtVmKBv37t8/afmqdnv16xWoQxag==", + "engines": { + "node": ">= 14.0.0" + }, + "peerDependencies": { + "express": "^4 || ^5" + } + }, "node_modules/express/node_modules/body-parser": { "version": "1.20.1", "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.1.tgz", @@ -16898,6 +16910,12 @@ } } }, + "express-rate-limit": { + "version": "6.9.0", + "resolved": "https://registry.npmjs.org/express-rate-limit/-/express-rate-limit-6.9.0.tgz", + "integrity": "sha512-AnISR3V8qy4gpKM62/TzYdoFO9NV84fBx0POXzTryHU/qGUJBWuVGd+JhbvtVmKBv37t8/afmqdnv16xWoQxag==", + "requires": {} + }, "extend": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", diff --git a/package.json b/package.json index cfc0057..1f3d2aa 100644 --- a/package.json +++ b/package.json @@ -52,6 +52,7 @@ "csv-parse": "^5.4.0", "dotenv": "^16.0.3", "express": "^4.18.2", + "express-rate-limit": "^6.9.0", "ioredis": "^5.3.2", "knex": "^2.4.2", "lodash": "^4.17.21", diff --git a/src/server/api.ts b/src/server/api.ts index 4a176dd..60c2b5c 100644 --- a/src/server/api.ts +++ b/src/server/api.ts @@ -5,6 +5,7 @@ import { join } from 'path'; import express, {Request, Response} from 'express'; import bodyParser from 'body-parser'; import xss from 'xss'; +import { rateLimit } from 'express-rate-limit'; import http from 'http'; import { Server, Socket } from 'socket.io'; @@ -71,6 +72,17 @@ app.use((req, res, next) => { next(); }); +const fightRateLimiter = rateLimit({ + windowMs: parseInt(process.env.RATE_LIMIT_WINDOW || '30000'), + max: parseInt(process.env.RATE_LIMIT_MAX_REQUESTS || '20'), + standardHeaders: true, + legacyHeaders: false, + handler: (req, res, next, options) => { + logger.log(`Blocked request: [${req.headers['x-authtoken']}: ${req.method} ${req.path}]`); + res.status(options.statusCode).send(options.message); + } +}); + async function bootstrapSocket(socket: Socket, player: Player) { // ref to get the socket id for a particular player cache.set(`socket:${player.id}`, socket.id); @@ -615,7 +627,7 @@ app.post('/fight/turn', authEndpoint, async (req: AuthRequest, res: Response) => res.send(html + travelSection + playerBar); }); -app.post('/fight', authEndpoint, async (req: AuthRequest, res: Response) => { +app.post('/fight', fightRateLimiter, authEndpoint, async (req: AuthRequest, res: Response) => { if(req.player.hp <= 0) { logger.log(`Player didn\'t have enough hp`); return res.sendStatus(400); -- 2.25.1