From 614a2558f525120892e4c4021ae728a4882f543d Mon Sep 17 00:00:00 2001 From: Tuan Dang Date: Tue, 17 Jan 2023 00:50:35 +0700 Subject: [PATCH] Patch IP recognition --- backend/package-lock.json | 11 +++++++++++ backend/package.json | 1 + backend/src/app.ts | 7 +++++-- backend/src/helpers/rateLimiter.ts | 13 +++++++++++-- backend/src/types/express/index.d.ts | 1 + 5 files changed, 29 insertions(+), 4 deletions(-) diff --git a/backend/package-lock.json b/backend/package-lock.json index 38c1126ccf..9caf23dd17 100644 --- a/backend/package-lock.json +++ b/backend/package-lock.json @@ -36,6 +36,7 @@ "nodemailer": "^6.8.0", "posthog-node": "^2.2.2", "query-string": "^7.1.3", + "request-ip": "^3.3.0", "rimraf": "^3.0.2", "stripe": "^10.7.0", "swagger-autogen": "^2.22.0", @@ -10516,6 +10517,11 @@ "url": "https://github.com/sponsors/mysticatea" } }, + "node_modules/request-ip": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/request-ip/-/request-ip-3.3.0.tgz", + "integrity": "sha512-cA6Xh6e0fDBBBwH77SLJaJPBmD3nWVAcF9/XAcsrIHdjhFzFiB5aNQFytdjCGPezU3ROwrR11IddKAM08vohxA==" + }, "node_modules/require-directory": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", @@ -19972,6 +19978,11 @@ "integrity": "sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg==", "dev": true }, + "request-ip": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/request-ip/-/request-ip-3.3.0.tgz", + "integrity": "sha512-cA6Xh6e0fDBBBwH77SLJaJPBmD3nWVAcF9/XAcsrIHdjhFzFiB5aNQFytdjCGPezU3ROwrR11IddKAM08vohxA==" + }, "require-directory": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", diff --git a/backend/package.json b/backend/package.json index b9359f6800..7a1552dd36 100644 --- a/backend/package.json +++ b/backend/package.json @@ -102,6 +102,7 @@ "nodemailer": "^6.8.0", "posthog-node": "^2.2.2", "query-string": "^7.1.3", + "request-ip": "^3.3.0", "rimraf": "^3.0.2", "stripe": "^10.7.0", "swagger-autogen": "^2.22.0", diff --git a/backend/src/app.ts b/backend/src/app.ts index 24b73d7e32..79561d00c0 100644 --- a/backend/src/app.ts +++ b/backend/src/app.ts @@ -8,8 +8,9 @@ import cookieParser from 'cookie-parser'; import dotenv from 'dotenv'; import swaggerUi = require('swagger-ui-express'); // eslint-disable-next-line @typescript-eslint/no-var-requires -const swaggerFile = require('../spec.json') - +const swaggerFile = require('../spec.json'); +// eslint-disable-next-line @typescript-eslint/no-var-requires +const requestIp = require('request-ip'); dotenv.config(); import { PORT, NODE_ENV, SITE_URL } from './config'; @@ -72,6 +73,8 @@ app.use( }) ); +app.use(requestIp.mw()) + if (NODE_ENV === 'production') { // enable app-wide rate-limiting + helmet security // in production diff --git a/backend/src/helpers/rateLimiter.ts b/backend/src/helpers/rateLimiter.ts index b25ee09473..432bd5f975 100644 --- a/backend/src/helpers/rateLimiter.ts +++ b/backend/src/helpers/rateLimiter.ts @@ -8,6 +8,9 @@ const apiLimiter = rateLimit({ legacyHeaders: false, skip: (request) => { return request.path === '/healthcheck' || request.path === '/api/status' + }, + keyGenerator: (req, res) => { + return req.clientIp } }); @@ -16,7 +19,10 @@ const authLimiter = rateLimit({ windowMs: 60 * 1000, max: 10, standardHeaders: true, - legacyHeaders: false + legacyHeaders: false, + keyGenerator: (req, res) => { + return req.clientIp + } }); // 10 requests per hour @@ -24,7 +30,10 @@ const passwordLimiter = rateLimit({ windowMs: 60 * 60 * 1000, max: 10, standardHeaders: true, - legacyHeaders: false + legacyHeaders: false, + keyGenerator: (req, res) => { + return req.clientIp + } }); export { diff --git a/backend/src/types/express/index.d.ts b/backend/src/types/express/index.d.ts index 1ce63e609a..acee877bdc 100644 --- a/backend/src/types/express/index.d.ts +++ b/backend/src/types/express/index.d.ts @@ -5,6 +5,7 @@ import { ISecret } from '../../models'; declare global { namespace Express { interface Request { + clientIp: any; user: any; workspace: any; membership: any;