From 6e9b208150099504059dbac0ca1bc443cb21da62 Mon Sep 17 00:00:00 2001 From: adrien gaultier Date: Sun, 6 Oct 2024 21:17:09 +0200 Subject: [PATCH] updates --- oryx-common/src/lib.rs | 13 ++++- oryx-ebpf/src/main.rs | 90 ++++++++++++++++++++++++-------- oryx-tui/src/ebpf.rs | 40 +++++++++++++- oryx-tui/src/section/firewall.rs | 12 +++-- 4 files changed, 128 insertions(+), 27 deletions(-) diff --git a/oryx-common/src/lib.rs b/oryx-common/src/lib.rs index 32483fb..c6ffc7c 100644 --- a/oryx-common/src/lib.rs +++ b/oryx-common/src/lib.rs @@ -1,6 +1,6 @@ #![no_std] -use core::mem; +use core::mem::{self, transmute}; use network_types::{arp::ArpHdr, icmp::IcmpHdr, ip::IpHdr, tcp::TcpHdr, udp::UdpHdr}; @@ -24,3 +24,14 @@ pub enum ProtoHdr { impl RawPacket { pub const LEN: usize = mem::size_of::(); } + +pub fn to_u128(x: [u16; 8]) -> u128 { + // (u128::from(x[0]) << 96) + // | (u128::from(x[1]) << 64) + // | (u128::from(x[2]) << 32) + // | u128::from(x[3]) + // } + + let addr16 = x.map(|x| x.to_be()); + u128::from_be_bytes(unsafe { transmute::<_, [u8; 16]>(addr16) }) +} diff --git a/oryx-ebpf/src/main.rs b/oryx-ebpf/src/main.rs index f124f3d..be369d5 100644 --- a/oryx-ebpf/src/main.rs +++ b/oryx-ebpf/src/main.rs @@ -2,9 +2,9 @@ #![no_main] use aya_ebpf::{ - bindings::TC_ACT_PIPE, + bindings::{TC_ACT_PIPE, TC_ACT_SHOT}, macros::{classifier, map}, - maps::{Array, RingBuf}, + maps::{Array, HashMap, RingBuf}, programs::TcContext, }; use core::mem; @@ -18,7 +18,7 @@ use network_types::{ }; use oryx_common::{ protocols::{LinkProtocol, NetworkProtocol, Protocol, TransportProtocol}, - ProtoHdr, RawPacket, + to_u128, ProtoHdr, RawPacket, }; #[map] @@ -33,6 +33,15 @@ static TRANSPORT_FILTERS: Array = Array::with_max_entries(8, 0); #[map] static LINK_FILTERS: Array = Array::with_max_entries(8, 0); +#[map] +static BLOCKLIST_IPV6_INGRESS: HashMap = HashMap::::with_max_entries(128, 0); +#[map] +static BLOCKLIST_IPV6_EGRESS: HashMap = HashMap::::with_max_entries(128, 0); +#[map] +static BLOCKLIST_IPV4_INGRESS: HashMap = HashMap::::with_max_entries(128, 0); +#[map] +static BLOCKLIST_IPV4_EGRESS: HashMap = HashMap::::with_max_entries(128, 0); + #[classifier] pub fn oryx(ctx: TcContext) -> i32 { match process(ctx) { @@ -89,26 +98,47 @@ fn process(ctx: TcContext) -> Result { match ethhdr.ether_type { EtherType::Ipv4 => { - if filter_packet(Protocol::Network(NetworkProtocol::Ipv4)) { - return Ok(TC_ACT_PIPE); - } let header: Ipv4Hdr = ctx.load(EthHdr::LEN).map_err(|_| ())?; + let src_addr = header.src_addr; + let dst_addr = header.dst_addr; + match header.proto { IpProto::Tcp => { - if filter_packet(Protocol::Transport(TransportProtocol::TCP)) { - return Ok(TC_ACT_PIPE); - } let tcphdr: *const TcpHdr = ptr_at(&ctx, EthHdr::LEN + Ipv4Hdr::LEN)?; + let src_port = u16::from_be(unsafe { (*tcphdr).source }); + let dst_port = u16::from_be(unsafe { (*tcphdr).dest }); + + if unsafe { BLOCKLIST_IPV4_INGRESS.get(&src_addr) } == Some(&src_port) + || unsafe { BLOCKLIST_IPV4_EGRESS.get(&dst_addr) } == Some(&dst_port) + { + return Ok(TC_ACT_SHOT); //DROP PACKET + } + + if filter_packet(Protocol::Network(NetworkProtocol::Ipv4)) + || filter_packet(Protocol::Transport(TransportProtocol::TCP)) + { + return Ok(TC_ACT_PIPE); //DONT FWD PACKET TO TUI + } submit(RawPacket::Ip( IpHdr::V4(header), ProtoHdr::Tcp(unsafe { *tcphdr }), )); } IpProto::Udp => { - if filter_packet(Protocol::Transport(TransportProtocol::UDP)) { - return Ok(TC_ACT_PIPE); - } let udphdr: *const UdpHdr = ptr_at(&ctx, EthHdr::LEN + Ipv4Hdr::LEN)?; + let src_port = u16::from_be(unsafe { (*udphdr).source }); + let dst_port = u16::from_be(unsafe { (*udphdr).dest }); + + if unsafe { BLOCKLIST_IPV4_INGRESS.get(&src_addr) } == Some(&src_port) + || unsafe { BLOCKLIST_IPV4_EGRESS.get(&dst_addr) } == Some(&dst_port) + { + return Ok(TC_ACT_SHOT); //DROP PACKET + } + if filter_packet(Protocol::Network(NetworkProtocol::Ipv4)) + || filter_packet(Protocol::Transport(TransportProtocol::UDP)) + { + return Ok(TC_ACT_PIPE); //DONT FWD PACKET TO TUI + } submit(RawPacket::Ip( IpHdr::V4(header), ProtoHdr::Udp(unsafe { *udphdr }), @@ -128,26 +158,44 @@ fn process(ctx: TcContext) -> Result { } } EtherType::Ipv6 => { - if filter_packet(Protocol::Network(NetworkProtocol::Ipv6)) { - return Ok(TC_ACT_PIPE); - } let header: Ipv6Hdr = ctx.load(EthHdr::LEN).map_err(|_| ())?; + let src_addr = to_u128(unsafe { header.src_addr.in6_u.u6_addr16 }); + let dst_addr = to_u128(unsafe { header.dst_addr.in6_u.u6_addr16 }); + match header.next_hdr { IpProto::Tcp => { - if filter_packet(Protocol::Transport(TransportProtocol::TCP)) { - return Ok(TC_ACT_PIPE); - } let tcphdr: *const TcpHdr = ptr_at(&ctx, EthHdr::LEN + Ipv6Hdr::LEN)?; + let src_port = u16::from_be(unsafe { (*tcphdr).source }); + let dst_port = u16::from_be(unsafe { (*tcphdr).dest }); + if unsafe { BLOCKLIST_IPV6_INGRESS.get(&src_addr) } == Some(&src_port) + || unsafe { BLOCKLIST_IPV6_EGRESS.get(&dst_addr) } == Some(&dst_port) + { + return Ok(TC_ACT_SHOT); //DROP PACKET + } + if filter_packet(Protocol::Network(NetworkProtocol::Ipv6)) + || filter_packet(Protocol::Transport(TransportProtocol::TCP)) + { + return Ok(TC_ACT_PIPE); //DONT FWD PACKET TO TUI + } submit(RawPacket::Ip( IpHdr::V6(header), ProtoHdr::Tcp(unsafe { *tcphdr }), )); } IpProto::Udp => { - if filter_packet(Protocol::Transport(TransportProtocol::UDP)) { - return Ok(TC_ACT_PIPE); - } let udphdr: *const UdpHdr = ptr_at(&ctx, EthHdr::LEN + Ipv6Hdr::LEN)?; + let src_port = u16::from_be(unsafe { (*udphdr).source }); + let dst_port = u16::from_be(unsafe { (*udphdr).dest }); + if unsafe { BLOCKLIST_IPV6_INGRESS.get(&src_addr.into()) } == Some(&src_port) + || unsafe { BLOCKLIST_IPV6_EGRESS.get(&dst_addr.into()) } == Some(&dst_port) + { + return Ok(TC_ACT_SHOT); //DROP PACKET + } + if filter_packet(Protocol::Network(NetworkProtocol::Ipv6)) + || filter_packet(Protocol::Transport(TransportProtocol::UDP)) + { + return Ok(TC_ACT_PIPE); //DONT FWD PACKET TO TUI + } submit(RawPacket::Ip( IpHdr::V6(header), ProtoHdr::Udp(unsafe { *udphdr }), diff --git a/oryx-tui/src/ebpf.rs b/oryx-tui/src/ebpf.rs index a77b8d2..3960108 100644 --- a/oryx-tui/src/ebpf.rs +++ b/oryx-tui/src/ebpf.rs @@ -1,5 +1,6 @@ use std::{ io, + net::IpAddr, os::fd::AsRawFd, sync::{atomic::AtomicBool, Arc}, thread::{self, spawn}, @@ -8,7 +9,7 @@ use std::{ use aya::{ include_bytes_aligned, - maps::{ring_buf::RingBufItem, Array, MapData, RingBuf}, + maps::{ring_buf::RingBufItem, Array, HashMap, MapData, RingBuf}, programs::{tc, SchedClassifier, TcAttachType}, Bpf, }; @@ -68,7 +69,7 @@ impl Ebpf { notification_sender: kanal::Sender, data_sender: kanal::Sender<[u8; RawPacket::LEN]>, filter_channel_receiver: kanal::Receiver<(Protocol, bool)>, - _firewall_ingress_receiver: kanal::Receiver, + firewall_ingress_receiver: kanal::Receiver, terminate: Arc, ) { thread::spawn({ @@ -149,6 +150,7 @@ impl Ebpf { let mut poll = Poll::new().unwrap(); let mut events = Events::with_capacity(128); + //filter-ebpf interface let mut transport_filters: Array<_, u32> = Array::try_from(bpf.take_map("TRANSPORT_FILTERS").unwrap()).unwrap(); @@ -157,8 +159,42 @@ impl Ebpf { let mut link_filters: Array<_, u32> = Array::try_from(bpf.take_map("LINK_FILTERS").unwrap()).unwrap(); + // firewall-ebpf interface + let mut ipv4_firewall: HashMap<_, u32, u16> = + HashMap::try_from(bpf.take_map("BLOCKLIST_IPV4_INGRESS").unwrap()).unwrap(); + let mut ipv6_firewall: HashMap<_, u128, u16> = + HashMap::try_from(bpf.take_map("BLOCKLIST_IPV6_INGRESS").unwrap()).unwrap(); spawn(move || loop { + if let Ok(rule) = firewall_ingress_receiver.recv() { + match rule.enabled { + true => match rule.ip { + IpAddr::V4(addr) => { + println!("{}", rule); + ipv4_firewall.insert(u32::from(addr), rule.port, 0).unwrap(); + } + IpAddr::V6(addr) => { + let _ = ipv6_firewall.insert( + u128::from_be_bytes(addr.octets()), + rule.port, + 0, + ); + } + }, + + false => match rule.ip { + IpAddr::V4(addr) => { + let _ = ipv4_firewall.remove(&u32::from(addr)); + } + + IpAddr::V6(addr) => { + let _ = + ipv6_firewall.remove(&u128::from_be_bytes(addr.octets())); + } + }, + } + } + if let Ok((filter, flag)) = filter_channel_receiver.recv() { match filter { Protocol::Transport(p) => { diff --git a/oryx-tui/src/section/firewall.rs b/oryx-tui/src/section/firewall.rs index 40455ed..a87bf3c 100644 --- a/oryx-tui/src/section/firewall.rs +++ b/oryx-tui/src/section/firewall.rs @@ -1,3 +1,4 @@ +use core::fmt::Display; use crossterm::event::{Event, KeyCode, KeyEvent}; use ratatui::{ layout::{Constraint, Direction, Flex, Layout, Margin, Rect}, @@ -16,11 +17,16 @@ use crate::app::AppResult; pub struct FirewallRule { id: uuid::Uuid, name: String, - enabled: bool, - ip: IpAddr, - port: u16, + pub enabled: bool, + pub ip: IpAddr, + pub port: u16, } +impl Display for FirewallRule { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "{} {}", self.ip, self.port) + } +} #[derive(Debug, Clone, PartialEq)] pub enum FocusedInput { Name,