mirror of
https://github.com/telemt/telemt.git
synced 2026-06-22 02:41:10 +03:00
Security hardening, concurrency fixes, and expanded test coverage
This commit introduces a comprehensive set of improvements to enhance the security, reliability, and configurability of the proxy server, specifically targeting adversarial resilience and high-load concurrency. Security & Cryptography: - Zeroize MTProto cryptographic key material (`dec_key`, `enc_key`) immediately after use to prevent memory leakage on early returns. - Move TLS handshake replay tracking after full policy/ALPN validation to prevent cache poisoning by unauthenticated probes. - Add `proxy_protocol_trusted_cidrs` configuration to restrict PROXY protocol headers to trusted networks, rejecting spoofed IPs. Adversarial Resilience & DoS Mitigation: - Implement "Tiny Frame Debt" tracking in the middle-relay to prevent CPU exhaustion from malicious 0-byte or 1-byte frame floods. - Add `mask_relay_max_bytes` to strictly bound unauthenticated fallback connections, preventing the proxy from being abused as an open relay. - Add a 5ms prefetch window (`mask_classifier_prefetch_timeout_ms`) to correctly assemble and classify fragmented HTTP/1.1 and HTTP/2 probes (e.g., `PRI * HTTP/2.0`) before routing them to masking heuristics. - Prevent recursive masking loops (FD exhaustion) by verifying the mask target is not the proxy's own listener via local interface enumeration. Concurrency & Reliability: - Eliminate executor waker storms during quota lock contention by replacing the spin-waker task with inline `Sleep` and exponential backoff. - Roll back user quota reservations (`rollback_me2c_quota_reservation`) if a network write fails, preventing Head-of-Line (HoL) blocking from permanently burning data quotas. - Recover gracefully from idle-registry `Mutex` poisoning instead of panicking, ensuring isolated thread failures do not break the proxy. - Fix `auth_probe_scan_start_offset` modulo logic to ensure bounds safety. Testing: - Add extensive adversarial, timing, fuzzing, and invariant test suites for both the client and handshake modules.
This commit is contained in:
@@ -0,0 +1,79 @@
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn exact_four_byte_http_tokens_are_classified() {
|
||||
for token in [b"GET ".as_ref(), b"POST".as_ref(), b"HEAD".as_ref(), b"PUT ".as_ref(), b"PRI ".as_ref()] {
|
||||
assert!(
|
||||
is_http_probe(token),
|
||||
"exact 4-byte token must be classified as HTTP probe: {:?}",
|
||||
token
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn exact_four_byte_non_http_tokens_are_not_classified() {
|
||||
for token in [
|
||||
b"GEX ".as_ref(),
|
||||
b"POXT".as_ref(),
|
||||
b"HEA/".as_ref(),
|
||||
b"PU\0 ".as_ref(),
|
||||
b"PRI/".as_ref(),
|
||||
] {
|
||||
assert!(
|
||||
!is_http_probe(token),
|
||||
"non-HTTP 4-byte token must not be classified: {:?}",
|
||||
token
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn detect_client_type_keeps_http_label_for_minimal_four_byte_http_prefixes() {
|
||||
assert_eq!(detect_client_type(b"GET "), "HTTP");
|
||||
assert_eq!(detect_client_type(b"PRI "), "HTTP");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn exact_long_http_tokens_are_classified() {
|
||||
for token in [b"CONNECT".as_ref(), b"TRACE".as_ref(), b"PATCH".as_ref()] {
|
||||
assert!(
|
||||
is_http_probe(token),
|
||||
"exact long HTTP token must be classified as HTTP probe: {:?}",
|
||||
token
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn detect_client_type_keeps_http_label_for_exact_long_http_tokens() {
|
||||
assert_eq!(detect_client_type(b"CONNECT"), "HTTP");
|
||||
assert_eq!(detect_client_type(b"TRACE"), "HTTP");
|
||||
assert_eq!(detect_client_type(b"PATCH"), "HTTP");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn light_fuzz_four_byte_ascii_noise_not_misclassified() {
|
||||
// Deterministic pseudo-fuzz over 4-byte printable ASCII inputs.
|
||||
let mut x = 0xA17C_93E5u32;
|
||||
for _ in 0..2048 {
|
||||
let mut token = [0u8; 4];
|
||||
for byte in &mut token {
|
||||
x = x.wrapping_mul(1664525).wrapping_add(1013904223);
|
||||
*byte = 32 + ((x & 0x3F) as u8); // printable ASCII subset
|
||||
}
|
||||
|
||||
if [b"GET ", b"POST", b"HEAD", b"PUT ", b"PRI "]
|
||||
.iter()
|
||||
.any(|m| token.as_slice() == *m)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
assert!(
|
||||
!is_http_probe(&token),
|
||||
"pseudo-fuzz noise misclassified as HTTP probe: {:?}",
|
||||
token
|
||||
);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user