summaryrefslogtreecommitdiff
path: root/packages/backend
diff options
context:
space:
mode:
authorかっこかり <67428053+kakkokari-gtyih@users.noreply.github.com>2025-12-20 19:07:05 +0900
committerGitHub <noreply@github.com>2025-12-20 19:07:05 +0900
commitee8dccea2ffb151636e520f71b7dfe2b91e06c71 (patch)
tree920d627b4d1f246684c799cc5312fbd99cc689b6 /packages/backend
parentfix(frontend): iPadOSのPWAでアプリを切り替えた際にウィジェ... (diff)
downloadmisskey-ee8dccea2ffb151636e520f71b7dfe2b91e06c71.tar.gz
misskey-ee8dccea2ffb151636e520f71b7dfe2b91e06c71.tar.bz2
misskey-ee8dccea2ffb151636e520f71b7dfe2b91e06c71.zip
fix(backend): fix #16994 by approach 6 (#17005)
* fix(backend): narrow down trustproxy default value and enhance documentation on how to configure it * Update Changelog * indent [ci skip] * Update CHANGELOG.md [ci skip] * add cloudflare specific example * Update .config/example.yml Co-authored-by: anatawa12 <anatawa12@icloud.com> * fix: productionでIPレートリミットされる際にlocalhostからリクエストが来たらログを残すように * fix: wrong condition * fix: use own logger for signin api * flip configuration * fix * fix [ci skip] * fix: wrong message [ci skip] * fix: どこがおかしいか明記 [ci skip] --------- Co-authored-by: anatawa12 <anatawa12@icloud.com>
Diffstat (limited to 'packages/backend')
-rw-r--r--packages/backend/src/config.ts14
-rw-r--r--packages/backend/src/server/ServerService.ts2
-rw-r--r--packages/backend/src/server/api/ApiCallService.ts13
-rw-r--r--packages/backend/src/server/api/SigninApiService.ts13
-rw-r--r--packages/backend/src/server/api/SigninWithPasskeyApiService.ts8
5 files changed, 34 insertions, 16 deletions
diff --git a/packages/backend/src/config.ts b/packages/backend/src/config.ts
index f9852d3578..657d7869fa 100644
--- a/packages/backend/src/config.ts
+++ b/packages/backend/src/config.ts
@@ -30,6 +30,7 @@ type Source = {
socket?: string;
trustProxy?: FastifyServerOptions['trustProxy'];
chmodSocket?: string;
+ enableIpRateLimit?: boolean;
disableHsts?: boolean;
db: {
host: string;
@@ -120,8 +121,9 @@ export type Config = {
url: string;
port: number;
socket: string | undefined;
- trustProxy: FastifyServerOptions['trustProxy'];
+ trustProxy: NonNullable<FastifyServerOptions['trustProxy']>;
chmodSocket: string | undefined;
+ enableIpRateLimit: boolean;
disableHsts: boolean | undefined;
db: {
host: string;
@@ -263,9 +265,17 @@ export function loadConfig(): Config {
url: url.origin,
port: config.port ?? parseInt(process.env.PORT ?? '', 10),
socket: config.socket,
- trustProxy: config.trustProxy,
+ trustProxy: config.trustProxy ?? [
+ '10.0.0.0/8',
+ '172.16.0.0/12',
+ '192.168.0.0/16',
+ '127.0.0.1/32',
+ '::1/128',
+ 'fc00::/7',
+ ],
chmodSocket: config.chmodSocket,
disableHsts: config.disableHsts,
+ enableIpRateLimit: config.enableIpRateLimit ?? true,
host,
hostname,
scheme,
diff --git a/packages/backend/src/server/ServerService.ts b/packages/backend/src/server/ServerService.ts
index 1286b4dad6..ef9ac81f95 100644
--- a/packages/backend/src/server/ServerService.ts
+++ b/packages/backend/src/server/ServerService.ts
@@ -75,7 +75,7 @@ export class ServerService implements OnApplicationShutdown {
@bindThis
public async launch(): Promise<void> {
const fastify = Fastify({
- trustProxy: this.config.trustProxy ?? true,
+ trustProxy: this.config.trustProxy,
logger: false,
});
this.#fastify = fastify;
diff --git a/packages/backend/src/server/api/ApiCallService.ts b/packages/backend/src/server/api/ApiCallService.ts
index 261e147040..8bae46d9fb 100644
--- a/packages/backend/src/server/api/ApiCallService.ts
+++ b/packages/backend/src/server/api/ApiCallService.ts
@@ -313,16 +313,15 @@ export class ApiCallService implements OnApplicationShutdown {
}
if (ep.meta.limit) {
- let limitActor: string | null;
+ let limitActor: string | null = null;
if (user) {
limitActor = user.id;
- } else {
- if (request.ip === '::1' || request.ip === '127.0.0.1') {
- console.warn('request ip is localhost, maybe caused by misconfiguration of trustProxy or reverse proxy');
- limitActor = null;
- } else {
- limitActor = getIpHash(request.ip);
+ } else if (this.config.enableIpRateLimit) {
+ if (process.env.NODE_ENV === 'production' && (request.ip === '::1' || request.ip === '127.0.0.1')) {
+ this.logger.warn('Recieved API request from localhost IP address for rate limiting in production environment. This is likely due to an improper trustProxy setting in the config file.');
}
+
+ limitActor = getIpHash(request.ip);
}
const limit = Object.assign({}, ep.meta.limit);
diff --git a/packages/backend/src/server/api/SigninApiService.ts b/packages/backend/src/server/api/SigninApiService.ts
index 14726f8411..00e8828242 100644
--- a/packages/backend/src/server/api/SigninApiService.ts
+++ b/packages/backend/src/server/api/SigninApiService.ts
@@ -15,6 +15,7 @@ import type {
UserSecurityKeysRepository,
UsersRepository,
} from '@/models/_.js';
+import type Logger from '@/logger.js';
import type { Config } from '@/config.js';
import { getIpHash } from '@/misc/get-ip-hash.js';
import type { MiLocalUser } from '@/models/User.js';
@@ -23,6 +24,7 @@ import { bindThis } from '@/decorators.js';
import { WebAuthnService } from '@/core/WebAuthnService.js';
import { UserAuthService } from '@/core/UserAuthService.js';
import { CaptchaService } from '@/core/CaptchaService.js';
+import { LoggerService } from '@/core/LoggerService.js';
import { FastifyReplyError } from '@/misc/fastify-reply-error.js';
import { RateLimiterService } from './RateLimiterService.js';
import { SigninService } from './SigninService.js';
@@ -31,6 +33,8 @@ import type { FastifyReply, FastifyRequest } from 'fastify';
@Injectable()
export class SigninApiService {
+ private logger: Logger;
+
constructor(
@Inject(DI.config)
private config: Config,
@@ -50,6 +54,7 @@ export class SigninApiService {
@Inject(DI.signinsRepository)
private signinsRepository: SigninsRepository,
+ private loggerService: LoggerService,
private idService: IdService,
private rateLimiterService: RateLimiterService,
private signinService: SigninService,
@@ -57,6 +62,7 @@ export class SigninApiService {
private webAuthnService: WebAuthnService,
private captchaService: CaptchaService,
) {
+ this.logger = this.loggerService.getLogger('Signin');
}
@bindThis
@@ -89,10 +95,11 @@ export class SigninApiService {
return { error };
}
- if (request.ip === '::1' || request.ip === '127.0.0.1') {
- console.warn('request ip is localhost, maybe caused by misconfiguration of trustProxy or reverse proxy');
- } else {
// not more than 1 attempt per second and not more than 10 attempts per hour
+ if (this.config.enableIpRateLimit) {
+ if (process.env.NODE_ENV === 'production' && (request.ip === '::1' || request.ip === '127.0.0.1')) {
+ this.logger.warn('Recieved signin request from localhost IP address for rate limiting in production environment. This is likely due to an improper trustProxy setting in the config file.');
+ }
const rateLimit = await this.rateLimiterService.limit({ key: 'signin', duration: 60 * 60 * 1000, max: 10, minInterval: 1000 }, getIpHash(request.ip));
if (rateLimit != null) {
reply.code(429);
diff --git a/packages/backend/src/server/api/SigninWithPasskeyApiService.ts b/packages/backend/src/server/api/SigninWithPasskeyApiService.ts
index 1b89752340..920f9d0b3a 100644
--- a/packages/backend/src/server/api/SigninWithPasskeyApiService.ts
+++ b/packages/backend/src/server/api/SigninWithPasskeyApiService.ts
@@ -84,9 +84,11 @@ export class SigninWithPasskeyApiService {
return error(status ?? 500, failure ?? { id: '4e30e80c-e338-45a0-8c8f-44455efa3b76' });
};
- if (request.ip === '::1' || request.ip === '127.0.0.1') {
- console.warn('request ip is localhost, maybe caused by misconfiguration of trustProxy or reverse proxy');
- } else {
+ if (this.config.enableIpRateLimit) {
+ if (process.env.NODE_ENV === 'production' && (request.ip === '::1' || request.ip === '127.0.0.1')) {
+ this.logger.warn('Recieved signin with passkey request from localhost IP address for rate limiting in production environment. This is likely due to an improper trustProxy setting in the config file.');
+ }
+
try {
// Not more than 1 API call per 250ms and not more than 100 attempts per 30min
// NOTE: 1 Sign-in require 2 API calls