mirror of
https://github.com/telemt/telemt.git
synced 2026-06-24 20:01:11 +03:00
91be148b72
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.
52 lines
1.4 KiB
Rust
52 lines
1.4 KiB
Rust
use super::*;
|
|
use std::pin::Pin;
|
|
use std::task::{Context, Poll};
|
|
use std::time::Instant;
|
|
use tokio::io::AsyncWrite;
|
|
|
|
struct NeverWritable;
|
|
|
|
impl AsyncWrite for NeverWritable {
|
|
fn poll_write(
|
|
self: Pin<&mut Self>,
|
|
_cx: &mut Context<'_>,
|
|
_buf: &[u8],
|
|
) -> Poll<std::io::Result<usize>> {
|
|
Poll::Pending
|
|
}
|
|
|
|
fn poll_flush(self: Pin<&mut Self>, _cx: &mut Context<'_>) -> Poll<std::io::Result<()>> {
|
|
Poll::Pending
|
|
}
|
|
|
|
fn poll_shutdown(self: Pin<&mut Self>, _cx: &mut Context<'_>) -> Poll<std::io::Result<()>> {
|
|
Poll::Ready(Ok(()))
|
|
}
|
|
}
|
|
|
|
#[tokio::test]
|
|
async fn shape_padding_returns_before_global_mask_timeout_on_blocked_writer() {
|
|
let mut writer = NeverWritable;
|
|
let started = Instant::now();
|
|
|
|
maybe_write_shape_padding(&mut writer, 1, true, 256, 4096, false, 0, false).await;
|
|
|
|
assert!(
|
|
started.elapsed() <= MASK_TIMEOUT + std::time::Duration::from_millis(30),
|
|
"shape padding blocked past timeout budget"
|
|
);
|
|
}
|
|
|
|
#[tokio::test]
|
|
async fn shape_padding_with_non_http_blur_disabled_at_cap_writes_nothing() {
|
|
let mut output = Vec::new();
|
|
{
|
|
let mut writer = tokio::io::BufWriter::new(&mut output);
|
|
maybe_write_shape_padding(&mut writer, 4096, true, 64, 4096, false, 128, false).await;
|
|
use tokio::io::AsyncWriteExt;
|
|
writer.flush().await.unwrap();
|
|
}
|
|
|
|
assert!(output.is_empty());
|
|
}
|