feat: CDN Control Plane (ONCP) implementation
- Add REST API for node/user management (axum-based) - Add NodeRegistry for server check-in and load balancing - Add SniManager for dynamic SNI updates and emergency blocking - Add CDN Dashboard CLI (oncp-master) with real-time monitoring - Add ProbeDetector in ostp-guard for active probing detection - Add iptables/nftables/Windows firewall ban integration - Extend MimicryEngine with async SNI updates from control plane - Fix all compilation warnings - Update author to ospab.team
This commit is contained in:
@@ -15,3 +15,4 @@ hmac.workspace = true
|
||||
sha2.workspace = true
|
||||
rand.workspace = true
|
||||
uuid.workspace = true
|
||||
serde.workspace = true
|
||||
|
||||
@@ -1,10 +1,14 @@
|
||||
//! Dynamic SNI & TLS Mimicry Engine
|
||||
|
||||
use std::collections::HashMap;
|
||||
use std::sync::Arc;
|
||||
use tokio::sync::RwLock;
|
||||
|
||||
/// Geo-based SNI target selection
|
||||
/// Geo-based SNI target selection with dynamic updates
|
||||
pub struct MimicryEngine {
|
||||
geo_sni_map: HashMap<String, Vec<String>>,
|
||||
/// Blocked domains (received from control plane)
|
||||
blocked: Arc<RwLock<std::collections::HashSet<String>>>,
|
||||
}
|
||||
|
||||
impl MimicryEngine {
|
||||
@@ -45,7 +49,10 @@ impl MimicryEngine {
|
||||
vec!["qq.com".into(), "baidu.com".into(), "taobao.com".into()],
|
||||
);
|
||||
|
||||
Self { geo_sni_map }
|
||||
Self {
|
||||
geo_sni_map,
|
||||
blocked: Arc::new(RwLock::new(std::collections::HashSet::new())),
|
||||
}
|
||||
}
|
||||
|
||||
/// Select SNI based on geo-location
|
||||
@@ -71,6 +78,76 @@ impl MimicryEngine {
|
||||
pub fn add_mapping(&mut self, country: String, domains: Vec<String>) {
|
||||
self.geo_sni_map.insert(country, domains);
|
||||
}
|
||||
|
||||
/// Update SNI list from control plane (async)
|
||||
pub async fn update_from_control_plane(&mut self, country: String, domains: Vec<String>) {
|
||||
self.geo_sni_map.insert(country, domains);
|
||||
}
|
||||
|
||||
/// Block a domain (emergency update from control plane)
|
||||
pub async fn block_domain(&self, domain: &str) {
|
||||
self.blocked.write().await.insert(domain.to_string());
|
||||
}
|
||||
|
||||
/// Check if domain is blocked
|
||||
pub async fn is_blocked(&self, domain: &str) -> bool {
|
||||
self.blocked.read().await.contains(domain)
|
||||
}
|
||||
|
||||
/// Get safe random SNI (excludes blocked domains)
|
||||
pub async fn safe_random_sni(&self, country_code: &str) -> Option<String> {
|
||||
let blocked = self.blocked.read().await;
|
||||
|
||||
self.geo_sni_map.get(country_code).and_then(|list| {
|
||||
let safe: Vec<&String> = list.iter()
|
||||
.filter(|d| !blocked.contains(*d))
|
||||
.collect();
|
||||
|
||||
if safe.is_empty() {
|
||||
None
|
||||
} else {
|
||||
let idx = rand::random::<usize>() % safe.len();
|
||||
Some(safe[idx].clone())
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
/// Apply bulk SNI update
|
||||
pub async fn apply_update(&mut self, update: SniUpdate) {
|
||||
// Block removed domains
|
||||
{
|
||||
let mut blocked = self.blocked.write().await;
|
||||
for domain in &update.remove {
|
||||
blocked.insert(domain.clone());
|
||||
}
|
||||
}
|
||||
|
||||
// Add new domains
|
||||
if !update.add.is_empty() {
|
||||
let country = update.country.unwrap_or_else(|| "GLOBAL".to_string());
|
||||
let entry = self.geo_sni_map.entry(country).or_insert_with(Vec::new);
|
||||
for domain in update.add {
|
||||
if !entry.contains(&domain) {
|
||||
entry.push(domain);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Get all available SNIs for a country (excluding blocked)
|
||||
pub async fn get_available_snis(&self, country_code: &str) -> Vec<String> {
|
||||
let blocked = self.blocked.read().await;
|
||||
|
||||
self.geo_sni_map
|
||||
.get(country_code)
|
||||
.map(|list| {
|
||||
list.iter()
|
||||
.filter(|d| !blocked.contains(*d))
|
||||
.cloned()
|
||||
.collect()
|
||||
})
|
||||
.unwrap_or_default()
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for MimicryEngine {
|
||||
@@ -79,6 +156,16 @@ impl Default for MimicryEngine {
|
||||
}
|
||||
}
|
||||
|
||||
/// SNI update command from control plane
|
||||
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
|
||||
pub struct SniUpdate {
|
||||
pub remove: Vec<String>,
|
||||
pub add: Vec<String>,
|
||||
pub country: Option<String>,
|
||||
#[serde(default)]
|
||||
pub emergency: bool,
|
||||
}
|
||||
|
||||
/// TLS ClientHello builder for REALITY-like mimicry
|
||||
pub struct TlsHelloBuilder {
|
||||
sni: String,
|
||||
|
||||
Reference in New Issue
Block a user