diff --git a/common/src/define/program_array.rs b/common/src/define/program_array.rs index e650988..a6a3922 100644 --- a/common/src/define/program_array.rs +++ b/common/src/define/program_array.rs @@ -1,8 +1,7 @@ pub mod ingress { pub const ACCESS_CONTROL: u32 = 0; - pub const SERVICE: u32 = 1; - pub const STATISTICS: u32 = 2; - pub const TRANSMISSION: u32 = 3; + pub const STATISTICS: u32 = 1; + pub const TRANSMISSION: u32 = 2; } pub mod egress { diff --git a/ingress-ebpf/src/action/mod.rs b/ingress-ebpf/src/action/mod.rs index 501fc26..314c443 100644 --- a/ingress-ebpf/src/action/mod.rs +++ b/ingress-ebpf/src/action/mod.rs @@ -1,3 +1,2 @@ pub mod access_control; -pub mod service; pub mod statistics; diff --git a/ingress-ebpf/src/action/service.rs b/ingress-ebpf/src/action/service.rs deleted file mode 100644 index 28ae4fc..0000000 --- a/ingress-ebpf/src/action/service.rs +++ /dev/null @@ -1,163 +0,0 @@ -use aya_ebpf::macros::map; -use aya_ebpf::maps::{Array, HashMap}; -use common::define::offset::*; -use common::define::setting::MAX_RULES; -use common::model::event::{IPv4Event, IPv6Event}; -use common::model::http_method::HttpMethodBitmap; -use common::model::ip_address::*; -use common::model::placeholder::PlaceHolder; -use network_types::ip::IpProto; -use network_types::tcp::TcpHdr; - -#[map] -static IPV4_HTTP_SERVICE: HashMap = HashMap::with_max_entries(MAX_RULES as u32, 0); -#[map] -static IPV6_HTTP_SERVICE: HashMap = HashMap::with_max_entries(MAX_RULES as u32, 0); -#[map] -static SSH_WHITE_LIST_ENABLE: Array = Array::with_max_entries(1, 0); -#[map] -static IPV4_SSH_SERVICE: HashMap = HashMap::with_max_entries(MAX_RULES as u32, 0); -#[map] -static IPV6_SSH_SERVICE: HashMap = HashMap::with_max_entries(MAX_RULES as u32, 0); -#[map] -static IPV4_SSH_WHITE_LIST: HashMap = HashMap::with_max_entries(MAX_RULES as u32, 0); -#[map] -static IPV6_SSH_WHITE_LIST: HashMap = HashMap::with_max_entries(MAX_RULES as u32, 0); -#[map] -static IPV4_SSH_BLACK_LIST: HashMap = HashMap::with_max_entries(MAX_RULES as u32, 0); -#[map] -static IPV6_SSH_BLACK_LIST: HashMap = HashMap::with_max_entries(MAX_RULES as u32, 0); - -pub fn ipv4_service_rule_violation(start: usize, end: usize, event: &IPv4Event) -> bool { - let protocol = event.protocol; - let source = event.source_addr(); - let destination = event.destination_addr(); - ipv4_http_service_violation(start, end, &protocol, &destination) - || ipv4_ssh_service_violation(&source, &destination) -} - -pub fn ipv6_service_rule_violation(start: usize, end: usize, event: &IPv6Event) -> bool { - let protocol = event.protocol; - let source = event.source_addr(); - let destination = event.destination_addr(); - ipv6_http_service_violation(start, end, &protocol, &destination) - || ipv6_ssh_service_violation(&source, &destination) -} - -#[inline(always)] -fn ipv4_http_service_violation(start: usize, end: usize, protocol: &IpProto, destination: &AddrPortV4) -> bool { - match IPV4_HTTP_SERVICE.get_ptr_mut(destination) { - Some(allow_method) => { - if !matches!(protocol, IpProto::Tcp) { - return false; - } - unsafe { - if start + IPV4_TCP_HEADER_END > end { - return false; - } - let tcp_header = &*((start + IPV4_TCP_HEADER_START) as *const TcpHdr); - if tcp_header.syn() != 0 || tcp_header.rst() != 0 || tcp_header.fin() != 0 { - return false; - } - if tcp_header.psh() == 0 || tcp_header.ack() == 0 { - return false; - } - let doff = tcp_header.doff(); - if doff < 5 || doff > 15 { - return false; - } - let tcp_header_len = (doff * 4) as usize; - let tcp_payload_start = IPV4_TCP_HEADER_END + tcp_header_len; - match get_http_request_method(start, end, tcp_payload_start) { - Some(http_method) => *allow_method & http_method == 0, - None => true, - } - } - } - None => false, - } -} - -#[inline(always)] -fn ipv6_http_service_violation(start: usize, end: usize, protocol: &IpProto, destination: &AddrPortV6) -> bool { - match IPV6_HTTP_SERVICE.get_ptr_mut(destination) { - Some(allow_method) => { - if !matches!(protocol, IpProto::Tcp) { - return false; - } - unsafe { - if start + IPV6_TCP_HEADER_END > end { - return false; - } - let tcp_header = &*((start + IPV6_TCP_HEADER_START) as *const TcpHdr); - if tcp_header.syn() != 0 || tcp_header.rst() != 0 || tcp_header.fin() != 0 { - return false; - } - if tcp_header.psh() == 0 || tcp_header.ack() == 0 { - return false; - } - let doff = tcp_header.doff(); - if doff < 5 || doff > 15 { - return false; - } - let tcp_header_len = (doff * 4) as usize; - let tcp_payload_start = IPV6_TCP_HEADER_END + tcp_header_len; - match get_http_request_method(start, end, tcp_payload_start) { - Some(http_method) => *allow_method & http_method == 0, - None => true, - } - } - } - None => false, - } -} - -#[inline(always)] -fn get_http_request_method(start: usize, end: usize, offset: usize) -> Option { - if start + offset + 8 > end { - return None; - } - let data = unsafe { core::slice::from_raw_parts((start + offset) as *const u8, 8) }; - match &data[..4] { - b"GET " => Some(1 << 0), - b"POST" if &data[4..5] == b" " => Some(1 << 1), - b"PUT " => Some(1 << 2), - b"DELE" if &data[4..7] == b"TE " => Some(1 << 3), - b"HEAD" if &data[4..5] == b" " => Some(1 << 4), - b"OPTI" if &data[4..8] == b"ONS " => Some(1 << 5), - b"PATC" if &data[4..6] == b"H " => Some(1 << 6), - b"TRAC" if &data[4..6] == b"E " => Some(1 << 7), - b"CONN" if &data[4..8] == b"ECT " => Some(1 << 8), - _ => None, - } -} - -#[inline(always)] -fn ipv4_ssh_service_violation(source: &AddrPortV4, destination: &AddrPortV4) -> bool { - unsafe { - if IPV4_SSH_SERVICE.get(destination).is_some() { - if SSH_WHITE_LIST_ENABLE.get(0).is_some() { - IPV4_SSH_WHITE_LIST.get(&source.ip()).is_none() - } else { - IPV4_SSH_BLACK_LIST.get(&source.ip()).is_some() - } - } else { - false - } - } -} - -#[inline(always)] -fn ipv6_ssh_service_violation(source_ip: &AddrPortV6, destination: &AddrPortV6) -> bool { - unsafe { - if IPV6_SSH_SERVICE.get(destination).is_some() { - if SSH_WHITE_LIST_ENABLE.get(0).is_some() { - IPV6_SSH_WHITE_LIST.get(&source_ip.ip()).is_none() - } else { - IPV6_SSH_BLACK_LIST.get(&source_ip.ip()).is_some() - } - } else { - false - } - } -} diff --git a/ingress-ebpf/src/main.rs b/ingress-ebpf/src/main.rs index 4855b75..1969d90 100644 --- a/ingress-ebpf/src/main.rs +++ b/ingress-ebpf/src/main.rs @@ -12,7 +12,7 @@ use common::define::program_array::ingress::*; use common::ebpf::parsing; use common::model::event::Event; -use crate::action::{access_control, service, statistics}; +use crate::action::{access_control, statistics}; #[map] static PROGRAM_ARRAY: ProgramArray = ProgramArray::with_max_entries(8, 0); @@ -80,43 +80,6 @@ unsafe fn try_access_control(ctx: &XdpContext) -> Result { } } } - let _ = PROGRAM_ARRAY.tail_call(ctx, SERVICE); - Err(()) - } -} - -#[xdp] -pub fn service(ctx: XdpContext) -> u32 { - unsafe { - match try_service(&ctx) { - Ok(action) => action, - Err(_) => { - let _ = PROGRAM_ARRAY.tail_call(&ctx, TRANSMISSION); - xdp_action::XDP_PASS - } - } - } -} - -#[inline(always)] -unsafe fn try_service(ctx: &XdpContext) -> Result { - unsafe { - let start = ctx.data(); - let end = ctx.data_end(); - let ptr = PARSED_PACKET.get_ptr(0).ok_or(())?; - let parsed_packet = &*ptr; - match parsed_packet { - Event::IPv4(event) => { - if service::ipv4_service_rule_violation(start, end, event) { - return Ok(xdp_action::XDP_DROP); - } - } - Event::IPv6(event) => { - if service::ipv6_service_rule_violation(start, end, event) { - return Ok(xdp_action::XDP_DROP); - } - } - } let _ = PROGRAM_ARRAY.tail_call(ctx, STATISTICS); Err(()) } diff --git a/mantis/src/core/app_state.rs b/mantis/src/core/app_state.rs index d29be2a..4be2a92 100644 --- a/mantis/src/core/app_state.rs +++ b/mantis/src/core/app_state.rs @@ -1,7 +1,6 @@ use std::sync::Arc; use crate::core::ebpf::access_control::AccessControl; -use crate::core::ebpf::service::Service; use crate::core::ebpf::statistics::Statistics; use crate::core::infrastructure::app_config::AppConfig; use crate::core::infrastructure::app_db::AppDB; @@ -14,7 +13,6 @@ pub struct AppState { pub app_config: Arc, pub inference_config: Arc, pub access_control: Arc, - pub service: Arc, pub statistics: Arc, pub health: Arc, pub detection_alert: Arc, diff --git a/mantis/src/core/ebpf/mod.rs b/mantis/src/core/ebpf/mod.rs index f45d630..9921b27 100644 --- a/mantis/src/core/ebpf/mod.rs +++ b/mantis/src/core/ebpf/mod.rs @@ -1,5 +1,4 @@ pub mod access_control; -pub mod service; pub mod statistics; pub mod xsk_manager; @@ -11,7 +10,6 @@ use macros::log; use tokio::sync::oneshot; use crate::core::ebpf::access_control::AccessControl; -use crate::core::ebpf::service::Service; use crate::core::ebpf::statistics::Statistics; use crate::core::ebpf::xsk_manager::XskManager; use crate::core::infrastructure::app_config::AppConfig; @@ -23,7 +21,6 @@ use crate::model::error::system::SystemError; pub struct EbpfServices { pub xsk_manager: Arc, pub access_control: Arc, - pub service: Arc, pub statistics: Arc, pub shutdowns: SegQueue>, } @@ -32,12 +29,10 @@ impl EbpfServices { pub fn new(app_config: Arc, ingress_ebpf: &mut Ebpf, egress_ebpf: &mut Ebpf) -> Result { let xsk_manager = XskManager::new(app_config.clone(), ingress_ebpf, egress_ebpf)?; let access_control = AccessControl::new(ingress_ebpf, egress_ebpf)?; - let service = Service::new(ingress_ebpf)?; let statistics = Statistics::new(app_config.clone(), ingress_ebpf, egress_ebpf)?; let ebpf_services = Self { xsk_manager: Arc::new(xsk_manager), access_control: Arc::new(access_control), - service: Arc::new(service), statistics: Arc::new(statistics), shutdowns: SegQueue::new(), }; diff --git a/mantis/src/core/ebpf/service.rs b/mantis/src/core/ebpf/service.rs deleted file mode 100644 index 0fe8568..0000000 --- a/mantis/src/core/ebpf/service.rs +++ /dev/null @@ -1,332 +0,0 @@ -use std::collections::HashMap; -use std::net::{Ipv4Addr, Ipv6Addr, SocketAddrV4, SocketAddrV6}; - -use aya::maps::{Array as AyaArray, HashMap as AyaHashMap, MapData}; -use aya::{Ebpf, Pod}; -use common::model::http_method::{HttpMethod, HttpMethodBitmap}; -use common::model::ip_address::{AddrPortV4, AddrPortV6, IPv4, IPv6}; -use common::model::placeholder::PlaceHolder; -use tokio::sync::RwLock; - -use crate::model::error::Error; -use crate::model::error::ebpf::EbpfError; -use crate::model::ip_address::NativeConvert; - -pub struct Service { - ipv4_http_service: RwLock>, - ipv6_http_service: RwLock>, - ssh_white_list_enable: RwLock, - ipv4_ssh_service: RwLock>, - ipv6_ssh_service: RwLock>, - ipv4_ssh_white_list: RwLock>, - ipv6_ssh_white_list: RwLock>, - ipv4_ssh_black_list: RwLock>, - ipv6_ssh_black_list: RwLock>, -} - -impl Service { - pub fn new(ebpf: &mut Ebpf) -> Result { - let service = Self { - ipv4_http_service: RwLock::new(HttpServiceWrapper::new(ebpf, "IPV4_HTTP_SERVICE")?), - ipv6_http_service: RwLock::new(HttpServiceWrapper::new(ebpf, "IPV6_HTTP_SERVICE")?), - ssh_white_list_enable: RwLock::new(WhiteListControl::new(ebpf, "SSH_WHITE_LIST_ENABLE")?), - ipv4_ssh_service: RwLock::new(SshServiceWrapper::new(ebpf, "IPV4_SSH_SERVICE")?), - ipv6_ssh_service: RwLock::new(SshServiceWrapper::new(ebpf, "IPV6_SSH_SERVICE")?), - ipv4_ssh_white_list: RwLock::new(SshListWrapper::new(ebpf, "IPV4_SSH_WHITE_LIST")?), - ipv6_ssh_white_list: RwLock::new(SshListWrapper::new(ebpf, "IPV6_SSH_WHITE_LIST")?), - ipv4_ssh_black_list: RwLock::new(SshListWrapper::new(ebpf, "IPV4_SSH_BLACK_LIST")?), - ipv6_ssh_black_list: RwLock::new(SshListWrapper::new(ebpf, "IPV6_SSH_BLACK_LIST")?), - }; - Ok(service) - } - - pub async fn get_ipv4_http_service(&self) -> HashMap> { - self.ipv4_http_service.read().await.get_http_method() - } - - pub async fn get_ipv6_http_service(&self) -> HashMap> { - self.ipv6_http_service.read().await.get_http_method() - } - - pub async fn add_ipv4_http_service( - &self, - address: SocketAddrV4, - http_method: Vec, - ) -> Result<(), Error> { - self.ipv4_http_service - .write() - .await - .add_http_service(address, http_method) - } - - pub async fn add_ipv6_http_service( - &self, - address: SocketAddrV6, - http_method: Vec, - ) -> Result<(), Error> { - self.ipv6_http_service - .write() - .await - .add_http_service(address, http_method) - } - - pub async fn remove_ipv4_http_service( - &self, - address: SocketAddrV4, - removed_http_method: Vec, - ) -> Result<(), Error> { - self.ipv4_http_service - .write() - .await - .remove_http_service(address, removed_http_method) - } - - pub async fn remove_ipv6_http_service( - &self, - address: SocketAddrV6, - removed_http_method: Vec, - ) -> Result<(), Error> { - self.ipv6_http_service - .write() - .await - .remove_http_service(address, removed_http_method) - } - - pub async fn is_ssh_white_list_enable(&self) -> bool { - self.ssh_white_list_enable.read().await.is_white_list_enable() - } - - pub async fn enable_ssh_white_list(&self) -> Result<(), Error> { - self.ssh_white_list_enable.write().await.enable_white_list() - } - - pub async fn disable_ssh_white_list(&self) -> Result<(), Error> { - self.ssh_white_list_enable.write().await.disable_white_list() - } - - pub async fn get_ipv4_ssh_service(&self) -> Vec { - self.ipv4_ssh_service.read().await.get_ssh_service() - } - - pub async fn get_ipv6_ssh_service(&self) -> Vec { - self.ipv6_ssh_service.read().await.get_ssh_service() - } - - pub async fn add_ipv4_ssh_service(&self, address: SocketAddrV4) -> Result<(), Error> { - self.ipv4_ssh_service.write().await.add_ssh_service(address) - } - - pub async fn add_ipv6_ssh_service(&self, address: SocketAddrV6) -> Result<(), Error> { - self.ipv6_ssh_service.write().await.add_ssh_service(address) - } - - pub async fn remove_ipv4_ssh_service(&self, address: SocketAddrV4) -> Result<(), Error> { - self.ipv4_ssh_service.write().await.remove_ssh_service(address) - } - - pub async fn remove_ipv6_ssh_service(&self, address: SocketAddrV6) -> Result<(), Error> { - self.ipv6_ssh_service.write().await.remove_ssh_service(address) - } - - pub async fn get_ipv4_ssh_white_list(&self) -> Vec { - self.ipv4_ssh_white_list.read().await.get_list() - } - - pub async fn get_ipv6_ssh_white_list(&self) -> Vec { - self.ipv6_ssh_white_list.read().await.get_list() - } - - pub async fn add_ipv4_ssh_white_list(&self, ip: Ipv4Addr) -> Result<(), Error> { - self.ipv4_ssh_white_list.write().await.add_list(ip) - } - - pub async fn add_ipv6_ssh_white_list(&self, ip: Ipv6Addr) -> Result<(), Error> { - self.ipv6_ssh_white_list.write().await.add_list(ip) - } - - pub async fn remove_ipv4_ssh_white_list(&self, ip: Ipv4Addr) -> Result<(), Error> { - self.ipv4_ssh_white_list.write().await.remove_list(ip) - } - - pub async fn remove_ipv6_ssh_white_list(&self, ip: Ipv6Addr) -> Result<(), Error> { - self.ipv6_ssh_white_list.write().await.remove_list(ip) - } - - pub async fn get_ipv4_ssh_black_list(&self) -> Vec { - self.ipv4_ssh_black_list.read().await.get_list() - } - - pub async fn get_ipv6_ssh_black_list(&self) -> Vec { - self.ipv6_ssh_black_list.read().await.get_list() - } - - pub async fn add_ipv4_ssh_black_list(&self, ip: Ipv4Addr) -> Result<(), Error> { - self.ipv4_ssh_black_list.write().await.add_list(ip) - } - - pub async fn add_ipv6_ssh_black_list(&self, ip: Ipv6Addr) -> Result<(), Error> { - self.ipv6_ssh_black_list.write().await.add_list(ip) - } - - pub async fn remove_ipv4_ssh_black_list(&self, ip: Ipv4Addr) -> Result<(), Error> { - self.ipv4_ssh_black_list.write().await.remove_list(ip) - } - - pub async fn remove_ipv6_ssh_black_list(&self, ip: Ipv6Addr) -> Result<(), Error> { - self.ipv6_ssh_black_list.write().await.remove_list(ip) - } -} - -struct WhiteListControl { - map: AyaArray, -} - -impl WhiteListControl { - fn new(ebpf: &mut Ebpf, map_name: &str) -> Result { - let map = ebpf.take_map(map_name).ok_or(EbpfError::MapNotFound)?; - let map = AyaArray::try_from(map).map_err(EbpfError::MapOperationError)?; - Ok(Self { map }) - } - - fn is_white_list_enable(&self) -> bool { - match self.map.get(&0, 0) { - Ok(status) => { - if status == 0 { - false - } else { - true - } - } - Err(_) => false, - } - } - - fn enable_white_list(&mut self) -> Result<(), Error> { - self.map.set(0, 1_u8, 0).map_err(EbpfError::MapOperationError)?; - Ok(()) - } - - fn disable_white_list(&mut self) -> Result<(), Error> { - self.map.set(0, 0_u8, 0).map_err(EbpfError::MapOperationError)?; - Ok(()) - } -} - -struct HttpServiceWrapper { - map: AyaHashMap, -} - -impl HttpServiceWrapper { - fn new(ebpf: &mut Ebpf, map_name: &str) -> Result { - let map = ebpf.take_map(map_name).ok_or(EbpfError::MapNotFound)?; - let map = AyaHashMap::try_from(map).map_err(EbpfError::MapOperationError)?; - Ok(Self { map }) - } - - fn get_http_method(&self) -> HashMap> { - self.map - .iter() - .filter_map(Result::ok) - .map(|(key, value)| { - let address = key.into_native(); - (address, HttpMethod::convert_from_bitmap(value)) - }) - .collect() - } - - fn add_http_service(&mut self, address: T::Native, http_method: Vec) -> Result<(), Error> { - let address = T::from_native(address); - let ebpf_method = HttpMethod::convert_to_bitmap(http_method); - self.map - .insert(address, ebpf_method, 0) - .map_err(|_| EbpfError::RuleReachLimit)?; - Ok(()) - } - - fn remove_http_service(&mut self, address: T::Native, removed_http_method: Vec) -> Result<(), Error> { - let address = T::from_native(address); - if let Ok(current_http_method) = self.map.get(&address, 0) { - let mut http_method = HttpMethod::convert_from_bitmap(current_http_method); - http_method.retain(|method| !removed_http_method.contains(method)); - if http_method.is_empty() { - self.map.remove(&address).map_err(EbpfError::MapOperationError)?; - } else { - let new_http_method = HttpMethod::convert_to_bitmap(http_method); - self.map - .insert(&address, new_http_method, 0) - .map_err(EbpfError::MapOperationError)?; - } - Ok(()) - } else { - Err(EbpfError::IpDoesNotExist)? - } - } -} - -struct SshServiceWrapper { - map: AyaHashMap, -} - -impl SshServiceWrapper { - fn new(ebpf: &mut Ebpf, map_name: &str) -> Result { - let map = ebpf.take_map(map_name).ok_or(EbpfError::MapNotFound)?; - let map = AyaHashMap::try_from(map).map_err(EbpfError::MapOperationError)?; - Ok(Self { map }) - } - - fn get_ssh_service(&self) -> Vec { - self.map - .keys() - .filter_map(Result::ok) - .map(|key| key.into_native()) - .collect() - } - - fn add_ssh_service(&mut self, address: T::Native) -> Result<(), Error> { - let address = T::from_native(address); - self.map - .insert(address, 0_u8, 0) - .map_err(|_| EbpfError::RuleReachLimit)?; - Ok(()) - } - - fn remove_ssh_service(&mut self, address: T::Native) -> Result<(), Error> { - let address = T::from_native(address); - self.map.remove(&address).map_err(|_| EbpfError::IpDoesNotExist)?; - Ok(()) - } -} - -struct SshListWrapper { - map: AyaHashMap, -} - -impl SshListWrapper { - fn new(ebpf: &mut Ebpf, map_name: &str) -> Result { - let map = ebpf.take_map(map_name).ok_or(EbpfError::MapNotFound)?; - let map = AyaHashMap::try_from(map).map_err(EbpfError::MapOperationError)?; - Ok(Self { map }) - } - - fn get_list(&self) -> Vec { - self.map - .keys() - .filter_map(Result::ok) - .map(|key| key.into_native()) - .collect() - } - - fn add_list(&mut self, address: T::Native) -> Result<(), Error> { - let address = T::from_native(address); - self.map - .insert(address, 0_u8, 0) - .map_err(|_| EbpfError::RuleReachLimit)?; - Ok(()) - } - - fn remove_list(&mut self, address: T::Native) -> Result<(), Error> { - let address = T::from_native(address); - self.map.remove(&address).map_err(|_| EbpfError::IpDoesNotExist)?; - Ok(()) - } -} diff --git a/mantis/src/core/system.rs b/mantis/src/core/system.rs index 4169271..69d0798 100644 --- a/mantis/src/core/system.rs +++ b/mantis/src/core/system.rs @@ -149,7 +149,6 @@ impl System { app_config: self.app_config.clone(), inference_config: self.inference_config.clone(), access_control: self.ebpf_services.access_control.clone(), - service: self.ebpf_services.service.clone(), statistics: self.ebpf_services.statistics.clone(), health: self.app_services.health.clone(), detection_alert: self.app_services.detection_alert.clone(), @@ -194,7 +193,6 @@ impl System { "access_control", ingress::ACCESS_CONTROL, )?; - Self::load_program(&mut ingress_ebpf, &mut program_array, "service", ingress::SERVICE)?; Self::load_program(&mut ingress_ebpf, &mut program_array, "statistics", ingress::STATISTICS)?; Self::load_program( &mut ingress_ebpf, diff --git a/mantis/src/detection/suricata/engine.rs b/mantis/src/detection/suricata/engine.rs index 979f158..2490fb8 100644 --- a/mantis/src/detection/suricata/engine.rs +++ b/mantis/src/detection/suricata/engine.rs @@ -33,6 +33,7 @@ impl SuricataEngine { eve_socket: &Path, fusion: Arc, ) -> Result, SuricataError> { + Self::kill_existing(); Self::setup_veth()?; let ifindex = Self::get_ifindex(MIRROR_IFACE)?; @@ -305,6 +306,7 @@ app-layer: af-packet: - interface: {iface} threads: {threads} + cluster-id: 99 use-mmap: yes tpacket-v3: yes ring-size: {ring_size} @@ -351,6 +353,11 @@ host-mode: sniffer-only Ok(fd) } + fn kill_existing() { + let _ = Command::new("pkill").args(["-x", "suricata"]).output(); + thread::sleep(Duration::from_millis(500)); + } + fn setup_veth() -> Result<(), SuricataError> { let _ = Command::new("ip").args(["link", "del", MIRROR_IFACE]).output(); diff --git a/mantis/src/web/api/control/mod.rs b/mantis/src/web/api/control/mod.rs index 914eee3..fdbe744 100644 --- a/mantis/src/web/api/control/mod.rs +++ b/mantis/src/web/api/control/mod.rs @@ -1,5 +1,4 @@ pub mod access_control; -pub mod service; pub mod statistics; use axum::Router; @@ -9,6 +8,5 @@ use crate::core::app_state::AppState; pub fn router() -> Router { Router::new() .nest("/access_control", access_control::router()) - .nest("/service", service::router()) .nest("/statistics", statistics::router()) } diff --git a/mantis/src/web/api/control/service.rs b/mantis/src/web/api/control/service.rs deleted file mode 100644 index fb5a73d..0000000 --- a/mantis/src/web/api/control/service.rs +++ /dev/null @@ -1,243 +0,0 @@ -use std::net::{Ipv4Addr, Ipv6Addr, SocketAddrV4, SocketAddrV6}; - -use axum::extract::{Path, State}; -use axum::http::StatusCode; -use axum::response::IntoResponse; -use axum::routing::{delete, get, post, put}; -use axum::{Json, Router}; -use common::model::http_method::HttpMethod; - -use crate::core::app_state::AppState; - -pub fn router() -> Router { - Router::new() - .route( - "/ipv4/http_service", - get(get_ipv4_http_service) - .put(add_ipv4_http_service) - .delete(remove_ipv4_http_service), - ) - .route( - "/ipv6/http_service", - get(get_ipv6_http_service) - .put(add_ipv6_http_service) - .delete(remove_ipv6_http_service), - ) - .route("/ssh_white_list", get(is_ssh_white_list_enable)) - .route("/ssh_white_list/enable", post(enable_ssh_white_list)) - .route("/ssh_white_list/disable", post(disable_ssh_white_list)) - .route( - "/ipv4/ssh_service", - get(get_ipv4_ssh_service) - .put(add_ipv4_ssh_service) - .delete(remove_ipv4_ssh_service), - ) - .route( - "/ipv6/ssh_service", - get(get_ipv6_ssh_service) - .put(add_ipv6_ssh_service) - .delete(remove_ipv6_ssh_service), - ) - .route( - "/ipv4/ssh_white_list", - get(get_ipv4_ssh_white_list) - .put(add_ipv4_ssh_white_list) - .delete(remove_ipv4_ssh_white_list), - ) - .route( - "/ipv6/ssh_white_list", - get(get_ipv6_ssh_white_list) - .put(add_ipv6_ssh_white_list) - .delete(remove_ipv6_ssh_white_list), - ) - .route( - "/ipv4/ssh_black_list", - get(get_ipv4_ssh_black_list) - .put(add_ipv4_ssh_black_list) - .delete(remove_ipv4_ssh_black_list), - ) - .route( - "/ipv6/ssh_black_list", - get(get_ipv6_ssh_black_list) - .put(add_ipv6_ssh_black_list) - .delete(remove_ipv6_ssh_black_list), - ) -} - -async fn get_ipv4_http_service(State(state): State) -> impl IntoResponse { - Json(state.service.get_ipv4_http_service().await) -} - -async fn get_ipv6_http_service(State(state): State) -> impl IntoResponse { - Json(state.service.get_ipv6_http_service().await) -} - -async fn add_ipv4_http_service( - State(state): State, - Json(payload): Json<(SocketAddrV4, Vec)>, -) -> impl IntoResponse { - let (addr, methods) = payload; - match state.service.add_ipv4_http_service(addr, methods).await { - Ok(_) => StatusCode::OK.into_response(), - Err(e) => (StatusCode::INTERNAL_SERVER_ERROR, e.to_string()).into_response(), - } -} - -async fn add_ipv6_http_service( - State(state): State, - Json(payload): Json<(SocketAddrV6, Vec)>, -) -> impl IntoResponse { - let (addr, methods) = payload; - match state.service.add_ipv6_http_service(addr, methods).await { - Ok(_) => StatusCode::OK.into_response(), - Err(e) => (StatusCode::INTERNAL_SERVER_ERROR, e.to_string()).into_response(), - } -} - -async fn remove_ipv4_http_service( - State(state): State, - Json(payload): Json<(SocketAddrV4, Vec)>, -) -> impl IntoResponse { - let (addr, methods) = payload; - match state.service.remove_ipv4_http_service(addr, methods).await { - Ok(_) => StatusCode::OK.into_response(), - Err(e) => (StatusCode::INTERNAL_SERVER_ERROR, e.to_string()).into_response(), - } -} - -async fn remove_ipv6_http_service( - State(state): State, - Json(payload): Json<(SocketAddrV6, Vec)>, -) -> impl IntoResponse { - let (addr, methods) = payload; - match state.service.remove_ipv6_http_service(addr, methods).await { - Ok(_) => StatusCode::OK.into_response(), - Err(e) => (StatusCode::INTERNAL_SERVER_ERROR, e.to_string()).into_response(), - } -} - -async fn is_ssh_white_list_enable(State(state): State) -> impl IntoResponse { - Json(state.service.is_ssh_white_list_enable().await) -} - -async fn enable_ssh_white_list(State(state): State) -> impl IntoResponse { - match state.service.enable_ssh_white_list().await { - Ok(_) => StatusCode::OK.into_response(), - Err(e) => (StatusCode::INTERNAL_SERVER_ERROR, e.to_string()).into_response(), - } -} - -async fn disable_ssh_white_list(State(state): State) -> impl IntoResponse { - match state.service.disable_ssh_white_list().await { - Ok(_) => StatusCode::OK.into_response(), - Err(e) => (StatusCode::INTERNAL_SERVER_ERROR, e.to_string()).into_response(), - } -} - -async fn get_ipv4_ssh_service(State(state): State) -> impl IntoResponse { - Json(state.service.get_ipv4_ssh_service().await) -} - -async fn get_ipv6_ssh_service(State(state): State) -> impl IntoResponse { - Json(state.service.get_ipv6_ssh_service().await) -} - -async fn add_ipv4_ssh_service(State(state): State, Json(addr): Json) -> impl IntoResponse { - match state.service.add_ipv4_ssh_service(addr).await { - Ok(_) => StatusCode::OK.into_response(), - Err(e) => (StatusCode::INTERNAL_SERVER_ERROR, e.to_string()).into_response(), - } -} - -async fn add_ipv6_ssh_service(State(state): State, Json(addr): Json) -> impl IntoResponse { - match state.service.add_ipv6_ssh_service(addr).await { - Ok(_) => StatusCode::OK.into_response(), - Err(e) => (StatusCode::INTERNAL_SERVER_ERROR, e.to_string()).into_response(), - } -} - -async fn remove_ipv4_ssh_service(State(state): State, Json(addr): Json) -> impl IntoResponse { - match state.service.remove_ipv4_ssh_service(addr).await { - Ok(_) => StatusCode::OK.into_response(), - Err(e) => (StatusCode::INTERNAL_SERVER_ERROR, e.to_string()).into_response(), - } -} - -async fn remove_ipv6_ssh_service(State(state): State, Json(addr): Json) -> impl IntoResponse { - match state.service.remove_ipv6_ssh_service(addr).await { - Ok(_) => StatusCode::OK.into_response(), - Err(e) => (StatusCode::INTERNAL_SERVER_ERROR, e.to_string()).into_response(), - } -} - -async fn get_ipv4_ssh_white_list(State(state): State) -> impl IntoResponse { - Json(state.service.get_ipv4_ssh_white_list().await) -} - -async fn get_ipv6_ssh_white_list(State(state): State) -> impl IntoResponse { - Json(state.service.get_ipv6_ssh_white_list().await) -} - -async fn add_ipv4_ssh_white_list(State(state): State, Json(addr): Json) -> impl IntoResponse { - match state.service.add_ipv4_ssh_white_list(addr).await { - Ok(_) => StatusCode::OK.into_response(), - Err(e) => (StatusCode::INTERNAL_SERVER_ERROR, e.to_string()).into_response(), - } -} - -async fn add_ipv6_ssh_white_list(State(state): State, Json(addr): Json) -> impl IntoResponse { - match state.service.add_ipv6_ssh_white_list(addr).await { - Ok(_) => StatusCode::OK.into_response(), - Err(e) => (StatusCode::INTERNAL_SERVER_ERROR, e.to_string()).into_response(), - } -} - -async fn remove_ipv4_ssh_white_list(State(state): State, Json(addr): Json) -> impl IntoResponse { - match state.service.remove_ipv4_ssh_white_list(addr).await { - Ok(_) => StatusCode::OK.into_response(), - Err(e) => (StatusCode::INTERNAL_SERVER_ERROR, e.to_string()).into_response(), - } -} - -async fn remove_ipv6_ssh_white_list(State(state): State, Json(addr): Json) -> impl IntoResponse { - match state.service.remove_ipv6_ssh_white_list(addr).await { - Ok(_) => StatusCode::OK.into_response(), - Err(e) => (StatusCode::INTERNAL_SERVER_ERROR, e.to_string()).into_response(), - } -} - -async fn get_ipv4_ssh_black_list(State(state): State) -> impl IntoResponse { - Json(state.service.get_ipv4_ssh_black_list().await) -} - -async fn get_ipv6_ssh_black_list(State(state): State) -> impl IntoResponse { - Json(state.service.get_ipv6_ssh_black_list().await) -} - -async fn add_ipv4_ssh_black_list(State(state): State, Json(addr): Json) -> impl IntoResponse { - match state.service.add_ipv4_ssh_black_list(addr).await { - Ok(_) => StatusCode::OK.into_response(), - Err(e) => (StatusCode::INTERNAL_SERVER_ERROR, e.to_string()).into_response(), - } -} - -async fn add_ipv6_ssh_black_list(State(state): State, Json(addr): Json) -> impl IntoResponse { - match state.service.add_ipv6_ssh_black_list(addr).await { - Ok(_) => StatusCode::OK.into_response(), - Err(e) => (StatusCode::INTERNAL_SERVER_ERROR, e.to_string()).into_response(), - } -} - -async fn remove_ipv4_ssh_black_list(State(state): State, Json(addr): Json) -> impl IntoResponse { - match state.service.remove_ipv4_ssh_black_list(addr).await { - Ok(_) => StatusCode::OK.into_response(), - Err(e) => (StatusCode::INTERNAL_SERVER_ERROR, e.to_string()).into_response(), - } -} - -async fn remove_ipv6_ssh_black_list(State(state): State, Json(addr): Json) -> impl IntoResponse { - match state.service.remove_ipv6_ssh_black_list(addr).await { - Ok(_) => StatusCode::OK.into_response(), - Err(e) => (StatusCode::INTERNAL_SERVER_ERROR, e.to_string()).into_response(), - } -}