mirror of
https://github.com/telemt/telemt.git
synced 2026-10-10 11:25:57 +03:00
Descriptor-anchored Secured Filesystem Operations
This commit is contained in:
@@ -25,6 +25,21 @@ impl RunningClientHandler {
|
||||
R: AsyncRead + Unpin + Send + 'static,
|
||||
W: AsyncWrite + Unpin + Send + 'static,
|
||||
{
|
||||
// Manually constructed handshake fixtures bypass credential validation, so
|
||||
// materialize the process-authority state that a real handshake generation owns.
|
||||
let config = if config.runtime_user_credential_id(&success.user).is_none() {
|
||||
let mut test_config = (*config).clone();
|
||||
test_config.access.users.insert(
|
||||
success.user.clone(),
|
||||
"00000000000000000000000000000000".to_string(),
|
||||
);
|
||||
test_config.rebuild_runtime_user_auth()?;
|
||||
Arc::new(test_config)
|
||||
} else {
|
||||
config
|
||||
};
|
||||
let shared = ProxySharedState::new();
|
||||
shared.apply_user_config(&config.access.users, &config.access.user_enabled);
|
||||
Self::handle_authenticated_static_with_shared(
|
||||
client_reader,
|
||||
client_writer,
|
||||
@@ -40,7 +55,7 @@ impl RunningClientHandler {
|
||||
local_addr,
|
||||
peer_addr,
|
||||
ip_tracker,
|
||||
ProxySharedState::new(),
|
||||
shared,
|
||||
)
|
||||
.await
|
||||
}
|
||||
|
||||
@@ -77,6 +77,7 @@ pub(crate) use self::auth_probe::{
|
||||
auth_probe_saturation_state_lock_for_testing_in_shared, auth_probe_state_for_testing_in_shared,
|
||||
auth_probe_slots_for_testing_in_shared, clear_auth_probe_state_for_testing_in_shared,
|
||||
clear_unknown_sni_warn_state_for_testing_in_shared, clear_warned_secrets_for_testing_in_shared,
|
||||
insert_auth_probe_state_for_testing_in_shared,
|
||||
should_emit_unknown_sni_warn_for_testing_in_shared, warned_secrets_for_testing_in_shared,
|
||||
};
|
||||
|
||||
|
||||
@@ -42,7 +42,7 @@ pub(super) fn ip_prefix_hint_key(peer_ip: IpAddr) -> u64 {
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) fn sticky_hint_get_by_ip(shared: &ProxySharedState, peer_ip: IpAddr) -> Option<u32> {
|
||||
pub(super) fn sticky_hint_get_by_ip(shared: &ProxySharedState, peer_ip: IpAddr) -> Option<u64> {
|
||||
shared
|
||||
.handshake
|
||||
.sticky_user_by_ip
|
||||
@@ -53,7 +53,7 @@ pub(super) fn sticky_hint_get_by_ip(shared: &ProxySharedState, peer_ip: IpAddr)
|
||||
pub(super) fn sticky_hint_get_by_ip_prefix(
|
||||
shared: &ProxySharedState,
|
||||
peer_ip: IpAddr,
|
||||
) -> Option<u32> {
|
||||
) -> Option<u64> {
|
||||
shared
|
||||
.handshake
|
||||
.sticky_user_by_ip_prefix
|
||||
@@ -61,7 +61,7 @@ pub(super) fn sticky_hint_get_by_ip_prefix(
|
||||
.map(|entry| *entry)
|
||||
}
|
||||
|
||||
pub(super) fn sticky_hint_get_by_sni(shared: &ProxySharedState, sni: &str) -> Option<u32> {
|
||||
pub(super) fn sticky_hint_get_by_sni(shared: &ProxySharedState, sni: &str) -> Option<u64> {
|
||||
let key = sni_hint_hash(sni);
|
||||
shared
|
||||
.handshake
|
||||
@@ -73,20 +73,20 @@ pub(super) fn sticky_hint_get_by_sni(shared: &ProxySharedState, sni: &str) -> Op
|
||||
pub(super) fn sticky_hint_record_success_in(
|
||||
shared: &ProxySharedState,
|
||||
peer_ip: IpAddr,
|
||||
user_id: u32,
|
||||
hint_key: u64,
|
||||
sni: Option<&str>,
|
||||
) {
|
||||
bounded_sticky_hint_upsert(
|
||||
&shared.handshake.sticky_user_by_ip,
|
||||
&shared.handshake.sticky_user_by_ip_slots,
|
||||
peer_ip,
|
||||
user_id,
|
||||
hint_key,
|
||||
);
|
||||
bounded_sticky_hint_upsert(
|
||||
&shared.handshake.sticky_user_by_ip_prefix,
|
||||
&shared.handshake.sticky_user_by_ip_prefix_slots,
|
||||
ip_prefix_hint_key(peer_ip),
|
||||
user_id,
|
||||
hint_key,
|
||||
);
|
||||
|
||||
if let Some(sni) = sni {
|
||||
@@ -94,34 +94,55 @@ pub(super) fn sticky_hint_record_success_in(
|
||||
&shared.handshake.sticky_user_by_sni_hash,
|
||||
&shared.handshake.sticky_user_by_sni_hash_slots,
|
||||
sni_hint_hash(sni),
|
||||
user_id,
|
||||
hint_key,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
fn bounded_sticky_hint_upsert<K>(
|
||||
entries: &DashMap<K, u32>,
|
||||
entries: &DashMap<K, u64>,
|
||||
slots: &crate::slot_budget::SlotBudget,
|
||||
key: K,
|
||||
user_id: u32,
|
||||
hint_key: u64,
|
||||
) where
|
||||
K: Eq + Hash,
|
||||
K: Clone + Eq + Hash,
|
||||
{
|
||||
match entries.entry(key) {
|
||||
Entry::Occupied(mut entry) => {
|
||||
entry.insert(user_id);
|
||||
if let Some(mut existing) = entries.get_mut(&key) {
|
||||
*existing = hint_key;
|
||||
return;
|
||||
}
|
||||
|
||||
for _ in 0..2 {
|
||||
if let Some(slot) = slots.try_acquire() {
|
||||
match entries.entry(key.clone()) {
|
||||
Entry::Occupied(mut entry) => {
|
||||
entry.insert(hint_key);
|
||||
}
|
||||
Entry::Vacant(entry) => {
|
||||
entry.insert(hint_key);
|
||||
slot.commit();
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
Entry::Vacant(entry) => {
|
||||
let Some(slot) = slots.try_acquire() else {
|
||||
return;
|
||||
};
|
||||
entry.insert(user_id);
|
||||
slot.commit();
|
||||
|
||||
let Some((victim_key, victim_hint_key)) = entries
|
||||
.iter()
|
||||
.next()
|
||||
.map(|entry| (entry.key().clone(), *entry.value()))
|
||||
else {
|
||||
return;
|
||||
};
|
||||
if entries
|
||||
.remove_if(&victim_key, |_, current| *current == victim_hint_key)
|
||||
.is_some()
|
||||
{
|
||||
slots.release();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) fn record_recent_user_success_in(shared: &ProxySharedState, user_id: u32) {
|
||||
pub(super) fn record_recent_user_success_in(shared: &ProxySharedState, hint_key: u64) {
|
||||
let ring = &shared.handshake.recent_user_ring;
|
||||
if ring.is_empty() {
|
||||
return;
|
||||
@@ -131,7 +152,7 @@ pub(super) fn record_recent_user_success_in(shared: &ProxySharedState, user_id:
|
||||
.recent_user_ring_seq
|
||||
.fetch_add(1, Ordering::Relaxed);
|
||||
let idx = (seq as usize) % ring.len();
|
||||
ring[idx].store(user_id.saturating_add(1), Ordering::Relaxed);
|
||||
ring[idx].store(hint_key, Ordering::Relaxed);
|
||||
}
|
||||
|
||||
pub(super) fn mark_candidate_if_new(
|
||||
@@ -387,7 +408,7 @@ mod bounded_registry_tests {
|
||||
sticky_hint_record_success_in(
|
||||
shared.as_ref(),
|
||||
peer_ip,
|
||||
index as u32,
|
||||
index as u64 | 1,
|
||||
Some(&format!("host-{index}.example")),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -21,8 +21,10 @@ pub(crate) fn auth_probe_fail_streak_for_testing_in_shared(
|
||||
}
|
||||
|
||||
pub(crate) fn clear_auth_probe_state_for_testing_in_shared(shared: &ProxySharedState) {
|
||||
let removed = shared.handshake.auth_probe.len();
|
||||
assert_eq!(shared.handshake.auth_probe_slots.used(), removed);
|
||||
shared.handshake.auth_probe.clear();
|
||||
shared.handshake.auth_probe_slots.reset_for_testing();
|
||||
shared.handshake.auth_probe_slots.release_many(removed);
|
||||
match shared.handshake.auth_probe_saturation.lock() {
|
||||
Ok(mut saturation) => {
|
||||
*saturation = None;
|
||||
@@ -35,6 +37,28 @@ pub(crate) fn clear_auth_probe_state_for_testing_in_shared(shared: &ProxySharedS
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn insert_auth_probe_state_for_testing_in_shared(
|
||||
shared: &ProxySharedState,
|
||||
peer_ip: IpAddr,
|
||||
state: AuthProbeState,
|
||||
) {
|
||||
let peer_ip = normalize_auth_probe_ip(peer_ip);
|
||||
let slot = shared
|
||||
.handshake
|
||||
.auth_probe_slots
|
||||
.try_acquire()
|
||||
.expect("test auth-probe registry capacity must be available");
|
||||
match shared.handshake.auth_probe.entry(peer_ip) {
|
||||
Entry::Occupied(mut entry) => {
|
||||
entry.insert(state);
|
||||
}
|
||||
Entry::Vacant(entry) => {
|
||||
entry.insert(state);
|
||||
slot.commit();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn auth_probe_state_for_testing_in_shared(
|
||||
shared: &ProxySharedState,
|
||||
) -> &DashMap<IpAddr, AuthProbeState> {
|
||||
|
||||
@@ -151,10 +151,14 @@ where
|
||||
if let Some(snapshot) = config.runtime_user_auth() {
|
||||
let sticky_ip_hint = sticky_hint_get_by_ip(shared, peer.ip());
|
||||
let sticky_prefix_hint = sticky_hint_get_by_ip_prefix(shared, peer.ip());
|
||||
let sticky_ip_candidates = sticky_ip_hint
|
||||
.and_then(|hint_key| snapshot.candidate_ids_by_hint_key(hint_key));
|
||||
let sticky_prefix_candidates = sticky_prefix_hint
|
||||
.and_then(|hint_key| snapshot.candidate_ids_by_hint_key(hint_key));
|
||||
let preferred_user_id = preferred_user.and_then(|user| snapshot.user_id_by_name(user));
|
||||
let exact_user_id = exact_user.and_then(|user| snapshot.user_id_by_name(user));
|
||||
let has_hint = sticky_ip_hint.is_some()
|
||||
|| sticky_prefix_hint.is_some()
|
||||
let has_hint = sticky_ip_candidates.is_some_and(|ids| !ids.is_empty())
|
||||
|| sticky_prefix_candidates.is_some_and(|ids| !ids.is_empty())
|
||||
|| preferred_user_id.is_some()
|
||||
|| exact_user_id.is_some();
|
||||
let overload = auth_probe_saturation_is_throttled_in(shared, Instant::now());
|
||||
@@ -204,9 +208,17 @@ where
|
||||
|
||||
let mut matched = exact_user_id.is_some_and(|user_id| try_user_id!(user_id));
|
||||
if exact_user.is_none()
|
||||
&& let Some(user_id) = sticky_ip_hint
|
||||
&& let Some(candidate_ids) = sticky_ip_candidates
|
||||
{
|
||||
matched = try_user_id!(user_id);
|
||||
for &user_id in candidate_ids {
|
||||
if try_user_id!(user_id) {
|
||||
matched = true;
|
||||
break;
|
||||
}
|
||||
if budget_exhausted {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if exact_user.is_none()
|
||||
@@ -218,9 +230,17 @@ where
|
||||
|
||||
if exact_user.is_none()
|
||||
&& !matched
|
||||
&& let Some(user_id) = sticky_prefix_hint
|
||||
&& let Some(candidate_ids) = sticky_prefix_candidates
|
||||
{
|
||||
matched = try_user_id!(user_id);
|
||||
for &user_id in candidate_ids {
|
||||
if try_user_id!(user_id) {
|
||||
matched = true;
|
||||
break;
|
||||
}
|
||||
if budget_exhausted {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if exact_user.is_none() && !matched && !budget_exhausted {
|
||||
@@ -231,18 +251,22 @@ where
|
||||
.recent_user_ring_seq
|
||||
.load(Ordering::Relaxed);
|
||||
let scan_limit = ring.len().min(RECENT_USER_RING_SCAN_LIMIT);
|
||||
for offset in 0..scan_limit {
|
||||
'recent_hints: for offset in 0..scan_limit {
|
||||
let idx = (next_seq as usize + ring.len() - 1 - offset) % ring.len();
|
||||
let encoded_user_id = ring[idx].load(Ordering::Relaxed);
|
||||
if encoded_user_id == 0 {
|
||||
let hint_key = ring[idx].load(Ordering::Relaxed);
|
||||
if hint_key == 0 {
|
||||
continue;
|
||||
}
|
||||
if try_user_id!(encoded_user_id - 1) {
|
||||
matched = true;
|
||||
break;
|
||||
}
|
||||
if budget_exhausted {
|
||||
break;
|
||||
if let Some(candidate_ids) = snapshot.candidate_ids_by_hint_key(hint_key) {
|
||||
for &user_id in candidate_ids {
|
||||
if try_user_id!(user_id) {
|
||||
matched = true;
|
||||
break 'recent_hints;
|
||||
}
|
||||
if budget_exhausted {
|
||||
break 'recent_hints;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -357,8 +381,10 @@ where
|
||||
|
||||
auth_probe_record_success_in(shared, peer.ip());
|
||||
if let Some(user_id) = matched_user_id {
|
||||
sticky_hint_record_success_in(shared, peer.ip(), user_id, None);
|
||||
record_recent_user_success_in(shared, user_id);
|
||||
if let Some(entry) = snapshot.entry_by_id(user_id) {
|
||||
sticky_hint_record_success_in(shared, peer.ip(), entry.hint_key, None);
|
||||
record_recent_user_success_in(shared, entry.hint_key);
|
||||
}
|
||||
}
|
||||
|
||||
let max_pending = config.general.crypto_pending_buffer;
|
||||
|
||||
@@ -396,8 +396,18 @@ where
|
||||
auth_probe_record_success_in(shared, peer.ip());
|
||||
|
||||
if let Some(user_id) = validated_user_id {
|
||||
sticky_hint_record_success_in(shared, peer.ip(), user_id, client_sni.as_deref());
|
||||
record_recent_user_success_in(shared, user_id);
|
||||
if let Some(entry) = config
|
||||
.runtime_user_auth()
|
||||
.and_then(|snapshot| snapshot.entry_by_id(user_id))
|
||||
{
|
||||
sticky_hint_record_success_in(
|
||||
shared,
|
||||
peer.ip(),
|
||||
entry.hint_key,
|
||||
client_sni.as_deref(),
|
||||
);
|
||||
record_recent_user_success_in(shared, entry.hint_key);
|
||||
}
|
||||
}
|
||||
|
||||
HandshakeResult::Success((
|
||||
|
||||
@@ -40,11 +40,17 @@ pub(super) async fn validate_tls_client(
|
||||
};
|
||||
|
||||
let sticky_ip_hint = sticky_hint_get_by_ip(shared, peer.ip());
|
||||
let sticky_ip_candidates = sticky_ip_hint
|
||||
.and_then(|hint_key| snapshot.candidate_ids_by_hint_key(hint_key));
|
||||
let preferred_user_id = preferred_user_hint.and_then(|user| snapshot.user_id_by_name(user));
|
||||
let sticky_sni_hint = client_sni
|
||||
.as_deref()
|
||||
.and_then(|sni| sticky_hint_get_by_sni(shared, sni));
|
||||
let sticky_sni_candidates = sticky_sni_hint
|
||||
.and_then(|hint_key| snapshot.candidate_ids_by_hint_key(hint_key));
|
||||
let sticky_prefix_hint = sticky_hint_get_by_ip_prefix(shared, peer.ip());
|
||||
let sticky_prefix_candidates = sticky_prefix_hint
|
||||
.and_then(|hint_key| snapshot.candidate_ids_by_hint_key(hint_key));
|
||||
let sni_candidates = client_sni
|
||||
.as_deref()
|
||||
.and_then(|sni| snapshot.sni_candidates(sni));
|
||||
@@ -52,10 +58,10 @@ pub(super) async fn validate_tls_client(
|
||||
.as_deref()
|
||||
.and_then(|sni| snapshot.sni_initial_candidates(sni));
|
||||
|
||||
let has_hint = sticky_ip_hint.is_some()
|
||||
let has_hint = sticky_ip_candidates.is_some_and(|ids| !ids.is_empty())
|
||||
|| preferred_user_id.is_some()
|
||||
|| sticky_sni_hint.is_some()
|
||||
|| sticky_prefix_hint.is_some()
|
||||
|| sticky_sni_candidates.is_some_and(|ids| !ids.is_empty())
|
||||
|| sticky_prefix_candidates.is_some_and(|ids| !ids.is_empty())
|
||||
|| sni_candidates.is_some_and(|ids| !ids.is_empty())
|
||||
|| sni_initial_candidates.is_some_and(|ids| !ids.is_empty());
|
||||
let overload = auth_probe_saturation_is_throttled_in(shared, Instant::now());
|
||||
@@ -95,20 +101,44 @@ pub(super) async fn validate_tls_client(
|
||||
}
|
||||
|
||||
let mut matched = false;
|
||||
if let Some(user_id) = sticky_ip_hint {
|
||||
matched = try_user_id!(user_id);
|
||||
if let Some(candidate_ids) = sticky_ip_candidates {
|
||||
for &user_id in candidate_ids {
|
||||
if try_user_id!(user_id) {
|
||||
matched = true;
|
||||
break;
|
||||
}
|
||||
if budget_exhausted {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if !matched && let Some(user_id) = preferred_user_id {
|
||||
matched = try_user_id!(user_id);
|
||||
}
|
||||
|
||||
if !matched && let Some(user_id) = sticky_sni_hint {
|
||||
matched = try_user_id!(user_id);
|
||||
if !matched && let Some(candidate_ids) = sticky_sni_candidates {
|
||||
for &user_id in candidate_ids {
|
||||
if try_user_id!(user_id) {
|
||||
matched = true;
|
||||
break;
|
||||
}
|
||||
if budget_exhausted {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if !matched && let Some(user_id) = sticky_prefix_hint {
|
||||
matched = try_user_id!(user_id);
|
||||
if !matched && let Some(candidate_ids) = sticky_prefix_candidates {
|
||||
for &user_id in candidate_ids {
|
||||
if try_user_id!(user_id) {
|
||||
matched = true;
|
||||
break;
|
||||
}
|
||||
if budget_exhausted {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if !matched
|
||||
@@ -149,18 +179,22 @@ pub(super) async fn validate_tls_client(
|
||||
.recent_user_ring_seq
|
||||
.load(Ordering::Relaxed);
|
||||
let scan_limit = ring.len().min(RECENT_USER_RING_SCAN_LIMIT);
|
||||
for offset in 0..scan_limit {
|
||||
'recent_hints: for offset in 0..scan_limit {
|
||||
let idx = (next_seq as usize + ring.len() - 1 - offset) % ring.len();
|
||||
let encoded_user_id = ring[idx].load(Ordering::Relaxed);
|
||||
if encoded_user_id == 0 {
|
||||
let hint_key = ring[idx].load(Ordering::Relaxed);
|
||||
if hint_key == 0 {
|
||||
continue;
|
||||
}
|
||||
if try_user_id!(encoded_user_id - 1) {
|
||||
matched = true;
|
||||
break;
|
||||
}
|
||||
if budget_exhausted {
|
||||
break;
|
||||
if let Some(candidate_ids) = snapshot.candidate_ids_by_hint_key(hint_key) {
|
||||
for &user_id in candidate_ids {
|
||||
if try_user_id!(user_id) {
|
||||
matched = true;
|
||||
break 'recent_hints;
|
||||
}
|
||||
if budget_exhausted {
|
||||
break 'recent_hints;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
use std::collections::hash_map::RandomState;
|
||||
use std::collections::{HashMap, HashSet};
|
||||
use std::net::{IpAddr, SocketAddr};
|
||||
use std::sync::atomic::{AtomicBool, AtomicU32, AtomicU64, Ordering};
|
||||
use std::sync::atomic::{AtomicBool, AtomicU64, Ordering};
|
||||
use std::sync::{Arc, Mutex};
|
||||
use std::time::Instant;
|
||||
|
||||
@@ -61,13 +61,13 @@ pub(crate) struct HandshakeSharedState {
|
||||
pub(crate) auth_probe_eviction_hasher: RandomState,
|
||||
pub(crate) invalid_secret_warned: Mutex<HashSet<(String, String)>>,
|
||||
pub(crate) unknown_sni_warn_next_allowed: Mutex<Option<Instant>>,
|
||||
pub(crate) sticky_user_by_ip: DashMap<IpAddr, u32>,
|
||||
pub(crate) sticky_user_by_ip: DashMap<IpAddr, u64>,
|
||||
pub(crate) sticky_user_by_ip_slots: SlotBudget,
|
||||
pub(crate) sticky_user_by_ip_prefix: DashMap<u64, u32>,
|
||||
pub(crate) sticky_user_by_ip_prefix: DashMap<u64, u64>,
|
||||
pub(crate) sticky_user_by_ip_prefix_slots: SlotBudget,
|
||||
pub(crate) sticky_user_by_sni_hash: DashMap<u64, u32>,
|
||||
pub(crate) sticky_user_by_sni_hash: DashMap<u64, u64>,
|
||||
pub(crate) sticky_user_by_sni_hash_slots: SlotBudget,
|
||||
pub(crate) recent_user_ring: Box<[AtomicU32]>,
|
||||
pub(crate) recent_user_ring: Box<[AtomicU64]>,
|
||||
pub(crate) recent_user_ring_seq: AtomicU64,
|
||||
pub(crate) auth_expensive_checks_total: AtomicU64,
|
||||
pub(crate) auth_budget_exhausted_total: AtomicU64,
|
||||
@@ -138,7 +138,7 @@ impl ProxySharedState {
|
||||
sticky_user_by_sni_hash_slots: SlotBudget::new(
|
||||
crate::proxy::handshake::STICKY_HINT_MAX_ENTRIES,
|
||||
),
|
||||
recent_user_ring: std::iter::repeat_with(|| AtomicU32::new(0))
|
||||
recent_user_ring: std::iter::repeat_with(|| AtomicU64::new(0))
|
||||
.take(HANDSHAKE_RECENT_USER_RING_LEN)
|
||||
.collect::<Vec<_>>()
|
||||
.into_boxed_slice(),
|
||||
|
||||
@@ -1241,7 +1241,10 @@ async fn tls_runtime_snapshot_updates_sticky_and_recent_hints() {
|
||||
.sticky_user_by_ip
|
||||
.get(&peer.ip())
|
||||
.map(|entry| *entry),
|
||||
Some(0),
|
||||
config
|
||||
.runtime_user_auth()
|
||||
.and_then(|snapshot| snapshot.entry_by_id(0))
|
||||
.map(|entry| entry.hint_key),
|
||||
"successful runtime-snapshot auth must seed sticky ip cache"
|
||||
);
|
||||
assert_eq!(
|
||||
@@ -3047,7 +3050,8 @@ async fn valid_tls_is_blocked_by_per_ip_preauth_throttle_without_saturation() {
|
||||
let rng = SecureRandom::new();
|
||||
let peer: SocketAddr = "198.51.100.103:45103".parse().unwrap();
|
||||
|
||||
auth_probe_state_for_testing_in_shared(shared.as_ref()).insert(
|
||||
insert_auth_probe_state_for_testing_in_shared(
|
||||
shared.as_ref(),
|
||||
normalize_auth_probe_ip(peer.ip()),
|
||||
AuthProbeState {
|
||||
fail_streak: AUTH_PROBE_BACKOFF_START_FAILS,
|
||||
@@ -3085,7 +3089,8 @@ async fn saturation_allows_valid_tls_even_when_peer_ip_is_currently_throttled()
|
||||
let peer: SocketAddr = "198.51.100.104:45104".parse().unwrap();
|
||||
let now = Instant::now();
|
||||
|
||||
auth_probe_state_for_testing_in_shared(shared.as_ref()).insert(
|
||||
insert_auth_probe_state_for_testing_in_shared(
|
||||
shared.as_ref(),
|
||||
normalize_auth_probe_ip(peer.ip()),
|
||||
AuthProbeState {
|
||||
fail_streak: AUTH_PROBE_BACKOFF_START_FAILS,
|
||||
@@ -3181,7 +3186,8 @@ async fn saturation_grace_exhaustion_preauth_throttles_repeated_invalid_tls_prob
|
||||
let rng = SecureRandom::new();
|
||||
let peer: SocketAddr = "198.51.100.205:45205".parse().unwrap();
|
||||
let now = Instant::now();
|
||||
auth_probe_state_for_testing_in_shared(shared.as_ref()).insert(
|
||||
insert_auth_probe_state_for_testing_in_shared(
|
||||
shared.as_ref(),
|
||||
normalize_auth_probe_ip(peer.ip()),
|
||||
AuthProbeState {
|
||||
fail_streak: AUTH_PROBE_BACKOFF_START_FAILS + AUTH_PROBE_SATURATION_GRACE_FAILS,
|
||||
@@ -3235,7 +3241,8 @@ async fn saturation_allows_valid_mtproto_even_when_peer_ip_is_currently_throttle
|
||||
let peer: SocketAddr = "198.51.100.106:45106".parse().unwrap();
|
||||
let now = Instant::now();
|
||||
|
||||
auth_probe_state_for_testing_in_shared(shared.as_ref()).insert(
|
||||
insert_auth_probe_state_for_testing_in_shared(
|
||||
shared.as_ref(),
|
||||
normalize_auth_probe_ip(peer.ip()),
|
||||
AuthProbeState {
|
||||
fail_streak: AUTH_PROBE_BACKOFF_START_FAILS,
|
||||
@@ -3328,7 +3335,8 @@ async fn saturation_grace_exhaustion_preauth_throttles_repeated_invalid_mtproto_
|
||||
let replay_checker = ReplayChecker::new(128, Duration::from_secs(60));
|
||||
let peer: SocketAddr = "198.51.100.206:45206".parse().unwrap();
|
||||
let now = Instant::now();
|
||||
auth_probe_state_for_testing_in_shared(shared.as_ref()).insert(
|
||||
insert_auth_probe_state_for_testing_in_shared(
|
||||
shared.as_ref(),
|
||||
normalize_auth_probe_ip(peer.ip()),
|
||||
AuthProbeState {
|
||||
fail_streak: AUTH_PROBE_BACKOFF_START_FAILS + AUTH_PROBE_SATURATION_GRACE_FAILS,
|
||||
@@ -3378,7 +3386,8 @@ async fn saturation_grace_progression_tls_reaches_cap_then_stops_incrementing()
|
||||
let rng = SecureRandom::new();
|
||||
let peer: SocketAddr = "198.51.100.207:45207".parse().unwrap();
|
||||
let now = Instant::now();
|
||||
auth_probe_state_for_testing_in_shared(shared.as_ref()).insert(
|
||||
insert_auth_probe_state_for_testing_in_shared(
|
||||
shared.as_ref(),
|
||||
normalize_auth_probe_ip(peer.ip()),
|
||||
AuthProbeState {
|
||||
fail_streak: AUTH_PROBE_BACKOFF_START_FAILS,
|
||||
@@ -3461,7 +3470,8 @@ async fn saturation_grace_progression_mtproto_reaches_cap_then_stops_incrementin
|
||||
let replay_checker = ReplayChecker::new(128, Duration::from_secs(60));
|
||||
let peer: SocketAddr = "198.51.100.208:45208".parse().unwrap();
|
||||
let now = Instant::now();
|
||||
auth_probe_state_for_testing_in_shared(shared.as_ref()).insert(
|
||||
insert_auth_probe_state_for_testing_in_shared(
|
||||
shared.as_ref(),
|
||||
normalize_auth_probe_ip(peer.ip()),
|
||||
AuthProbeState {
|
||||
fail_streak: AUTH_PROBE_BACKOFF_START_FAILS,
|
||||
@@ -3545,7 +3555,8 @@ async fn saturation_grace_boundary_still_admits_valid_tls_before_exhaustion() {
|
||||
let rng = SecureRandom::new();
|
||||
let peer: SocketAddr = "198.51.100.209:45209".parse().unwrap();
|
||||
let now = Instant::now();
|
||||
auth_probe_state_for_testing_in_shared(shared.as_ref()).insert(
|
||||
insert_auth_probe_state_for_testing_in_shared(
|
||||
shared.as_ref(),
|
||||
normalize_auth_probe_ip(peer.ip()),
|
||||
AuthProbeState {
|
||||
fail_streak: AUTH_PROBE_BACKOFF_START_FAILS + AUTH_PROBE_SATURATION_GRACE_FAILS - 1,
|
||||
@@ -3599,7 +3610,8 @@ async fn saturation_grace_exhaustion_blocks_valid_tls_until_backoff_expires() {
|
||||
let rng = SecureRandom::new();
|
||||
let peer: SocketAddr = "198.51.100.210:45210".parse().unwrap();
|
||||
let now = Instant::now();
|
||||
auth_probe_state_for_testing_in_shared(shared.as_ref()).insert(
|
||||
insert_auth_probe_state_for_testing_in_shared(
|
||||
shared.as_ref(),
|
||||
normalize_auth_probe_ip(peer.ip()),
|
||||
AuthProbeState {
|
||||
fail_streak: AUTH_PROBE_BACKOFF_START_FAILS + AUTH_PROBE_SATURATION_GRACE_FAILS,
|
||||
@@ -3667,7 +3679,8 @@ async fn saturation_grace_exhaustion_is_shared_across_tls_and_mtproto_for_same_p
|
||||
let rng = SecureRandom::new();
|
||||
let peer: SocketAddr = "198.51.100.211:45211".parse().unwrap();
|
||||
let now = Instant::now();
|
||||
auth_probe_state_for_testing_in_shared(shared.as_ref()).insert(
|
||||
insert_auth_probe_state_for_testing_in_shared(
|
||||
shared.as_ref(),
|
||||
normalize_auth_probe_ip(peer.ip()),
|
||||
AuthProbeState {
|
||||
fail_streak: AUTH_PROBE_BACKOFF_START_FAILS + AUTH_PROBE_SATURATION_GRACE_FAILS,
|
||||
@@ -3735,7 +3748,8 @@ async fn adversarial_same_peer_invalid_tls_storm_does_not_bypass_saturation_grac
|
||||
let rng = Arc::new(SecureRandom::new());
|
||||
let peer: SocketAddr = "198.51.100.212:45212".parse().unwrap();
|
||||
let now = Instant::now();
|
||||
auth_probe_state_for_testing_in_shared(shared.as_ref()).insert(
|
||||
insert_auth_probe_state_for_testing_in_shared(
|
||||
shared.as_ref(),
|
||||
normalize_auth_probe_ip(peer.ip()),
|
||||
AuthProbeState {
|
||||
fail_streak: AUTH_PROBE_BACKOFF_START_FAILS + AUTH_PROBE_SATURATION_GRACE_FAILS,
|
||||
@@ -3801,7 +3815,8 @@ async fn light_fuzz_saturation_grace_tls_invalid_inputs_never_authenticate_or_pa
|
||||
let rng = SecureRandom::new();
|
||||
let peer: SocketAddr = "198.51.100.213:45213".parse().unwrap();
|
||||
let now = Instant::now();
|
||||
auth_probe_state_for_testing_in_shared(shared.as_ref()).insert(
|
||||
insert_auth_probe_state_for_testing_in_shared(
|
||||
shared.as_ref(),
|
||||
normalize_auth_probe_ip(peer.ip()),
|
||||
AuthProbeState {
|
||||
fail_streak: AUTH_PROBE_BACKOFF_START_FAILS + AUTH_PROBE_SATURATION_GRACE_FAILS,
|
||||
@@ -3986,7 +4001,8 @@ async fn expired_saturation_keeps_per_ip_throttle_enforced_for_valid_tls() {
|
||||
let peer: SocketAddr = "198.51.100.110:45110".parse().unwrap();
|
||||
let now = Instant::now();
|
||||
|
||||
auth_probe_state_for_testing_in_shared(shared.as_ref()).insert(
|
||||
insert_auth_probe_state_for_testing_in_shared(
|
||||
shared.as_ref(),
|
||||
normalize_auth_probe_ip(peer.ip()),
|
||||
AuthProbeState {
|
||||
fail_streak: AUTH_PROBE_BACKOFF_START_FAILS,
|
||||
|
||||
Reference in New Issue
Block a user