Prepare Control APIs

This commit is contained in:
DaLaw2 2024-12-03 01:03:23 +08:00
parent 4618c89db6
commit 1cf790dd22
11 changed files with 256 additions and 96 deletions

View File

@ -1,14 +1,17 @@
use std::net::{IpAddr, Ipv4Addr, Ipv6Addr, SocketAddrV4, SocketAddrV6};
use std::sync::OnceLock;
use crate::core::system::System;
use crate::model::http_method::HttpMethod;
use crate::utils::ip_address::convert_ports_to_vec;
use crate::utils::log_entry::system::SystemEntry;
use aya::maps::{Array as AyaArray, HashMap as AyaHashMap, MapData};
use tokio::sync::{RwLock, RwLockReadGuard, RwLockWriteGuard};
use tracing::{error, info};
use net_guardia_common::MAX_RULES_PORT;
use net_guardia_common::model::http_method::EbpfHttpMethod;
use net_guardia_common::model::ip_address::{EbpfAddrPortV4, EbpfAddrPortV6, IPv4, IPv6, Port};
use net_guardia_common::model::placeholder::PlaceHolder;
use crate::core::system::System;
use crate::utils::log_entry::system::SystemEntry;
use net_guardia_common::MAX_RULES_PORT;
use std::collections::HashMap as StdHashMap;
use std::net::{IpAddr, Ipv4Addr, Ipv6Addr, SocketAddrV4, SocketAddrV6};
use std::sync::OnceLock;
use tokio::sync::{RwLock, RwLockReadGuard, RwLockWriteGuard};
use tracing::{error, info};
static CONTROL: OnceLock<RwLock<Control>> = OnceLock::new();
@ -25,7 +28,7 @@ pub struct Control {
ipv4_ssh_black_list: AyaHashMap<MapData, IPv4, PlaceHolder>,
ipv6_ssh_black_list: AyaHashMap<MapData, IPv6, PlaceHolder>,
ipv4_scanner_list: AyaHashMap<MapData, IPv4, PlaceHolder>,
ipv6_scanner_list: AyaHashMap<MapData, IPv6, PlaceHolder>
ipv6_scanner_list: AyaHashMap<MapData, IPv6, PlaceHolder>,
}
impl Control {
@ -33,7 +36,7 @@ impl Control {
info!("{}", SystemEntry::Initializing);
let mut system = System::instance_mut().await;
let mut ebpf = &mut system.ebpf;
let control = Control {
let mut control = Control {
ipv4_black_list: AyaHashMap::try_from(ebpf.take_map("IPV4_BLACKLIST").unwrap())?,
ipv6_black_list: AyaHashMap::try_from(ebpf.take_map("IPV6_BLACKLIST").unwrap())?,
ipv4_http_service: AyaHashMap::try_from(ebpf.take_map("IPV4_HTTP_SERVICE").unwrap())?,
@ -41,13 +44,24 @@ impl Control {
ssh_white_list_only: AyaArray::try_from(ebpf.take_map("SSH_WHITE_LIST_ONLY").unwrap())?,
ipv4_ssh_service: AyaHashMap::try_from(ebpf.take_map("IPV4_SSH_SERVICE").unwrap())?,
ipv6_ssh_service: AyaHashMap::try_from(ebpf.take_map("IPV6_SSH_SERVICE").unwrap())?,
ipv4_ssh_white_list: AyaHashMap::try_from(ebpf.take_map("IPV4_SSH_WHITE_LIST").unwrap())?,
ipv6_ssh_white_list: AyaHashMap::try_from(ebpf.take_map("IPV6_SSH_WHITE_LIST").unwrap())?,
ipv4_ssh_black_list: AyaHashMap::try_from(ebpf.take_map("IPV4_SSH_BLACK_LIST").unwrap())?,
ipv6_ssh_black_list: AyaHashMap::try_from(ebpf.take_map("IPV6_SSH_BLACK_LIST").unwrap())?,
ipv4_ssh_white_list: AyaHashMap::try_from(
ebpf.take_map("IPV4_SSH_WHITE_LIST").unwrap(),
)?,
ipv6_ssh_white_list: AyaHashMap::try_from(
ebpf.take_map("IPV6_SSH_WHITE_LIST").unwrap(),
)?,
ipv4_ssh_black_list: AyaHashMap::try_from(
ebpf.take_map("IPV4_SSH_BLACK_LIST").unwrap(),
)?,
ipv6_ssh_black_list: AyaHashMap::try_from(
ebpf.take_map("IPV6_SSH_BLACK_LIST").unwrap(),
)?,
ipv4_scanner_list: AyaHashMap::try_from(ebpf.take_map("IPV4_SCANNER_LIST").unwrap())?,
ipv6_scanner_list: AyaHashMap::try_from(ebpf.take_map("IPV6_SCANNER_LIST").unwrap())?,
};
if control.ssh_white_list_only.set(0, 0_u8, 0).is_err() {
error!(" ");
}
CONTROL.get_or_init(|| RwLock::new(control));
info!("{}", SystemEntry::InitializeComplete);
Ok(())
@ -69,17 +83,122 @@ impl Control {
once_lock.write().await
}
pub async fn add_ipv4_http_service(address: SocketAddrV4, ) {
pub async fn get_ipv4_black_list() -> StdHashMap<Ipv4Addr, Vec<Port>> {
let control = Control::instance().await;
control
.ipv4_black_list
.iter()
.filter_map(Result::ok)
.map(|(key, value)| (Ipv4Addr::from(key), convert_ports_to_vec(value)))
.collect()
}
pub async fn get_ipv6_black_list() -> StdHashMap<Ipv6Addr, Vec<Port>> {
let control = Control::instance().await;
control
.ipv6_black_list
.iter()
.filter_map(Result::ok)
.map(|(key, value)| (Ipv6Addr::from(key), convert_ports_to_vec(value)))
.collect()
}
pub async fn add_ipv4_black_list() {
let mut control = Control::instance_mut().await;
}
pub async fn add_ipv6_black_list() {
let mut control = Control::instance_mut().await;
}
pub async fn remove_ipv4_black_list() {
}
pub async fn enable_ssh_white_list() {
pub async fn remove_ipv6_black_list() {
}
pub async fn get_ipv4_http_service() -> Vec<SocketAddrV4> {
}
pub async fn get_ipv6_http_service() -> Vec<SocketAddrV6> {
}
pub async fn add_ipv4_http_service(address: SocketAddrV4, http_method: Vec<HttpMethod>) {
let ip: u32 = (*address.ip()).into();
let port = address.port();
let addr_port = [ip, port as u32];
let ebpf_method = HttpMethod::convert_to_ebpf(http_method);
let mut control = Control::instance_mut().await;
if control
.ipv4_http_service
.insert(addr_port, ebpf_method, 0)
.is_err()
{
error!(" ");
}
}
pub async fn add_ipv6_http_service(address: SocketAddrV6, http_method: Vec<HttpMethod>) {
let ip: u128 = (*address.ip()).into();
let port = address.port();
let addr_port = [ip, port as u128];
let ebpf_method = HttpMethod::convert_to_ebpf(http_method);
let mut control = Control::instance_mut().await;
if control
.ipv6_http_service
.insert(addr_port, ebpf_method, 0)
.is_err()
{
error!(" ");
}
}
pub async fn remove_ipv4_http_service(address: SocketAddrV4, http_method: Vec<HttpMethod>) {
}
pub async fn remove_ipv6_http_service(address: SocketAddrV6, http_method: Vec<HttpMethod>) {
}
pub async fn is_ssh_white_list_enable() -> bool {
let control = Control::instance().await;
match control.ssh_white_list_only.get(&0, 0) {
Ok(status) => if status == 0 {
false
} else {
true
}
Err(_) => false
}
}
pub async fn enable_ssh_white_list() {
let mut control = Control::instance_mut().await;
if control.ssh_white_list_only.set(0, 1_u8, 0).is_err() {
error!(" ");
}
}
pub async fn disable_ssh_white_list() {
let mut control = Control::instance_mut().await;
if control.ssh_white_list_only.set(0, 0_u8, 0).is_err() {
error!(" ");
}
}
pub async fn get_ipv4_ssh_white_list() {
}
pub async fn get_ipv6_ssh_white_list() {
}
pub async fn add_ipv4_ssh_white_list(ip: Ipv4Addr) {
let ip: u32 = ip.into();
let mut control = Control::instance_mut().await;
@ -96,6 +215,22 @@ impl Control {
}
}
pub async fn remove_ipv4_ssh_white_list() {
}
pub async fn remove_ipv6_ssh_white_list() {
}
pub async fn get_ipv4_ssh_black_list(ip: Ipv4Addr) {
}
pub async fn get_ipv6_ssh_black_list(ip: Ipv4Addr) {
}
pub async fn add_ipv4_ssh_black_list(ip: Ipv4Addr) {
let ip: u32 = ip.into();
let mut control = Control::instance_mut().await;
@ -111,4 +246,28 @@ impl Control {
error!(" ");
}
}
pub async fn remove_ipv6_ssh_black_list() {
}
pub async fn remove_ipv4_ssh_black_list() {
}
pub async fn get_ipv4_scanner_list() {
}
pub async fn get_ipv6_scanner_list() {
}
pub async fn remove_ipv4_scanner_list() {
}
pub async fn remove_ipv6_scanner_list() {
}
}

View File

@ -1,4 +1,5 @@
use crate::core::system::System;
use crate::model::flow_stats::FlowStats;
use crate::model::flow_type::{IPv4FlowType, IPv6FlowType};
use crate::utils::log_entry::system::SystemEntry;
use aya::maps::{HashMap as AyaHashMap, MapData};
@ -6,6 +7,7 @@ use aya::Pod;
use net_guardia_common::model::flow_stats::EbpfFlowStats;
use net_guardia_common::model::ip_address::{EbpfAddrPortV4, EbpfAddrPortV6};
use std::collections::HashMap as StdHashMap;
use std::net::{Ipv4Addr, Ipv6Addr, SocketAddrV4, SocketAddrV6};
use std::sync::OnceLock;
use tokio::sync::{RwLock, RwLockReadGuard, RwLockWriteGuard};
use tracing::info;
@ -133,7 +135,7 @@ impl Monitor {
pub async fn get_ipv4_flow_data(
ipv4_flow_type: IPv4FlowType,
) -> StdHashMap<EbpfAddrPortV4, EbpfFlowStats> {
) -> StdHashMap<SocketAddrV4, FlowStats> {
let monitor = Monitor::instance().await;
let iter = match ipv4_flow_type {
IPv4FlowType::Src1Min => monitor.ipv4_src_1min.iter(),
@ -143,12 +145,18 @@ impl Monitor {
IPv4FlowType::Dst10Min => monitor.ipv4_dst_10min.iter(),
IPv4FlowType::Dst1Hour => monitor.ipv4_dst_1hour.iter(),
};
iter.filter_map(|result| result.ok()).collect()
iter.filter_map(Result::ok)
.map(|(key, value)| {
let ip = Ipv4Addr::from(key[0]);
let port = key[1] as u16;
(SocketAddrV4::new(ip, port), FlowStats::from(value))
})
.collect()
}
pub async fn get_ipv6_flow_data(
ipv6_flow_type: IPv6FlowType,
) -> StdHashMap<EbpfAddrPortV6, EbpfFlowStats> {
) -> StdHashMap<SocketAddrV6, FlowStats> {
let monitor = Monitor::instance().await;
let iter = match ipv6_flow_type {
IPv6FlowType::Src1Min => monitor.ipv6_src_1min.iter(),
@ -158,6 +166,12 @@ impl Monitor {
IPv6FlowType::Dst10Min => monitor.ipv6_dst_10min.iter(),
IPv6FlowType::Dst1Hour => monitor.ipv6_dst_1hour.iter(),
};
iter.filter_map(|result| result.ok()).collect()
iter.filter_map(Result::ok)
.map(|(key, value)| {
let ip = Ipv6Addr::from(key[0]);
let port = key[1] as u16;
(SocketAddrV6::new(ip, port, 0, 0), FlowStats::from(value))
})
.collect()
}
}

View File

@ -0,0 +1,35 @@
use serde::{Deserialize, Serialize};
use net_guardia_common::model::http_method::EbpfHttpMethod;
#[derive(Serialize, Deserialize, Debug, Copy, Clone)]
pub enum HttpMethod {
GET,
POST,
PUT,
DELETE,
HEAD,
OPTIONS,
PATCH,
TRACE,
CONNECT,
}
impl HttpMethod {
pub fn convert_to_ebpf(http_methods: Vec<HttpMethod>) -> EbpfHttpMethod {
let mut ebpf_http_method = 0_u16;
for http_method in http_methods {
match http_method {
HttpMethod::GET => ebpf_http_method |= 0b0000_0000_0000_0001,
HttpMethod::POST => ebpf_http_method |= 0b0000_0000_0000_0010,
HttpMethod::PUT => ebpf_http_method |= 0b0000_0000_0000_0100,
HttpMethod::DELETE => ebpf_http_method |= 0b0000_0000_0000_1000,
HttpMethod::HEAD => ebpf_http_method |= 0b0000_0000_0001_0000,
HttpMethod::OPTIONS => ebpf_http_method |= 0b0000_0000_0010_0000,
HttpMethod::PATCH => ebpf_http_method |= 0b0000_0000_0100_0000,
HttpMethod::TRACE => ebpf_http_method |= 0b0000_0000_1000_0000,
HttpMethod::CONNECT => ebpf_http_method |= 0b0000_0001_0000_0000,
}
}
ebpf_http_method
}
}

View File

@ -1,19 +0,0 @@
use crate::utils::definition::IntoString;
use net_guardia_common::model::ip_address::{EbpfAddrPortV4, EbpfAddrPortV6};
use std::net::{Ipv4Addr, Ipv6Addr};
impl IntoString for EbpfAddrPortV4 {
fn into_string(self) -> String {
let ip_addr = Ipv4Addr::from(self[0]);
let port = self[1] as u16;
format!("{}:{}", ip_addr, port)
}
}
impl IntoString for EbpfAddrPortV6 {
fn into_string(self) -> String {
let ip_addr = Ipv6Addr::from(self[0]);
let port = self[1] as u16;
format!("[{}]:{}", ip_addr, port)
}
}

View File

@ -1,4 +1,4 @@
pub mod config;
pub mod flow_stats;
pub mod flow_type;
pub mod ip_address;
pub mod http_method;

View File

@ -0,0 +1,13 @@
use net_guardia_common::MAX_RULES_PORT;
use net_guardia_common::model::ip_address::Port;
pub fn convert_ports_to_vec(ports: [u16; MAX_RULES_PORT]) -> Vec<Port> {
let mut filtered_ports: Vec<Port> = ports
.into_iter()
.filter(|&port| port != 0)
.collect();
if filtered_ports.is_empty() {
filtered_ports.push(0);
}
filtered_ports
}

View File

@ -1,4 +1,5 @@
pub mod log_entry;
pub mod definition;
pub mod ip_address;
pub mod logging;
pub mod static_files;

View File

@ -1,9 +1,7 @@
use crate::core::monitor::Monitor;
use crate::model::flow_type::{IPv4FlowType, IPv6FlowType};
use crate::web::utils::map_util::{transform_ipv4_flow_data, transform_ipv6_flow_data};
use actix_web::{get, web, Error, HttpRequest, HttpResponse, Responder, Scope};
use actix_web_actors::ws::start;
use tracing::info;
use crate::web::utils::flow_websocket::{IPv4FlowWebSocket, IPv6FlowWebSocket};
pub fn initialize() -> Scope {
@ -27,85 +25,73 @@ pub fn initialize() -> Scope {
#[get("/get/ipv4/src/1min")]
async fn get_ipv4_src_1min() -> impl Responder {
let flow_data = Monitor::get_ipv4_flow_data(IPv4FlowType::Src1Min).await;
let formated = transform_ipv4_flow_data(flow_data);
HttpResponse::Ok().json(web::Json(formated))
HttpResponse::Ok().json(web::Json(flow_data))
}
#[get("/get/ipv4/src/10min")]
async fn get_ipv4_src_10min() -> impl Responder {
let flow_data = Monitor::get_ipv4_flow_data(IPv4FlowType::Src10Min).await;
let formated = transform_ipv4_flow_data(flow_data);
HttpResponse::Ok().json(web::Json(formated))
HttpResponse::Ok().json(web::Json(flow_data))
}
#[get("/get/ipv4/src/1hour")]
async fn get_ipv4_src_1hour() -> impl Responder {
let flow_data = Monitor::get_ipv4_flow_data(IPv4FlowType::Src1Hour).await;
let formated = transform_ipv4_flow_data(flow_data);
HttpResponse::Ok().json(web::Json(formated))
HttpResponse::Ok().json(web::Json(flow_data))
}
#[get("/get/ipv6/src/1min")]
async fn get_ipv6_src_1min() -> impl Responder {
let flow_data = Monitor::get_ipv6_flow_data(IPv6FlowType::Src1Min).await;
let formated = transform_ipv6_flow_data(flow_data);
HttpResponse::Ok().json(web::Json(formated))
HttpResponse::Ok().json(web::Json(flow_data))
}
#[get("/get/ipv6/src/10min")]
async fn get_ipv6_src_10min() -> impl Responder {
let flow_data = Monitor::get_ipv6_flow_data(IPv6FlowType::Src10Min).await;
let formated = transform_ipv6_flow_data(flow_data);
HttpResponse::Ok().json(web::Json(formated))
HttpResponse::Ok().json(web::Json(flow_data))
}
#[get("/get/ipv6/src/1hour")]
async fn get_ipv6_src_1hour() -> impl Responder {
let flow_data = Monitor::get_ipv6_flow_data(IPv6FlowType::Src1Hour).await;
let formated = transform_ipv6_flow_data(flow_data);
HttpResponse::Ok().json(web::Json(formated))
HttpResponse::Ok().json(web::Json(flow_data))
}
#[get("/get/ipv4/dst/1min")]
async fn get_ipv4_dst_1min() -> impl Responder {
let flow_data = Monitor::get_ipv4_flow_data(IPv4FlowType::Dst1Min).await;
let formated = transform_ipv4_flow_data(flow_data);
HttpResponse::Ok().json(web::Json(formated))
HttpResponse::Ok().json(web::Json(flow_data))
}
#[get("/get/ipv4/dst/10min")]
async fn get_ipv4_dst_10min() -> impl Responder {
let flow_data = Monitor::get_ipv4_flow_data(IPv4FlowType::Dst10Min).await;
let formated = transform_ipv4_flow_data(flow_data);
HttpResponse::Ok().json(web::Json(formated))
HttpResponse::Ok().json(web::Json(flow_data))
}
#[get("/get/ipv4/dst/1hour")]
async fn get_ipv4_dst_1hour() -> impl Responder {
let flow_data = Monitor::get_ipv4_flow_data(IPv4FlowType::Dst1Hour).await;
let formated = transform_ipv4_flow_data(flow_data);
HttpResponse::Ok().json(web::Json(formated))
HttpResponse::Ok().json(web::Json(flow_data))
}
#[get("/get/ipv6/dst/1min")]
async fn get_ipv6_dst_1min() -> impl Responder {
let flow_data = Monitor::get_ipv6_flow_data(IPv6FlowType::Src1Min).await;
let formated = transform_ipv6_flow_data(flow_data);
HttpResponse::Ok().json(web::Json(formated))
HttpResponse::Ok().json(web::Json(flow_data))
}
#[get("/get/ipv6/dst/10min")]
async fn get_ipv6_dst_10min() -> impl Responder {
let flow_data = Monitor::get_ipv6_flow_data(IPv6FlowType::Src10Min).await;
let formated = transform_ipv6_flow_data(flow_data);
HttpResponse::Ok().json(web::Json(formated))
HttpResponse::Ok().json(web::Json(flow_data))
}
#[get("/get/ipv6/dst/1hour")]
async fn get_ipv6_dst_1hour() -> impl Responder {
let flow_data = Monitor::get_ipv6_flow_data(IPv6FlowType::Src1Hour).await;
let formated = transform_ipv6_flow_data(flow_data);
HttpResponse::Ok().json(web::Json(formated))
HttpResponse::Ok().json(web::Json(flow_data))
}
#[get("/websocket/ipv4/{flow_type}")]

View File

@ -1,7 +1,6 @@
use crate::core::config_manager::ConfigManager;
use crate::core::monitor::Monitor;
use crate::model::flow_type::{IPv4FlowType, IPv6FlowType};
use crate::web::utils::map_util::{transform_ipv4_flow_data, transform_ipv6_flow_data};
use actix::prelude::*;
use actix_web_actors::ws;
use std::time::Duration;
@ -20,8 +19,7 @@ impl Actor for IPv4FlowWebSocket {
let interval = ctx.run_interval(refresh_interval, |actor, ctx| {
let flow_type = actor.flow_type.clone();
let future = async move {
let flow_data = Monitor::get_ipv4_flow_data(flow_type).await;
transform_ipv4_flow_data(flow_data)
Monitor::get_ipv4_flow_data(flow_type).await
};
ctx.wait(future.into_actor(actor).map(|flow_data, _, ctx| {
if let Ok(json) = serde_json::to_string(&flow_data) {
@ -67,8 +65,7 @@ impl Actor for IPv6FlowWebSocket {
let interval = ctx.run_interval(refresh_interval, |actor, ctx| {
let flow_type = actor.flow_type.clone();
let future = async move {
let flow_data = Monitor::get_ipv6_flow_data(flow_type).await;
transform_ipv6_flow_data(flow_data)
Monitor::get_ipv6_flow_data(flow_type).await
};
ctx.wait(future.into_actor(actor).map(|flow_data, _, ctx| {
if let Ok(json) = serde_json::to_string(&flow_data) {

View File

@ -1,25 +0,0 @@
use crate::model::flow_stats::FlowStats;
use net_guardia_common::model::flow_stats::EbpfFlowStats as EbpfFlowStats;
use net_guardia_common::model::ip_address::{
EbpfAddrPortV4 as EbpfAddrPortV4, EbpfAddrPortV6 as EbpfAddrPortV6,
};
use std::collections::HashMap;
use crate::utils::definition::IntoString;
pub fn transform_ipv4_flow_data(
original: HashMap<EbpfAddrPortV4, EbpfFlowStats>,
) -> HashMap<String, FlowStats> {
original
.into_iter()
.map(|(key, value)| (key.into_string(), FlowStats::from(value)))
.collect()
}
pub fn transform_ipv6_flow_data(
original: HashMap<EbpfAddrPortV6, EbpfFlowStats>,
) -> HashMap<String, FlowStats> {
original
.into_iter()
.map(|(key, value)| (key.into_string(), FlowStats::from(value)))
.collect()
}

View File

@ -1,2 +1 @@
pub mod flow_websocket;
pub mod map_util;