diff --git a/packages/backend/package.json b/packages/backend/package.json index 8e8d76bf23..65eda6153c 100644 --- a/packages/backend/package.json +++ b/packages/backend/package.json @@ -156,6 +156,7 @@ "pkce-challenge": "4.1.0", "probe-image-size": "7.2.3", "promise-limit": "2.7.0", + "proxy-addr": "^2.0.7", "pug": "3.0.2", "punycode": "2.3.1", "qrcode": "1.5.3", diff --git a/packages/backend/src/server/api/StreamingApiServerService.ts b/packages/backend/src/server/api/StreamingApiServerService.ts index 7ac1bcf469..1435169812 100644 --- a/packages/backend/src/server/api/StreamingApiServerService.ts +++ b/packages/backend/src/server/api/StreamingApiServerService.ts @@ -22,6 +22,7 @@ import { ChannelsService } from './stream/ChannelsService.js'; import { RateLimiterService } from './RateLimiterService.js'; import { RoleService } from '@/core/RoleService.js'; import { getIpHash } from '@/misc/get-ip-hash.js'; +import proxyAddr from 'proxy-addr'; import ms from 'ms'; import type * as http from 'node:http'; import type { IEndpointMeta } from './endpoints.js'; @@ -69,7 +70,9 @@ export class StreamingApiServerService { if (factor <= 0) return false; // Rate limit - return await this.rateLimiterService.limit(limit, limitActor, factor).then(() => { return false }).catch(err => { return true }); + return await this.rateLimiterService.limit(limit, limitActor, factor) + .then(() => { return false; }) + .catch(err => { return true; }); } @bindThis @@ -85,7 +88,12 @@ export class StreamingApiServerService { return; } - if (await this.rateLimitThis(null, request.socket.remoteAddress, { + // ServerServices sets `trustProxy: true`, which inside + // fastify/request.js ends up calling `proxyAddr` in this way, + // so we do the same + const requestIp = proxyAddr(request, () => { return true; } ); + + if (await this.rateLimitThis(null, requestIp, { key: 'wsconnect', duration: ms('1min'), max: 20, @@ -134,7 +142,7 @@ export class StreamingApiServerService { } const rateLimiter = () => { - return this.rateLimitThis(user, request.socket.remoteAddress, { + return this.rateLimitThis(user, requestIp, { key: 'wsmessage', duration: ms('1sec'), max: 100, diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 1f3cd8216f..d6e9f1196a 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -352,6 +352,9 @@ importers: promise-limit: specifier: 2.7.0 version: 2.7.0 + proxy-addr: + specifier: ^2.0.7 + version: 2.0.7 pug: specifier: 3.0.2 version: 3.0.2