201 lines
5.4 KiB
TypeScript
201 lines
5.4 KiB
TypeScript
import { EventEmitter } from 'node:events';
|
|
/**
|
|
* Interface for rate limit configuration
|
|
*/
|
|
export interface IRateLimitConfig {
|
|
maxMessagesPerMinute?: number;
|
|
maxRecipientsPerMessage?: number;
|
|
maxConnectionsPerIP?: number;
|
|
maxErrorsPerIP?: number;
|
|
maxAuthFailuresPerIP?: number;
|
|
blockDuration?: number;
|
|
}
|
|
/**
|
|
* Interface for hierarchical rate limits
|
|
*/
|
|
export interface IHierarchicalRateLimits {
|
|
global: IRateLimitConfig;
|
|
patterns?: Record<string, IRateLimitConfig>;
|
|
ips?: Record<string, IRateLimitConfig>;
|
|
domains?: Record<string, IRateLimitConfig>;
|
|
blocks?: Record<string, number>;
|
|
}
|
|
/**
|
|
* Rate limiter statistics
|
|
*/
|
|
export interface IRateLimiterStats {
|
|
activeCounters: number;
|
|
totalBlocked: number;
|
|
currentlyBlocked: number;
|
|
byPattern: Record<string, {
|
|
messagesPerMinute: number;
|
|
totalMessages: number;
|
|
totalBlocked: number;
|
|
}>;
|
|
byIp: Record<string, {
|
|
messagesPerMinute: number;
|
|
totalMessages: number;
|
|
totalBlocked: number;
|
|
connections: number;
|
|
errors: number;
|
|
authFailures: number;
|
|
blocked: boolean;
|
|
}>;
|
|
}
|
|
/**
|
|
* Result of a rate limit check
|
|
*/
|
|
export interface IRateLimitResult {
|
|
allowed: boolean;
|
|
reason?: string;
|
|
limit?: number;
|
|
current?: number;
|
|
resetIn?: number;
|
|
}
|
|
/**
|
|
* Unified rate limiter for all email processing modes
|
|
*/
|
|
export declare class UnifiedRateLimiter extends EventEmitter {
|
|
private config;
|
|
private counters;
|
|
private patternCounters;
|
|
private ipCounters;
|
|
private domainCounters;
|
|
private cleanupInterval?;
|
|
private stats;
|
|
/**
|
|
* Create a new unified rate limiter
|
|
* @param config Rate limit configuration
|
|
*/
|
|
constructor(config: IHierarchicalRateLimits);
|
|
/**
|
|
* Start the cleanup interval
|
|
*/
|
|
private startCleanupInterval;
|
|
/**
|
|
* Stop the cleanup interval
|
|
*/
|
|
stop(): void;
|
|
/**
|
|
* Destroy the rate limiter and clean up all resources
|
|
*/
|
|
destroy(): void;
|
|
/**
|
|
* Clean up expired counters and blocks
|
|
*/
|
|
private cleanup;
|
|
/**
|
|
* Check if a message is allowed by rate limits
|
|
* @param email Email address
|
|
* @param ip IP address
|
|
* @param recipients Number of recipients
|
|
* @param pattern Matched pattern
|
|
* @param domain Domain name for domain-specific limits
|
|
* @returns Result of rate limit check
|
|
*/
|
|
checkMessageLimit(email: string, ip: string, recipients: number, pattern?: string, domain?: string): IRateLimitResult;
|
|
/**
|
|
* Check global message rate limit
|
|
* @param email Email address
|
|
*/
|
|
private checkGlobalMessageLimit;
|
|
/**
|
|
* Check pattern-specific message rate limit
|
|
* @param pattern Pattern to check
|
|
*/
|
|
private checkPatternMessageLimit;
|
|
/**
|
|
* Check domain-specific message rate limit
|
|
* @param domain Domain to check
|
|
*/
|
|
private checkDomainMessageLimit;
|
|
/**
|
|
* Check IP-specific message rate limit
|
|
* @param ip IP address
|
|
*/
|
|
private checkIpMessageLimit;
|
|
/**
|
|
* Check recipient limit
|
|
* @param email Email address
|
|
* @param recipients Number of recipients
|
|
* @param pattern Matched pattern
|
|
* @param domain Domain name
|
|
*/
|
|
private checkRecipientLimit;
|
|
/**
|
|
* Record a connection from an IP
|
|
* @param ip IP address
|
|
* @returns Result of rate limit check
|
|
*/
|
|
recordConnection(ip: string): IRateLimitResult;
|
|
/**
|
|
* Record an error from an IP
|
|
* @param ip IP address
|
|
* @returns True if IP should be blocked
|
|
*/
|
|
recordError(ip: string): boolean;
|
|
/**
|
|
* Record an authentication failure from an IP
|
|
* @param ip IP address
|
|
* @returns True if IP should be blocked
|
|
*/
|
|
recordAuthFailure(ip: string): boolean;
|
|
/**
|
|
* Block an IP address
|
|
* @param ip IP address to block
|
|
* @param duration Override the default block duration (milliseconds)
|
|
*/
|
|
blockIp(ip: string, duration?: number): void;
|
|
/**
|
|
* Unblock an IP address
|
|
* @param ip IP address to unblock
|
|
*/
|
|
unblockIp(ip: string): void;
|
|
/**
|
|
* Check if an IP is blocked
|
|
* @param ip IP address to check
|
|
*/
|
|
isIpBlocked(ip: string): boolean;
|
|
/**
|
|
* Get the time until a block is released
|
|
* @param ip IP address
|
|
* @returns Milliseconds until release or 0 if not blocked
|
|
*/
|
|
getBlockReleaseTime(ip: string): number;
|
|
/**
|
|
* Update rate limiter statistics
|
|
*/
|
|
private updateStats;
|
|
/**
|
|
* Get rate limiter statistics
|
|
*/
|
|
getStats(): IRateLimiterStats;
|
|
/**
|
|
* Update rate limiter configuration
|
|
* @param config New configuration
|
|
*/
|
|
updateConfig(config: Partial<IHierarchicalRateLimits>): void;
|
|
/**
|
|
* Get configuration for debugging
|
|
*/
|
|
getConfig(): IHierarchicalRateLimits;
|
|
/**
|
|
* Apply domain-specific rate limits
|
|
* Merges domain limits with existing configuration
|
|
* @param domain Domain name
|
|
* @param limits Rate limit configuration for the domain
|
|
*/
|
|
applyDomainLimits(domain: string, limits: IRateLimitConfig): void;
|
|
/**
|
|
* Remove domain-specific rate limits
|
|
* @param domain Domain name
|
|
*/
|
|
removeDomainLimits(domain: string): void;
|
|
/**
|
|
* Get domain-specific rate limits
|
|
* @param domain Domain name
|
|
* @returns Domain rate limit config or undefined
|
|
*/
|
|
getDomainLimits(domain: string): IRateLimitConfig | undefined;
|
|
}
|