UNPKG

kaizenxakamai

Version:

Advanced rate-limiting and request protection module with 30+ features.

73 lines (71 loc) 3.1 kB
const fs = require('fs'); class RateLimiter { constructor(options) { this.options = { windowMs: options.windowMs || 60000, maxRequests: options.maxRequests || 100, blockDuration: options.blockDuration || 300000, permanentBlockThreshold: options.permanentBlockThreshold || 500, spamRequestThreshold: options.spamRequestThreshold || 10, allowList: new Set(options.allowList || []), denyList: new Set(options.denyList || []), logBlockedRequests: options.logBlockedRequests || false, logPath: options.logPath || 'blocked_ips.log', blockVPN: options.blockVPN || false, blockTor: options.blockTor || false, customResponseCode: options.customResponseCode || 429, customResponseMessage: options.customResponseMessage || 'Too many requests, try again later.', autoUnblock: options.autoUnblock || true, maxPayloadSize: options.maxPayloadSize || 1048576, strictMode: options.strictMode || false, detectUserAgentAnomalies: options.detectUserAgentAnomalies || false, allowedUserAgents: options.allowedUserAgents || [], blockEmptyUserAgent: options.blockEmptyUserAgent || false, blockByHeader: options.blockByHeader || [], blockByMethod: options.blockByMethod || [], rateLimitPerRoute: options.rateLimitPerRoute || {}, rateLimitPerUser: options.rateLimitPerUser || {}, challengeMode: options.challengeMode || false, blockMaliciousPatterns: options.blockMaliciousPatterns || false, blockSlowloris: options.blockSlowloris || false, autoAdjustRateLimit: options.autoAdjustRateLimit || false, banForever: options.banForever || false, }; this.store = new Map(); this.blockedIPs = new Set(); this.permanentBlockedIPs = new Set(); } checkRateLimit(ip, req) { if (this.options.allowList.has(ip)) return true; if (this.options.denyList.has(ip) || this.blockedIPs.has(ip) || this.permanentBlockedIPs.has(ip)) return false; const now = Date.now(); const windowStart = now - this.options.windowMs; const requestData = this.store.get(ip) || []; const validRequests = requestData.filter(timestamp => timestamp > windowStart); this.store.set(ip, validRequests); if (validRequests.length < this.options.maxRequests) { this.store.get(ip).push(now); return true; } else { if (validRequests.length >= this.options.permanentBlockThreshold) { this.permanentBlockedIPs.add(ip); if (this.options.logBlockedRequests) this.logBlock(ip, 'PERMANENT'); } else { this.blockIP(ip); } return false; } } blockIP(ip) { this.blockedIPs.add(ip); if (this.options.logBlockedRequests) this.logBlock(ip, 'TEMPORARY'); if (this.options.autoUnblock) { setTimeout(() => this.blockedIPs.delete(ip), this.options.blockDuration); } } logBlock(ip, type) { const logMessage = `${new Date().toISOString()} - BLOCKED ${type}: ${ip}\n`; fs.appendFileSync(this.options.logPath, logMessage); } } module.exports = RateLimiter;