Gajus Kuizinas браво!
Вече описахте недостатъците на описания подход.
Бих предложил по-разпространено и гъвкаво решение срещу DDoS и грубо форсиране на идентификатори.
Ето пакета rate-limiter-flexible node.js, който помага.
Нека напишем прост пример.
const redis = require('redis'); const { RateLimiterRedis, RateLimiterMemory } = require('rate-limiter-flexible'); const redisClient = redis.createClient({ enable_offline_queue: false }); const opts = { redis: redisClient, points: 40, // Number of points duration: 1, // Per second(s) blockOnPointsConsumed: 80, // If >=80 points consumed per sec blockDuration: 30, // totally block for 30 seconds insuranceLimiter: new RateLimiterMemory( { points: 2, // 2 is fair if you have 20 workers in total duration: 1, }) }; const rateLimiterRedis = new RateLimiterRedis(opts); rateLimiterRedis.consume(remoteAddress) // consume 1 point .then(() => { // ... request to DB or to Cache ... if (noSuchResource) { // probably malicious, let's fine it rateLimiterRedis.penalty(remoteAddress, 3); } }) .catch((rejRes) => { // can't consume const secs = Math.round(rejRes.msBeforeNext / 1000) || 1; res.set('Retry-After', String(secs)); res.status(429).send('Too Many Requests'); } });
Резултати:
- защитени срещу претоварване на DB или Cache
- блокира клиенти, които се опитват да DDoS
- клиентите, които се опитват да форсират нашето приложение с различни идентификатори, са ограничени по-рано, така че DB или Cache системата не се зареждат много
- `insuranceLimiter` помага да продължите работата, ако Redis не работи. Може да бъде и вторият Redis сървър/клъстер като застраховка
Надявам се, че ще ви бъде полезно