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}