Files
telemt/src/synlimit_control/pf_runtime_tests.rs
T
2026-08-22 16:31:49 +03:00

81 lines
2.7 KiB
Rust

use std::net::{IpAddr, Ipv4Addr, Ipv6Addr};
use std::path::Path;
use std::time::Duration;
use super::*;
use crate::synlimit_control::model::{
SynLimitNamespace, SynLimitRule, SynLimitTargets, synlimit_namespace,
};
fn rule(ip: IpAddr, hitcount: u32) -> SynLimitRule {
SynLimitRule {
ip: Some(ip),
port: 24443,
generic_seconds: 60,
generic_hitcount: hitcount,
generic_burst: 24,
ios_seconds: 1,
ios_hitcount: 12,
ios_burst: 24,
hashlimit_expire_ms: 60_000,
hashlimit_size: 32_768,
}
}
fn targets(low_family: &str) -> SynLimitTargets {
let (v4_rate, v6_rate) = match low_family {
"v4" => (2, 100),
"v6" => (100, 2),
_ => panic!("TELEMT_PF_LOW_FAMILY must be v4 or v6"),
};
SynLimitTargets {
pf_v4: vec![rule(IpAddr::V4(Ipv4Addr::new(198, 18, 1, 1)), v4_rate)],
pf_v6: vec![rule(
IpAddr::V6("fd00:18:1::1".parse::<Ipv6Addr>().unwrap()),
v6_rate,
)],
..Default::default()
}
}
fn write_metadata(path: &str, namespace: &SynLimitNamespace) {
std::fs::write(path, format!("anchor={}\n", namespace.pf_anchor)).unwrap();
}
async fn wait_for_file(path: &Path) {
tokio::time::timeout(Duration::from_secs(30), async {
while !path.exists() {
tokio::time::sleep(Duration::from_millis(20)).await;
}
})
.await
.expect("PF runtime-test release barrier timed out");
}
#[tokio::test]
#[ignore = "requires native FreeBSD PF and VNET test harness"]
async fn production_pf_runtime_role() {
let role = std::env::var("TELEMT_PF_ROLE").expect("TELEMT_PF_ROLE is required");
let low_family = std::env::var("TELEMT_PF_LOW_FAMILY").unwrap_or_else(|_| "v4".to_string());
let targets = targets(&low_family);
let namespace = synlimit_namespace(&targets).expect("PF namespace missing");
let metadata = std::env::var("TELEMT_PF_META").expect("TELEMT_PF_META is required");
match role.as_str() {
"render" => {
let script_path = std::env::var("TELEMT_PF_SCRIPT").unwrap();
std::fs::write(script_path, pf_synlimit_script(&targets)).unwrap();
write_metadata(&metadata, &namespace);
}
"apply-wait" => {
apply_synlimit_rules(&targets, &namespace).await.unwrap();
write_metadata(&metadata, &namespace);
let barrier = std::env::var("TELEMT_PF_BARRIER").unwrap();
let release = std::env::var("TELEMT_PF_RELEASE").unwrap();
std::fs::write(&barrier, b"ready").unwrap();
wait_for_file(Path::new(&release)).await;
assert!(clear_rules(&namespace).await.unwrap());
}
_ => panic!("TELEMT_PF_ROLE must be render or apply-wait"),
}
}