Add ssh service protect

This commit is contained in:
DaLaw2 2024-12-01 21:23:32 +08:00
parent 3d0970ad99
commit e3d2ed077d
10 changed files with 77 additions and 36 deletions

View File

@ -11,7 +11,7 @@ pub const MAX_STATS: u32 = 100000;
///
/// Limits the number of rules that can be configured to ensure
/// predictable performance and resource usage.
pub const MAX_RULES: u32 = 32;
pub const MAX_RULES: u32 = 1000;
/// Maximum number of port-specific rules allowed
///
/// Defines the upper limit for port-based filtering rules to maintain

View File

@ -3,4 +3,5 @@ pub mod flow_stats;
pub mod http_method;
pub mod ip_address;
pub mod packet_status;
pub mod placeholder;
pub mod pseudo_header;

View File

@ -0,0 +1 @@
pub type PlaceHolder = u8;

View File

@ -5,40 +5,30 @@ use net_guardia_common::model::ip_address::{IPv4, IPv6, Port};
use net_guardia_common::{MAX_RULES, MAX_RULES_PORT};
#[map]
static BLOCKED_IPV4: HashMap<IPv4, [Port; MAX_RULES_PORT]> =
static PERMANENT_BLACKLIST_IPV4: HashMap<IPv4, [Port; MAX_RULES_PORT]> =
HashMap::with_max_entries(MAX_RULES, 0);
#[map]
static BLOCKED_IPV6: HashMap<IPv6, [Port; MAX_RULES_PORT]> =
static PERMANENT_BLACKLIST_IPV6: HashMap<IPv6, [Port; MAX_RULES_PORT]> =
HashMap::with_max_entries(MAX_RULES, 0);
pub fn should_block_ipv4(event: &IPv4Event) -> bool {
unsafe {
if let Some(ports) = BLOCKED_IPV4.get(&event.source_ip) {
if let Some(ports) = PERMANENT_BLACKLIST_IPV4.get(&event.source_ip) {
if is_port_blocked(ports, event.source_port) {
return true;
}
}
if let Some(ports) = BLOCKED_IPV4.get(&event.destination_ip) {
if is_port_blocked(ports, event.destination_port) {
return true;
}
}
}
false
}
pub fn should_block_ipv6(event: &IPv6Event) -> bool {
unsafe {
if let Some(ports) = BLOCKED_IPV6.get(&event.source_ip) {
if let Some(ports) = PERMANENT_BLACKLIST_IPV6.get(&event.source_ip) {
if is_port_blocked(ports, event.source_port) {
return true;
}
}
if let Some(ports) = BLOCKED_IPV6.get(&event.destination_ip) {
if is_port_blocked(ports, event.destination_port) {
return true;
}
}
}
false
}

View File

@ -1,5 +1,5 @@
pub mod forward;
pub mod blocking;
pub mod detect;
pub mod defence;
pub mod forward;
pub mod monitor;
pub mod service;

View File

@ -1,7 +1,8 @@
use aya_ebpf::maps::HashMap;
use aya_ebpf::maps::{Array, HashMap};
use net_guardia_common::model::event::{IPv4Event, IPv6Event};
use net_guardia_common::model::http_method::EbpfHttpMethod;
use net_guardia_common::model::ip_address::{EbpfAddrPortV4, EbpfAddrPortV6};
use net_guardia_common::model::ip_address::{EbpfAddrPortV4, EbpfAddrPortV6, IPv4, IPv6};
use net_guardia_common::model::placeholder::PlaceHolder;
use net_guardia_common::MAX_RULES;
static HTTP_SERVICE_V4: HashMap<EbpfAddrPortV4, EbpfHttpMethod> =
@ -9,35 +10,47 @@ static HTTP_SERVICE_V4: HashMap<EbpfAddrPortV4, EbpfHttpMethod> =
static HTTP_SERVICE_V6: HashMap<EbpfAddrPortV6, EbpfHttpMethod> =
HashMap::with_max_entries(MAX_RULES, 0);
pub fn ipv4_service_rule(event: &IPv4Event, start: usize, end: usize, offset: usize) -> bool {
static SSH_WHITE_LIST_ONLY: Array<PlaceHolder> = Array::with_max_entries(1, 0);
static IPV4_SSH_SERVICE: HashMap<EbpfAddrPortV4, PlaceHolder> =
HashMap::with_max_entries(MAX_RULES, 0);
static IPV6_SSH_SERVICE: HashMap<EbpfAddrPortV6, PlaceHolder> =
HashMap::with_max_entries(MAX_RULES, 0);
static IPV4_SSH_WHITE_LIST: HashMap<IPv4, PlaceHolder> = HashMap::with_max_entries(MAX_RULES, 0);
static IPV6_SSH_WHITE_LIST: HashMap<IPv6, PlaceHolder> = HashMap::with_max_entries(MAX_RULES, 0);
static IPV4_SSH_BLACK_LIST: HashMap<IPv4, PlaceHolder> = HashMap::with_max_entries(MAX_RULES, 0);
static IPV6_SSH_BLACK_LIST: HashMap<IPv6, PlaceHolder> = HashMap::with_max_entries(MAX_RULES, 0);
pub fn ipv4_service_rule_violation(event: &IPv4Event, start: usize, end: usize, offset: usize) -> bool {
let source = event.get_source();
let destination = event.get_destination();
ipv4_http_service(destination, start, end, offset)
ipv4_http_service_violation(&destination, start, end, offset) || ipv4_ssh_service_violation(&source, &destination)
}
pub fn ipv6_service_rule(event: &IPv6Event, start: usize, end: usize, offset: usize) -> bool {
pub fn ipv6_service_rule_violation(event: &IPv6Event, start: usize, end: usize, offset: usize) -> bool {
let source = event.get_source();
let destination = event.get_destination();
ipv6_http_service(destination, start, end, offset)
ipv6_http_service_violation(&destination, start, end, offset) || ipv6_ssh_service_violation(&source, &destination)
}
#[inline(always)]
fn ipv4_http_service(addr_port: EbpfAddrPortV4, start: usize, end: usize, offset: usize) -> bool {
match HTTP_SERVICE_V4.get_ptr_mut(&addr_port) {
fn ipv4_http_service_violation(addr_port: &EbpfAddrPortV4, start: usize, end: usize, offset: usize) -> bool {
match HTTP_SERVICE_V4.get_ptr_mut(addr_port) {
Some(allow_method) => match get_http_request_method(start, end, offset) {
Some(http_method) => unsafe { *allow_method & http_method != 0 },
None => false,
Some(http_method) => unsafe { *allow_method & http_method == 0 },
None => true,
},
None => true,
None => false,
}
}
#[inline(always)]
fn ipv6_http_service(addr_port: EbpfAddrPortV6, start: usize, end: usize, offset: usize) -> bool {
match HTTP_SERVICE_V6.get_ptr_mut(&addr_port) {
fn ipv6_http_service_violation(addr_port: &EbpfAddrPortV6, start: usize, end: usize, offset: usize) -> bool {
match HTTP_SERVICE_V6.get_ptr_mut(addr_port) {
Some(allow_method) => match get_http_request_method(start, end, offset) {
Some(http_method) => unsafe { *allow_method & http_method != 0 },
None => false,
Some(http_method) => unsafe { *allow_method & http_method == 0 },
None => true,
},
None => true,
None => false,
}
}
@ -60,3 +73,33 @@ fn get_http_request_method(start: usize, end: usize, offset: usize) -> Option<Eb
_ => None,
}
}
#[inline(always)]
fn ipv4_ssh_service_violation(source_ip: &EbpfAddrPortV4, destination: &EbpfAddrPortV4) -> bool {
unsafe {
if IPV4_SSH_SERVICE.get(destination).is_some() {
if SSH_WHITE_LIST_ONLY.get(0).is_some() {
IPV4_SSH_WHITE_LIST.get(&source_ip[0]).is_none()
} else {
IPV4_SSH_BLACK_LIST.get(&source_ip[0]).is_some()
}
} else {
false
}
}
}
#[inline(always)]
fn ipv6_ssh_service_violation(source_ip: &EbpfAddrPortV6, destination: &EbpfAddrPortV6) -> bool {
unsafe {
if IPV6_SSH_SERVICE.get(destination).is_some() {
if SSH_WHITE_LIST_ONLY.get(0).is_some() {
IPV6_SSH_WHITE_LIST.get(&source_ip[0]).is_none()
} else {
IPV6_SSH_BLACK_LIST.get(&source_ip[0]).is_some()
}
} else {
false
}
}
}

View File

@ -10,6 +10,7 @@ use aya_ebpf::{bindings::xdp_action, macros::xdp, programs::XdpContext};
#[allow(unused_imports)]
use aya_log_ebpf::info;
use network_types::eth::EtherType;
use crate::action::service;
#[xdp]
pub fn net_guardia(ctx: XdpContext) -> u32 {
@ -29,7 +30,9 @@ fn try_net_guardia(ctx: XdpContext) -> Result<u32, ()> {
if blocking::should_block_ipv4(&event) {
return Ok(xdp_action::XDP_DROP);
}
if service::ipv4_service_rule_violation(&event, start, end, offset) {
return Ok(xdp_action::XDP_DROP);
}
monitor::update_stats_ipv4(&event);
}
EtherType::Ipv6 => {
@ -37,6 +40,9 @@ fn try_net_guardia(ctx: XdpContext) -> Result<u32, ()> {
if blocking::should_block_ipv6(&event) {
return Ok(xdp_action::XDP_DROP);
}
if service::ipv6_service_rule_violation(&event, start, end, offset) {
return Ok(xdp_action::XDP_DROP);
}
monitor::update_stats_ipv6(&event);
}
_ => Err(())?,

View File

@ -2,7 +2,7 @@ use aya::maps::{HashMap as AyaHashMap, MapData};
use net_guardia_common::MAX_RULES_PORT;
use net_guardia_common::model::ip_address::{IPv4, IPv6, Port};
pub struct Blocking {
pub struct Control {
ipv4_black_list: AyaHashMap<MapData, IPv4, [Port; MAX_RULES_PORT]>,
ipv6_black_list: AyaHashMap<MapData, IPv6, [Port; MAX_RULES_PORT]>,
}

View File

@ -1,4 +1,4 @@
pub mod config_manager;
pub mod control;
pub mod monitor;
pub mod system;
mod blocking;