Refactor and enhance tests for proxy and relay functionality

- Renamed test functions in `client_tls_clienthello_truncation_adversarial_tests.rs` to remove "but_leaks" suffix for clarity.
- Added new tests in `direct_relay_business_logic_tests.rs` to validate business logic for data center resolution and scope hints.
- Introduced tests in `direct_relay_common_mistakes_tests.rs` to cover common mistakes in direct relay configurations.
- Added security tests in `direct_relay_security_tests.rs` to ensure proper handling of symlink and parent swap scenarios.
- Created `direct_relay_subtle_adversarial_tests.rs` to stress test concurrent logging and validate scope hint behavior.
- Implemented `relay_quota_lock_pressure_adversarial_tests.rs` to test quota lock behavior under high contention and stress.
- Updated `relay_security_tests.rs` to include quota lock contention tests ensuring proper behavior under concurrent access.
- Introduced `ip_tracker_hotpath_adversarial_tests.rs` to validate the performance and correctness of the IP tracking logic under various scenarios.
This commit is contained in:
David Osipov
2026-03-21 13:38:17 +04:00
parent 8188fedf6a
commit 5933b5e821
13 changed files with 1138 additions and 21 deletions

View File

@@ -307,9 +307,8 @@ fn extract_sni_with_duplicate_extensions_rejected() {
h.extend_from_slice(&(handshake.len() as u16).to_be_bytes());
h.extend_from_slice(&handshake);
// Parser might return first, see second, or fail. OWASP ASVS prefers rejection of unexpected dups.
// Telemt's `extract_sni` returns the first one found.
assert!(extract_sni_from_client_hello(&h).is_some());
// Duplicate SNI extensions are ambiguous and must fail closed.
assert!(extract_sni_from_client_hello(&h).is_none());
}
#[test]

View File

@@ -588,6 +588,9 @@ pub fn extract_sni_from_client_hello(handshake: &[u8]) -> Option<String> {
return None;
}
let mut saw_sni_extension = false;
let mut extracted_sni = None;
while pos + 4 <= ext_end {
let etype = u16::from_be_bytes([handshake[pos], handshake[pos + 1]]);
let elen = u16::from_be_bytes([handshake[pos + 2], handshake[pos + 3]]) as usize;
@@ -595,6 +598,12 @@ pub fn extract_sni_from_client_hello(handshake: &[u8]) -> Option<String> {
if pos + elen > ext_end {
break;
}
if etype == 0x0000 {
if saw_sni_extension {
return None;
}
saw_sni_extension = true;
}
if etype == 0x0000 && elen >= 5 {
// server_name extension
let list_len = u16::from_be_bytes([handshake[pos], handshake[pos + 1]]) as usize;
@@ -611,7 +620,8 @@ pub fn extract_sni_from_client_hello(handshake: &[u8]) -> Option<String> {
&& let Ok(host) = std::str::from_utf8(&handshake[sn_pos..sn_pos + name_len])
{
if is_valid_sni_hostname(host) {
return Some(host.to_string());
extracted_sni = Some(host.to_string());
break;
}
}
sn_pos += name_len;
@@ -620,7 +630,7 @@ pub fn extract_sni_from_client_hello(handshake: &[u8]) -> Option<String> {
pos += elen;
}
None
extracted_sni
}
fn is_valid_sni_hostname(host: &str) -> bool {