Skip to main content

cloudillo_core/rate_limit/
config.rs

1// SPDX-FileCopyrightText: Szilárd Hajba
2// SPDX-License-Identifier: LGPL-3.0-or-later
3
4//! Rate Limiting Configuration
5//!
6//! Configuration structs for hierarchical rate limiting with dual-tier
7//! (short-term burst + long-term sustained) limits.
8
9use std::num::NonZeroU32;
10use std::time::Duration;
11
12/// Dual-tier rate limit configuration for a single address level
13#[derive(Clone, Debug)]
14pub struct RateLimitTierConfig {
15	// Short-term: burst protection (per-second)
16	/// Requests per second
17	pub short_term_rps: NonZeroU32,
18	/// Burst capacity for short-term
19	pub short_term_burst: NonZeroU32,
20
21	// Long-term: sustained abuse protection (per-hour)
22	/// Requests per hour
23	pub long_term_rph: NonZeroU32,
24	/// Burst capacity for long-term
25	pub long_term_burst: NonZeroU32,
26}
27
28impl RateLimitTierConfig {
29	pub fn new(short_rps: u32, short_burst: u32, long_rph: u32, long_burst: u32) -> Self {
30		Self {
31			short_term_rps: NonZeroU32::new(short_rps).unwrap_or(NonZeroU32::MIN),
32			short_term_burst: NonZeroU32::new(short_burst).unwrap_or(NonZeroU32::MIN),
33			long_term_rph: NonZeroU32::new(long_rph).unwrap_or(NonZeroU32::MIN),
34			long_term_burst: NonZeroU32::new(long_burst).unwrap_or(NonZeroU32::MIN),
35		}
36	}
37}
38
39/// Configuration for an endpoint category with all address levels
40#[derive(Clone, Debug)]
41pub struct EndpointCategoryConfig {
42	/// Category name (e.g., "auth", "federation", "general")
43	pub name: &'static str,
44	/// IPv4 individual (/32) limits
45	pub ipv4_individual: RateLimitTierConfig,
46	/// IPv4 network (/24) limits
47	pub ipv4_network: RateLimitTierConfig,
48	/// IPv6 subnet (/64) limits
49	pub ipv6_subnet: RateLimitTierConfig,
50	/// IPv6 provider (/48) limits
51	pub ipv6_provider: RateLimitTierConfig,
52}
53
54/// Main rate limit configuration
55#[derive(Clone, Debug)]
56pub struct RateLimitConfig {
57	/// Auth endpoints (login, register, password reset)
58	pub auth: EndpointCategoryConfig,
59	/// Federation endpoints (inbox)
60	pub federation: EndpointCategoryConfig,
61	/// General public endpoints (profile, refs)
62	pub general: EndpointCategoryConfig,
63	/// WebSocket endpoints
64	pub websocket: EndpointCategoryConfig,
65	/// Maximum number of IPs to track (memory limit)
66	pub max_tracked_ips: usize,
67	/// How long to retain entries after last access
68	pub entry_ttl: Duration,
69}
70
71impl Default for RateLimitConfig {
72	fn default() -> Self {
73		Self {
74			auth: EndpointCategoryConfig {
75				name: "auth",
76				// Auth: strict limits but allow a few rapid page refreshes
77				ipv4_individual: RateLimitTierConfig::new(5, 10, 60, 60),
78				ipv4_network: RateLimitTierConfig::new(15, 30, 200, 200),
79				ipv6_subnet: RateLimitTierConfig::new(5, 10, 60, 60),
80				ipv6_provider: RateLimitTierConfig::new(15, 30, 200, 200),
81			},
82			federation: EndpointCategoryConfig {
83				name: "federation",
84				// Federation: moderate limits for inter-instance communication
85				ipv4_individual: RateLimitTierConfig::new(100, 200, 1000, 100),
86				ipv4_network: RateLimitTierConfig::new(500, 750, 5000, 500),
87				ipv6_subnet: RateLimitTierConfig::new(100, 200, 1000, 100),
88				ipv6_provider: RateLimitTierConfig::new(500, 750, 5000, 500),
89			},
90			general: EndpointCategoryConfig {
91				name: "general",
92				// General: relaxed limits for normal browsing
93				ipv4_individual: RateLimitTierConfig::new(300, 500, 5000, 500),
94				ipv4_network: RateLimitTierConfig::new(600, 1000, 50000, 5000),
95				ipv6_subnet: RateLimitTierConfig::new(300, 500, 5000, 500),
96				ipv6_provider: RateLimitTierConfig::new(600, 1000, 50000, 5000),
97			},
98			websocket: EndpointCategoryConfig {
99				name: "websocket",
100				// WebSocket: relaxed limits for collaborative scenarios (connections are long-lived)
101				ipv4_individual: RateLimitTierConfig::new(100, 200, 1000, 500),
102				ipv4_network: RateLimitTierConfig::new(100, 200, 1000, 500),
103				ipv6_subnet: RateLimitTierConfig::new(100, 200, 1000, 500),
104				ipv6_provider: RateLimitTierConfig::new(100, 200, 1000, 500),
105			},
106			max_tracked_ips: 100_000,
107			entry_ttl: Duration::from_secs(3600), // 1 hour
108		}
109	}
110}
111
112/// Proof-of-Work counter configuration
113#[derive(Clone, Debug)]
114pub struct PowConfig {
115	/// Maximum counter value (caps PoW difficulty)
116	pub max_counter: u32,
117	/// Counter decay: decrease by 1 every N seconds of no violations
118	pub decay_interval_secs: u64,
119	/// LRU cache size for individual IPs
120	pub max_individual_entries: usize,
121	/// LRU cache size for networks
122	pub max_network_entries: usize,
123}
124
125impl Default for PowConfig {
126	fn default() -> Self {
127		Self {
128			max_counter: 10,           // Max "AAAAAAAAAA" required
129			decay_interval_secs: 3600, // 1 hour decay
130			max_individual_entries: 50_000,
131			max_network_entries: 10_000,
132		}
133	}
134}
135
136// vim: ts=4