ant_quic/relay/mod.rs
1// Copyright 2024 Saorsa Labs Ltd.
2//
3// This Saorsa Network Software is licensed under the General Public License (GPL), version 3.
4// Please see the file LICENSE-GPL, or visit <http://www.gnu.org/licenses/> for the full text.
5//
6// Full details available at https://saorsalabs.com/licenses
7
8//! Relay Infrastructure for NAT Traversal
9//!
10//! This module provides relay infrastructure components used by the MASQUE
11//! CONNECT-UDP Bind implementation for guaranteed NAT traversal fallback.
12//!
13//! # Overview
14//!
15//! The relay system implements `draft-ietf-masque-connect-udp-listen-10` to
16//! enable UDP proxying over QUIC connections. This provides 100% connectivity
17//! guarantee even when direct hole punching fails.
18//!
19//! # Components
20//!
21//! - `authenticator` - ML-DSA-65 post-quantum authentication
22//! - `error` - Relay error types
23//! - `rate_limiter` - Token bucket rate limiting
24//! - `statistics` - Relay statistics collection
25//!
26//! # Usage
27//!
28//! The primary relay implementation is in [`crate::masque`]. This module
29//! provides shared infrastructure components.
30//!
31//! ```rust,ignore
32//! use ant_quic::masque::{MasqueRelayServer, MasqueRelayClient, RelayManager};
33//! use ant_quic::relay::{RelayAuthenticator, RateLimiter};
34//!
35//! // Create a relay server with authentication
36//! let authenticator = RelayAuthenticator::new(keypair);
37//! let server = MasqueRelayServer::new(config, relay_address);
38//!
39//! // Create a relay client
40//! let client = MasqueRelayClient::new(relay_address, client_config);
41//! ```
42//!
43//! See [`crate::masque`] for the full MASQUE implementation.
44
45pub mod authenticator;
46pub mod error;
47pub mod rate_limiter;
48pub mod statistics;
49
50// Core exports
51pub use authenticator::{AuthToken, RelayAuthenticator};
52pub use error::{RelayError, RelayResult};
53pub use rate_limiter::{RateLimiter, TokenBucket};
54pub use statistics::RelayStatisticsCollector;
55
56// Re-export MASQUE types for convenience
57pub use crate::masque::{
58 MasqueRelayClient, MasqueRelayConfig, MasqueRelayServer, MasqueRelayStats, MigrationConfig,
59 MigrationCoordinator, MigrationState, RelayManager, RelayManagerConfig, RelaySession,
60 RelaySessionConfig, RelaySessionState,
61};
62
63use std::time::Duration;
64
65/// Default relay session timeout (5 minutes)
66pub const DEFAULT_SESSION_TIMEOUT: Duration = Duration::from_secs(300);
67
68/// Default bandwidth limit per session (1 MB/s)
69pub const DEFAULT_BANDWIDTH_LIMIT: u32 = 1_048_576;
70
71/// Maximum number of concurrent relay sessions per client
72pub const MAX_CONCURRENT_SESSIONS: usize = 10;
73
74/// Maximum size of relay data payload (64 KB)
75pub const MAX_RELAY_DATA_SIZE: usize = 65536;
76
77/// Rate limiting: tokens per second (100 requests/second)
78pub const RATE_LIMIT_TOKENS_PER_SECOND: u32 = 100;
79
80/// Rate limiting: maximum burst size (500 tokens)
81pub const RATE_LIMIT_BURST_SIZE: u32 = 500;
82
83/// Anti-replay window size for authentication tokens
84pub const ANTI_REPLAY_WINDOW_SIZE: u64 = 1000;
85
86/// Session cleanup interval (check every 30 seconds)
87pub const SESSION_CLEANUP_INTERVAL: Duration = Duration::from_secs(30);
88
89/// Comprehensive relay statistics combining all relay operations
90#[derive(Debug, Clone, Default)]
91pub struct RelayStatistics {
92 /// Session-related statistics
93 pub session_stats: SessionStatistics,
94
95 /// Connection-related statistics
96 pub connection_stats: ConnectionStatistics,
97
98 /// Authentication and security statistics
99 pub auth_stats: AuthenticationStatistics,
100
101 /// Rate limiting statistics
102 pub rate_limit_stats: RateLimitingStatistics,
103
104 /// Error and failure statistics
105 pub error_stats: ErrorStatistics,
106}
107
108/// Session management statistics
109#[derive(Debug, Clone, Default)]
110pub struct SessionStatistics {
111 /// Total sessions created since startup
112 pub total_sessions_created: u64,
113
114 /// Currently active sessions
115 pub active_sessions: u32,
116
117 /// Sessions currently in pending state
118 pub pending_sessions: u32,
119
120 /// Sessions terminated normally
121 pub sessions_terminated_normally: u64,
122
123 /// Sessions terminated due to timeout
124 pub sessions_timed_out: u64,
125
126 /// Sessions terminated due to errors
127 pub sessions_terminated_with_errors: u64,
128
129 /// Average session duration (in seconds)
130 pub avg_session_duration: f64,
131
132 /// Total data forwarded across all sessions (bytes)
133 pub total_bytes_forwarded: u64,
134}
135
136/// Connection-level statistics
137#[derive(Debug, Clone, Default)]
138pub struct ConnectionStatistics {
139 /// Total relay connections established
140 pub total_connections: u64,
141
142 /// Currently active connections
143 pub active_connections: u32,
144
145 /// Total bytes sent through all connections
146 pub total_bytes_sent: u64,
147
148 /// Total bytes received through all connections
149 pub total_bytes_received: u64,
150
151 /// Average connection bandwidth usage (bytes/sec)
152 pub avg_bandwidth_usage: f64,
153
154 /// Peak concurrent connections
155 pub peak_concurrent_connections: u32,
156
157 /// Connection timeouts
158 pub connection_timeouts: u64,
159
160 /// Keep-alive packets sent
161 pub keep_alive_sent: u64,
162}
163
164/// Authentication and security statistics
165#[derive(Debug, Clone, Default)]
166pub struct AuthenticationStatistics {
167 /// Total authentication attempts
168 pub total_auth_attempts: u64,
169
170 /// Successful authentications
171 pub successful_auths: u64,
172
173 /// Failed authentications
174 pub failed_auths: u64,
175
176 /// Authentication rate (auths per second)
177 pub auth_rate: f64,
178
179 /// Replay attacks detected and blocked
180 pub replay_attacks_blocked: u64,
181
182 /// Invalid signatures detected
183 pub invalid_signatures: u64,
184
185 /// Unknown peer keys encountered
186 pub unknown_peer_keys: u64,
187}
188
189/// Rate limiting statistics
190#[derive(Debug, Clone, Default)]
191pub struct RateLimitingStatistics {
192 /// Total requests received
193 pub total_requests: u64,
194
195 /// Requests allowed through rate limiter
196 pub requests_allowed: u64,
197
198 /// Requests blocked by rate limiter
199 pub requests_blocked: u64,
200
201 /// Current token bucket levels
202 pub current_tokens: u32,
203
204 /// Rate limiting efficiency (% of requests allowed)
205 pub efficiency_percentage: f64,
206
207 /// Peak request rate (requests per second)
208 pub peak_request_rate: f64,
209}
210
211/// Error and failure statistics
212#[derive(Debug, Clone, Default)]
213pub struct ErrorStatistics {
214 /// Protocol errors encountered
215 pub protocol_errors: u64,
216
217 /// Resource exhaustion events
218 pub resource_exhausted: u64,
219
220 /// Session-related errors
221 pub session_errors: u64,
222
223 /// Authentication failures
224 pub auth_failures: u64,
225
226 /// Network-related errors
227 pub network_errors: u64,
228
229 /// Internal errors
230 pub internal_errors: u64,
231
232 /// Error rate (errors per second)
233 pub error_rate: f64,
234
235 /// Most common error types
236 pub error_breakdown: std::collections::HashMap<String, u64>,
237}
238
239impl RelayStatistics {
240 /// Create new empty relay statistics
241 pub fn new() -> Self {
242 Self::default()
243 }
244
245 /// Calculate overall success rate
246 pub fn success_rate(&self) -> f64 {
247 let total_ops = self.session_stats.total_sessions_created
248 + self.connection_stats.total_connections
249 + self.auth_stats.total_auth_attempts;
250
251 if total_ops == 0 {
252 return 1.0;
253 }
254
255 let total_failures = self.session_stats.sessions_terminated_with_errors
256 + self.connection_stats.connection_timeouts
257 + self.auth_stats.failed_auths
258 + self.error_stats.protocol_errors
259 + self.error_stats.resource_exhausted;
260
261 1.0 - (total_failures as f64 / total_ops as f64)
262 }
263
264 /// Calculate total throughput (bytes per second)
265 pub fn total_throughput(&self) -> f64 {
266 if self.session_stats.avg_session_duration == 0.0 {
267 return 0.0;
268 }
269 self.session_stats.total_bytes_forwarded as f64 / self.session_stats.avg_session_duration
270 }
271
272 /// Check if relay is operating within healthy parameters
273 pub fn is_healthy(&self) -> bool {
274 let total_ops = self.session_stats.total_sessions_created
275 + self.connection_stats.total_connections
276 + self.auth_stats.total_auth_attempts
277 + self.rate_limit_stats.total_requests;
278
279 if total_ops == 0 {
280 return true;
281 }
282
283 let total_errors = self.error_stats.protocol_errors
284 + self.error_stats.resource_exhausted
285 + self.error_stats.session_errors
286 + self.error_stats.auth_failures
287 + self.error_stats.network_errors
288 + self.error_stats.internal_errors;
289
290 let error_rate_ok = if total_errors == 0 {
291 true
292 } else if self.error_stats.error_rate < 1.0 {
293 true
294 } else {
295 total_errors <= 5 && total_ops >= 100
296 };
297
298 self.success_rate() > 0.95
299 && error_rate_ok
300 && (self.rate_limit_stats.total_requests == 0
301 || self.rate_limit_stats.efficiency_percentage > 80.0)
302 }
303}