Rate Limiting va Throttling

~15 daq · NestJS · Fayllar va Xavfsizlik

Muammodan boshlaylik

Bot yoki xaker /auth/login ga soniyada 1000 ta so'rov yubordi. Har biri baza so'rovi qiladi — server qulab tushdi. Yoki kimdir /api/search ga avtomatlashtirilgan so'rovlar yuborib, ma'lumotlarni to'pladi.

Rate Limiting — bir vaqt oralig'ida bir manzildan kelishi mumkin bo'lgan so'rovlar sonini cheklash. Limit oshsa — 429 Too Many Requests.


O'rnatish

npm install @nestjs/throttler

Global sozlash — AppModule

// src/app.module.ts
import { Module } from '@nestjs/common';
import { ThrottlerModule, ThrottlerGuard } from '@nestjs/throttler';
import { APP_GUARD } from '@nestjs/core';

@Module({
  imports: [
    ThrottlerModule.forRoot([
      {
        name:  'short',   // qisqa oraliq
        ttl:   1000,      // 1 soniya (millisekund)
        limit: 10,        // 10 ta so'rov
      },
      {
        name:  'medium',
        ttl:   60_000,    // 1 daqiqa
        limit: 100,       // 100 ta so'rov
      },
      {
        name:  'long',
        ttl:   3_600_000, // 1 soat
        limit: 1000,      // 1000 ta so'rov
      },
    ]),
  ],
  providers: [
    {
      provide:  APP_GUARD,
      useClass: ThrottlerGuard, // ← barcha endpointlarga qo'llaniladi
    },
  ],
})
export class AppModule {}

Bir nechta oraliq: agar soniyada 10 dan oshsa — blok. Daqiqada 100 dan oshsa — blok. Soatda 1000 dan oshsa — blok.


Controller darajasida sozlash

// src/auth/auth.controller.ts
import { Throttle, SkipThrottle } from '@nestjs/throttler';

@Controller('auth')
export class AuthController {

  // Login — qattiqroq limit (brute force himoya)
  @Post('login')
  @Throttle({ short: { ttl: 60_000, limit: 5 } }) // 1 daqiqada 5 ta urinish
  login(@Req() req) { ... }

  // Register — o'rtacha limit
  @Post('register')
  @Throttle({ short: { ttl: 60_000, limit: 3 } }) // 1 daqiqada 3 ta
  register(@Body() dto: CreateUserDto) { ... }

  // Refresh — global limitdan ozod
  @Post('refresh')
  @SkipThrottle() // ← limit yo'q (tez-tez chaqiriladi)
  refresh(@Req() req) { ... }
}
// Butun controller uchun limit
@Controller('search')
@Throttle({ medium: { ttl: 60_000, limit: 30 } }) // daqiqada 30 ta qidirish
export class SearchController { ... }

Redis bilan — tarqatilgan tizimlar uchun

Standart holda limitlar server xotirasida saqlanadi. Ikki server bo'lsa — har biri alohida sanaydi. Bir serverga 10 ta, ikkinchisiga 10 ta — jami 20 ta so'rov o'tib ketadi.

Redis bilan — barcha serverlar bitta sanagichni ko'radi:

npm install @nestjs/throttler ioredis
// src/app.module.ts
import { ThrottlerModule } from '@nestjs/throttler';
import { ThrottlerStorageRedisService } from '@nest-lab/throttler-storage-redis';

@Module({
  imports: [
    ThrottlerModule.forRootAsync({
      useFactory: (config: ConfigService) => ({
        throttlers: [
          { name: 'short',  ttl: 1_000,       limit: 10  },
          { name: 'medium', ttl: 60_000,       limit: 100 },
          { name: 'long',   ttl: 3_600_000,    limit: 1000 },
        ],
        storage: new ThrottlerStorageRedisService({
          host: config.get('REDIS_HOST'),
          port: config.get('REDIS_PORT'),
        }),
      }),
      inject: [ConfigService],
    }),
  ],
})
export class AppModule {}

Tez-tez uchraydigan xatolar

Login da global limit yetarli deb o'ylash

// ❌ Global: 1 daqiqada 100 ta so'rov → login uchun juda yumshoq
ThrottlerModule.forRoot([{ ttl: 60_000, limit: 100 }])

// ✅ Login uchun qattiqroq, alohida
@Post('login')
@Throttle({ short: { ttl: 60_000, limit: 5 } })
login() { ... }

429 xatosini foydalanuvchiga tushunarli qilmaslik

// ❌ Standart xato — texnik, noaniq
{ "statusCode": 429, "message": "ThrottlerException: Too Many Requests" }

// ✅ Exception Filter bilan xato xabarini o'zgartirish
import { ThrottlerException } from '@nestjs/throttler';

@Catch(ThrottlerException)
export class ThrottlerExceptionFilter implements ExceptionFilter {
  catch(exception: ThrottlerException, host: ArgumentsHost) {
    const ctx = host.switchToHttp();
    ctx.getResponse().status(429).json({
      statusCode: 429,
      message: 'Juda ko\'p so\'rov yuborildi. Biroz kuting.',
      retryAfter: 60, // soniyada qayta urinish
    });
  }
}

Xulosa

Rate Limiting — xakerlik, bot hujumi va serverga yukdan himoya. @nestjs/throttler — global yoki endpoint darajasida sozlanadi.

Eslab qoling:

  • Global limit → ThrottlerModule.forRoot + APP_GUARD
  • Endpoint limiti → @Throttle({ name: { ttl, limit } })
  • Limitdan ozod → @SkipThrottle()
  • Login/register → qattiqroq limit (brute force)
  • Ko'p server → Redis storage
  • ttl millisekunda, limit so'rovlar soni

Keyingi dars

33-dars: Caching — Cache Manager, Redis