diff --git a/Cargo.lock b/Cargo.lock index 0324f6d..81da77a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -68,9 +68,9 @@ dependencies = [ [[package]] name = "anyhow" -version = "1.0.94" +version = "1.0.95" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c1fd03a028ef38ba2276dce7e33fcd6369c158a1bca17946c4b1b701891c1ff7" +checksum = "34ac096ce696dc2fcabef30516bb13c0a68a11d30131d3df6f04711467681b04" [[package]] name = "assert_matches" @@ -144,9 +144,9 @@ dependencies = [ [[package]] name = "cc" -version = "1.2.3" +version = "1.2.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "27f657647bcff5394bf56c7317665bbf790a137a50eaaa5c6bfbb9e27a518f2d" +checksum = "a012a0df96dd6d06ba9a1b29d6402d1a5d77c6befd2566afdc26e10603dc93d7" dependencies = [ "shlex", ] @@ -205,9 +205,9 @@ checksum = "5b63caa9aa9397e2d9480a9b13673856c78d8ac123288526c37d7839f2a86990" [[package]] name = "compact_str" -version = "0.8.0" +version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6050c3a16ddab2e412160b31f2c871015704239bca62f72f6e5f0be631d3f644" +checksum = "3b79c4069c6cad78e2e0cdfcbd26275770669fb39fd308a752dc110e83b9af32" dependencies = [ "castaway", "cfg-if", @@ -361,9 +361,9 @@ checksum = "60b1af1c220855b6ceac025d3f6ecdd2b7c4894bfe9cd9bda4fbb4bc7c0d4cf0" [[package]] name = "env_filter" -version = "0.1.2" +version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4f2c92ceda6ceec50f43169f9ee8424fe2db276791afde7b2cd8bc084cb376ab" +checksum = "186e05a59d4c50738528153b83b0b0194d3a29507dfec16eccd4b342903397d0" dependencies = [ "log", "regex", @@ -371,9 +371,9 @@ dependencies = [ [[package]] name = "env_logger" -version = "0.11.5" +version = "0.11.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e13fa619b91fb2381732789fc5de83b45675e882f66623b7d8cb4f643017018d" +checksum = "dcaee3d8e3cfc3fd92428d477bc97fc29ec8716d180c0d74c643bb26166660e0" dependencies = [ "anstream", "anstyle", @@ -406,9 +406,9 @@ checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" [[package]] name = "foldhash" -version = "0.1.3" +version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f81ec6369c545a7d40e4589b5597581fa1c441fe1cce96dd1de43159910a36a2" +checksum = "a0d2fde1f7b3d48b8395d5f2de76c18a528bd6a9cdde438df747bfcba3e05d6f" [[package]] name = "font8x8" @@ -480,9 +480,9 @@ checksum = "b248f5224d1d606005e02c97f5aa4e88eeb230488bcc03bc9ca4d7991399f2b5" [[package]] name = "instability" -version = "0.3.3" +version = "0.3.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b829f37dead9dc39df40c2d3376c179fdfd2ac771f53f55d3c30dc096a3c0c6e" +checksum = "898e106451f7335950c9cc64f8ec67b5f65698679ac67ed00619aeef14e1cf75" dependencies = [ "darling", "indoc", @@ -507,6 +507,15 @@ dependencies = [ "either", ] +[[package]] +name = "itertools" +version = "0.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b192c782037fadd9cfa75548310488aabdbf3d2da73885b31bd0abd03351285" +dependencies = [ + "either", +] + [[package]] name = "itoa" version = "1.0.14" @@ -525,9 +534,9 @@ dependencies = [ [[package]] name = "libc" -version = "0.2.167" +version = "0.2.169" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09d6582e104315a817dff97f75133544b2e094ee22447d2acf4a74e189ba06fc" +checksum = "b5aba8db14291edd000dfcc4d620c7ebfb122c613afb886ca8803fa4e128a20a" [[package]] name = "libmimalloc-sys" @@ -615,9 +624,9 @@ checksum = "e82e9f64c09f56aa7c80c3fa087997bd99a913f91d9c74d36cf5fd75dd5773e6" [[package]] name = "object" -version = "0.36.5" +version = "0.36.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aedf0a2d09c573ed1d8d85b30c119153926a2b36dce0ab28322c09a117a4683e" +checksum = "62948e14d923ea95ea2c7c86c71013138b66525b86bdc08d2dcc262bdb497b87" dependencies = [ "crc32fast", "hashbrown", @@ -653,7 +662,7 @@ dependencies = [ "crossterm", "dirs", "env_logger", - "itertools", + "itertools 0.14.0", "kanal", "libc", "log", @@ -719,9 +728,9 @@ dependencies = [ [[package]] name = "quote" -version = "1.0.37" +version = "1.0.38" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b5b9d34b8991d19d98081b46eacdd8eb58c6f2b201139f7c5f643cc155a633af" +checksum = "0e4dccaaaf89514f546c693ddc140f729f958c247918a13380cccc6078391acc" dependencies = [ "proc-macro2", ] @@ -738,7 +747,7 @@ dependencies = [ "crossterm", "indoc", "instability", - "itertools", + "itertools 0.13.0", "lru", "paste", "strum", @@ -749,9 +758,9 @@ dependencies = [ [[package]] name = "redox_syscall" -version = "0.5.7" +version = "0.5.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b6dfecf2c74bce2466cabf93f6664d6998a69eb21e39f4207930065b27b771f" +checksum = "03a862b389f93e68874fbf580b9de08dd02facb9a788ebadaf4a3fd33cf58834" dependencies = [ "bitflags", ] @@ -811,9 +820,9 @@ dependencies = [ [[package]] name = "rustversion" -version = "1.0.18" +version = "1.0.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0e819f2bc632f285be6d7cd36e25940d45b2391dd6d9b939e79de557f7014248" +checksum = "f7c45b9784283f1b2e7fb61b42047c2fd678ef0960d4f6f1eba131594cc369d4" [[package]] name = "ryu" @@ -829,18 +838,18 @@ checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" [[package]] name = "serde" -version = "1.0.215" +version = "1.0.217" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6513c1ad0b11a9376da888e3e0baa0077f1aed55c17f50e7b2397136129fb88f" +checksum = "02fc4265df13d6fa1d00ecff087228cc0a2b5f3c0e87e258d8b94a156e984c70" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.215" +version = "1.0.217" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ad1e866f866923f252f05c889987993144fb74e722403468a4ebd70c3cd756c0" +checksum = "5a9bf7cf98d04a2b28aead066b7496853d4779c9cc183c440dbac457641e19a0" dependencies = [ "proc-macro2", "quote", @@ -849,9 +858,9 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.133" +version = "1.0.134" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c7fceb2473b9166b2294ef05efcb65a3db80803f0b03ef86a5fc88a2b85ee377" +checksum = "d00f4175c42ee48b15416f6193a959ba3a0d67fc699a0db9ad12df9f83991c7d" dependencies = [ "itoa", "memchr", @@ -937,9 +946,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.90" +version = "2.0.94" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "919d3b74a5dd0ccd15aeb8f93e7006bd9e14c295087c9896a110f490752bcf31" +checksum = "987bc0be1cdea8b10216bd06e2ca407d40b9543468fafd3ddfb02f36e77f71f3" dependencies = [ "proc-macro2", "quote", @@ -974,7 +983,7 @@ checksum = "8b046cf880cb40db75567b60ca22dc38a4165ef490be6bfad5718b22bcb6aabf" dependencies = [ "derive_builder", "font8x8", - "itertools", + "itertools 0.13.0", "ratatui", ] @@ -1006,7 +1015,7 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b3644627a5af5fa321c95b9b235a72fd24cd29c648c2c379431e6628655627bf" dependencies = [ - "itertools", + "itertools 0.13.0", "unicode-segmentation", "unicode-width 0.1.14", ] diff --git a/oryx-common/src/ip.rs b/oryx-common/src/ip.rs deleted file mode 100644 index 7dbc32d..0000000 --- a/oryx-common/src/ip.rs +++ /dev/null @@ -1,134 +0,0 @@ -// use core::fmt::Display; -// -// use core::net::{Ipv4Addr, Ipv6Addr}; -// -// #[derive(Debug, Copy, Clone)] -// pub enum IpPacket { -// V4(Ipv4Packet), -// V6(Ipv6Packet), -// } -// -// #[derive(Debug, Copy, Clone)] -// pub struct Ipv4Packet { -// pub src_ip: Ipv4Addr, -// pub dst_ip: Ipv4Addr, -// pub ihl: u8, -// pub tos: u8, -// pub total_length: u16, -// pub id: u16, -// pub fragment_offset: u16, -// pub ttl: u8, -// pub proto: IpProto, -// pub checksum: u16, -// } -// -// #[derive(Debug, Copy, Clone)] -// pub struct Ipv6Packet { -// pub src_ip: Ipv6Addr, -// pub dst_ip: Ipv6Addr, -// pub proto: IpProto, -// } -// -// #[derive(Debug, Copy, Clone)] -// pub enum IpProto { -// Tcp(TcpPacket), -// Udp(UdpPacket), -// Icmp(IcmpPacket), -// } -// -// #[derive(Debug, Copy, Clone)] -// pub struct TcpPacket { -// pub dst_port: u16, -// pub src_port: u16, -// } -// -// #[derive(Debug, Copy, Clone)] -// pub struct UdpPacket { -// pub dst_port: u16, -// pub src_port: u16, -// } -// -// #[derive(Debug, Copy, Clone)] -// pub struct IcmpPacket { -// pub icmp_type: IcmpType, -// } -// -// #[derive(Debug, Copy, Clone)] -// pub enum IcmpType { -// EchoRequest, -// EchoReply, -// DestinationUnreachable, -// } -// -// impl Display for IcmpType { -// fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { -// match self { -// IcmpType::EchoReply => { -// write!(f, "Echo Reply") -// } -// IcmpType::EchoRequest => { -// write!(f, "Echo Request") -// } -// IcmpType::DestinationUnreachable => { -// write!(f, "Destination Unreachable") -// } -// } -// } -// } -// -// impl Display for IpPacket { -// fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { -// match self { -// IpPacket::V4(ipv4_packet) => match ipv4_packet.proto { -// IpProto::Tcp(tcp_packet) => { -// write!( -// f, -// "{} {} {} {} TCP", -// ipv4_packet.src_ip, -// tcp_packet.src_port, -// ipv4_packet.dst_ip, -// tcp_packet.dst_port -// ) -// } -// IpProto::Udp(udp_packet) => { -// write!( -// f, -// "{} {} {} {} UDP", -// ipv4_packet.src_ip, -// udp_packet.src_port, -// ipv4_packet.dst_ip, -// udp_packet.dst_port -// ) -// } -// IpProto::Icmp(_) => { -// write!(f, "{} {} ICMP", ipv4_packet.src_ip, ipv4_packet.dst_ip) -// } -// }, -// IpPacket::V6(ipv6_packet) => match ipv6_packet.proto { -// IpProto::Tcp(tcp_packet) => { -// write!( -// f, -// "{} {} {} {} TCP", -// ipv6_packet.src_ip, -// tcp_packet.src_port, -// ipv6_packet.dst_ip, -// tcp_packet.dst_port -// ) -// } -// IpProto::Udp(udp_packet) => { -// write!( -// f, -// "{} {} {} {} UDP", -// ipv6_packet.src_ip, -// udp_packet.src_port, -// ipv6_packet.dst_ip, -// udp_packet.dst_port -// ) -// } -// IpProto::Icmp(_) => { -// write!(f, "{} {} ICMP", ipv6_packet.src_ip, ipv6_packet.dst_ip) -// } -// }, -// } -// } -// } diff --git a/oryx-common/src/lib.rs b/oryx-common/src/lib.rs index 36c7063..6dbcd2c 100644 --- a/oryx-common/src/lib.rs +++ b/oryx-common/src/lib.rs @@ -4,7 +4,6 @@ use core::mem; use network_types::{arp::ArpHdr, icmp::IcmpHdr, ip::IpHdr, tcp::TcpHdr, udp::UdpHdr}; -pub mod ip; pub mod protocols; pub const MAX_FIREWALL_RULES: u32 = 32; diff --git a/oryx-ebpf/Cargo.lock b/oryx-ebpf/Cargo.lock index 4ad61cf..298c082 100644 --- a/oryx-ebpf/Cargo.lock +++ b/oryx-ebpf/Cargo.lock @@ -97,24 +97,24 @@ dependencies = [ [[package]] name = "quote" -version = "1.0.37" +version = "1.0.38" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b5b9d34b8991d19d98081b46eacdd8eb58c6f2b201139f7c5f643cc155a633af" +checksum = "0e4dccaaaf89514f546c693ddc140f729f958c247918a13380cccc6078391acc" dependencies = [ "proc-macro2", ] [[package]] name = "rustversion" -version = "1.0.18" +version = "1.0.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0e819f2bc632f285be6d7cd36e25940d45b2391dd6d9b939e79de557f7014248" +checksum = "f7c45b9784283f1b2e7fb61b42047c2fd678ef0960d4f6f1eba131594cc369d4" [[package]] name = "syn" -version = "2.0.90" +version = "2.0.94" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "919d3b74a5dd0ccd15aeb8f93e7006bd9e14c295087c9896a110f490752bcf31" +checksum = "987bc0be1cdea8b10216bd06e2ca407d40b9543468fafd3ddfb02f36e77f71f3" dependencies = [ "proc-macro2", "quote", diff --git a/oryx-tui/Cargo.toml b/oryx-tui/Cargo.toml index 98ca497..af73fe3 100644 --- a/oryx-tui/Cargo.toml +++ b/oryx-tui/Cargo.toml @@ -17,7 +17,7 @@ libc = "0.2" aya = "0.13" oryx-common = { path = "../oryx-common" } mio = { version = "1", features = ["os-poll", "os-ext"] } -itertools = "0.13" +itertools = "0.14" dirs = "5" kanal = "0.1.0-pre8" mimalloc = "0.1" diff --git a/oryx-tui/src/app.rs b/oryx-tui/src/app.rs index c1c528b..8906d80 100644 --- a/oryx-tui/src/app.rs +++ b/oryx-tui/src/app.rs @@ -10,7 +10,11 @@ use std::{ time::Duration, }; -use crate::{filter::Filter, help::Help}; +use crate::{ + filter::Filter, + help::Help, + packet::{direction::TrafficDirection, NetworkPacket}, +}; use crate::{filter::IoChannels, notification::Notification}; use crate::{packet::AppPacket, section::Section}; @@ -41,7 +45,7 @@ pub struct App { pub packets: Arc>>, pub notifications: Vec, pub section: Section, - pub data_channel_sender: kanal::Sender<[u8; RawPacket::LEN]>, + pub data_channel_sender: kanal::Sender<([u8; RawPacket::LEN], TrafficDirection)>, pub is_editing: bool, pub active_popup: Option, } @@ -54,20 +58,25 @@ impl Default for App { impl App { pub fn new() -> Self { - let packets = Arc::new(Mutex::new(Vec::with_capacity(AppPacket::LEN * 1024 * 1024))); + let packets = Arc::new(Mutex::new(Vec::with_capacity(RawPacket::LEN * 1024 * 1024))); let (sender, receiver) = kanal::unbounded(); let firewall_channels = IoChannels::new(); + thread::spawn({ let packets = packets.clone(); move || loop { - if let Ok(raw_packet) = receiver.recv() { - let app_packet = AppPacket::from(raw_packet); + if let Ok((raw_packet, direction)) = receiver.recv() { + let network_packet = NetworkPacket::from(raw_packet); let mut packets = packets.lock().unwrap(); if packets.len() == packets.capacity() { packets.reserve(1024 * 1024); } + let app_packet = AppPacket { + packet: network_packet, + direction, + }; packets.push(app_packet); } } diff --git a/oryx-tui/src/ebpf/egress.rs b/oryx-tui/src/ebpf/egress.rs index 68e3008..a0b19cf 100644 --- a/oryx-tui/src/ebpf/egress.rs +++ b/oryx-tui/src/ebpf/egress.rs @@ -19,6 +19,7 @@ use crate::{ event::Event, filter::FilterChannelSignal, notification::{Notification, NotificationLevel}, + packet::direction::TrafficDirection, section::firewall::FirewallSignal, }; use mio::{unix::SourceFd, Events, Interest, Poll, Token}; @@ -31,7 +32,7 @@ use super::{ pub fn load_egress( iface: String, notification_sender: kanal::Sender, - data_sender: kanal::Sender<[u8; RawPacket::LEN]>, + data_sender: kanal::Sender<([u8; RawPacket::LEN], TrafficDirection)>, filter_channel_receiver: kanal::Receiver, firewall_egress_receiver: kanal::Receiver, terminate: Arc, @@ -221,7 +222,7 @@ pub fn load_egress( break; } let packet: [u8; RawPacket::LEN] = item.to_owned().try_into().unwrap(); - data_sender.send(packet).ok(); + data_sender.send((packet, TrafficDirection::Egress)).ok(); } } } diff --git a/oryx-tui/src/ebpf/ingress.rs b/oryx-tui/src/ebpf/ingress.rs index 826e258..2db027a 100644 --- a/oryx-tui/src/ebpf/ingress.rs +++ b/oryx-tui/src/ebpf/ingress.rs @@ -19,6 +19,7 @@ use crate::{ event::Event, filter::FilterChannelSignal, notification::{Notification, NotificationLevel}, + packet::direction::TrafficDirection, section::firewall::FirewallSignal, }; use mio::{unix::SourceFd, Events, Interest, Poll, Token}; @@ -31,7 +32,7 @@ use super::{ pub fn load_ingress( iface: String, notification_sender: kanal::Sender, - data_sender: kanal::Sender<[u8; RawPacket::LEN]>, + data_sender: kanal::Sender<([u8; RawPacket::LEN], TrafficDirection)>, filter_channel_receiver: kanal::Receiver, firewall_ingress_receiver: kanal::Receiver, terminate: Arc, @@ -225,7 +226,7 @@ pub fn load_ingress( break; } let packet: [u8; RawPacket::LEN] = item.to_owned().try_into().unwrap(); - data_sender.send(packet).ok(); + data_sender.send((packet, TrafficDirection::Ingress)).ok(); } } } diff --git a/oryx-tui/src/export.rs b/oryx-tui/src/export.rs index 78599ca..de5e4d0 100644 --- a/oryx-tui/src/export.rs +++ b/oryx-tui/src/export.rs @@ -8,7 +8,7 @@ use crate::{ app::AppResult, packet::{ network::{IpPacket, IpProto}, - AppPacket, + AppPacket, NetworkPacket, }, }; @@ -39,8 +39,8 @@ pub fn export(packets: &[AppPacket]) -> AppResult<()> { headers.0, headers.1, headers.2, headers.3, headers.4 )?; for packet in packets { - match packet { - AppPacket::Arp(p) => { + match packet.packet { + NetworkPacket::Arp(p) => { writeln!( file, "{:39} {:^11} {:39} {:^11} ARP", @@ -50,7 +50,7 @@ pub fn export(packets: &[AppPacket]) -> AppResult<()> { "-" )?; } - AppPacket::Ip(packet) => match packet { + NetworkPacket::Ip(packet) => match packet { IpPacket::V4(ipv4_packet) => match ipv4_packet.proto { IpProto::Tcp(p) => { writeln!( diff --git a/oryx-tui/src/filter.rs b/oryx-tui/src/filter.rs index a62a717..3c80600 100644 --- a/oryx-tui/src/filter.rs +++ b/oryx-tui/src/filter.rs @@ -5,7 +5,7 @@ mod network; mod transport; use crossterm::event::{KeyCode, KeyEvent}; -use direction::{TrafficDirection, TrafficDirectionFilter}; +use direction::TrafficDirectionFilter; use link::LinkFilter; use network::NetworkFilter; use oryx_common::{ @@ -30,6 +30,7 @@ use crate::{ ebpf::{egress::load_egress, ingress::load_ingress}, event::Event, interface::Interface, + packet::direction::TrafficDirection, section::firewall::FirewallSignal, }; @@ -145,7 +146,7 @@ impl Filter { pub fn start( &mut self, notification_sender: kanal::Sender, - data_sender: kanal::Sender<[u8; RawPacket::LEN]>, + data_sender: kanal::Sender<([u8; RawPacket::LEN], TrafficDirection)>, ) -> AppResult<()> { let iface = self.interface.selected_interface.name.clone(); diff --git a/oryx-tui/src/filter/direction.rs b/oryx-tui/src/filter/direction.rs index b2708b2..55bd363 100644 --- a/oryx-tui/src/filter/direction.rs +++ b/oryx-tui/src/filter/direction.rs @@ -1,9 +1,6 @@ -use std::{ - fmt::Display, - sync::{ - atomic::{AtomicBool, Ordering}, - Arc, - }, +use std::sync::{ + atomic::{AtomicBool, Ordering}, + Arc, }; use ratatui::{ @@ -12,7 +9,8 @@ use ratatui::{ widgets::{Block, BorderType, Borders, Row, Table, TableState}, Frame, }; -use serde::{Deserialize, Serialize}; + +use crate::packet::direction::TrafficDirection; #[derive(Debug)] pub struct TrafficDirectionFilter { @@ -23,21 +21,6 @@ pub struct TrafficDirectionFilter { pub terminate_egress: Arc, } -#[derive(Debug, Copy, Clone, PartialEq, Serialize, Deserialize)] -pub enum TrafficDirection { - Ingress, - Egress, -} - -impl Display for TrafficDirection { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - match self { - TrafficDirection::Ingress => write!(f, "Ingress"), - TrafficDirection::Egress => write!(f, "Egress"), - } - } -} - impl Default for TrafficDirectionFilter { fn default() -> Self { Self::new() diff --git a/oryx-tui/src/filter/fuzzy.rs b/oryx-tui/src/filter/fuzzy.rs index 124b45a..5b45564 100644 --- a/oryx-tui/src/filter/fuzzy.rs +++ b/oryx-tui/src/filter/fuzzy.rs @@ -35,10 +35,10 @@ impl Fuzzy { let mut pattern = String::new(); loop { thread::sleep(Duration::from_millis(TICK_RATE)); - let packets = packets.lock().unwrap(); let mut fuzzy = fuzzy.lock().unwrap(); if fuzzy.is_enabled() && !fuzzy.filter.value().is_empty() { + let packets = packets.lock().unwrap(); let current_pattern = fuzzy.filter.value().to_owned(); if current_pattern != pattern { fuzzy.find(packets.as_slice()); @@ -98,7 +98,7 @@ impl Fuzzy { self.packets = packets .iter() .copied() - .filter(|p| p.to_string().contains(self.filter.value())) + .filter(|p| p.packet.to_string().contains(self.filter.value())) .collect::>(); } @@ -107,7 +107,7 @@ impl Fuzzy { &mut packets .iter() .copied() - .filter(|p| p.to_string().contains(self.filter.value())) + .filter(|p| p.packet.to_string().contains(self.filter.value())) .collect::>(), ); } diff --git a/oryx-tui/src/handler.rs b/oryx-tui/src/handler.rs index 6a1a7be..dca3f05 100644 --- a/oryx-tui/src/handler.rs +++ b/oryx-tui/src/handler.rs @@ -21,10 +21,7 @@ pub fn handle_key_events( match key_event.code { KeyCode::Enter => { if app.filter.focused_block == FocusedBlock::Apply { - app.section.stats = Some(Stats::new( - app.packets.clone(), - app.filter.interface.selected_interface.clone(), - )); + app.section.stats = Some(Stats::new(app.packets.clone())); app.filter .start(event_sender.clone(), app.data_channel_sender.clone())?; diff --git a/oryx-tui/src/packet.rs b/oryx-tui/src/packet.rs index 543469d..2fd7bc6 100644 --- a/oryx-tui/src/packet.rs +++ b/oryx-tui/src/packet.rs @@ -1,9 +1,11 @@ +pub mod direction; pub mod link; pub mod network; pub mod transport; use std::{fmt::Display, mem, net::Ipv4Addr}; +use direction::TrafficDirection; use link::{ArpPacket, ArpType, MacAddr}; use network::{IcmpPacket, IcmpType, IpPacket, IpProto, Ipv4Packet, Ipv6Packet}; use network_types::ip::IpHdr; @@ -11,16 +13,22 @@ use oryx_common::{ProtoHdr, RawPacket}; use transport::{TcpPacket, UdpPacket}; #[derive(Debug, Copy, Clone)] -pub enum AppPacket { - Ip(IpPacket), - Arp(ArpPacket), +pub struct AppPacket { + pub packet: NetworkPacket, + pub direction: TrafficDirection, } impl AppPacket { pub const LEN: usize = mem::size_of::(); } -impl Display for AppPacket { +#[derive(Debug, Copy, Clone)] +pub enum NetworkPacket { + Ip(IpPacket), + Arp(ArpPacket), +} + +impl Display for NetworkPacket { fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { match self { Self::Arp(packet) => write!(f, "{}", packet), @@ -29,7 +37,7 @@ impl Display for AppPacket { } } -impl From<[u8; RawPacket::LEN]> for AppPacket { +impl From<[u8; RawPacket::LEN]> for NetworkPacket { fn from(value: [u8; RawPacket::LEN]) -> Self { let raw_packet = value.as_ptr() as *const RawPacket; match unsafe { &*raw_packet } { @@ -87,7 +95,7 @@ impl From<[u8; RawPacket::LEN]> for AppPacket { } }; - AppPacket::Ip(IpPacket::V4(Ipv4Packet { + NetworkPacket::Ip(IpPacket::V4(Ipv4Packet { src_ip, dst_ip, ihl: u8::from_be(ipv4_packet.ihl()), @@ -153,7 +161,7 @@ impl From<[u8; RawPacket::LEN]> for AppPacket { } }; - AppPacket::Ip(IpPacket::V6(Ipv6Packet { + NetworkPacket::Ip(IpPacket::V6(Ipv6Packet { traffic_class: ipv6_packet.priority(), flow_label: ipv6_packet.flow_label, payload_length: u16::from_be(ipv6_packet.payload_len), diff --git a/oryx-tui/src/packet/direction.rs b/oryx-tui/src/packet/direction.rs new file mode 100644 index 0000000..b6a4cf7 --- /dev/null +++ b/oryx-tui/src/packet/direction.rs @@ -0,0 +1,18 @@ +use std::fmt::Display; + +use serde::{Deserialize, Serialize}; + +#[derive(Debug, Copy, Clone, PartialEq, Serialize, Deserialize)] +pub enum TrafficDirection { + Ingress, + Egress, +} + +impl Display for TrafficDirection { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + TrafficDirection::Ingress => write!(f, "Ingress"), + TrafficDirection::Egress => write!(f, "Egress"), + } + } +} diff --git a/oryx-tui/src/packet/network.rs b/oryx-tui/src/packet/network.rs index e25dff2..d776d3d 100644 --- a/oryx-tui/src/packet/network.rs +++ b/oryx-tui/src/packet/network.rs @@ -257,8 +257,8 @@ impl Ipv6Packet { Span::styled("Flow Label", Style::new().bold()), Span::from(format!( "{:#0x}", - (self.flow_label[0] as u32) << 16 - | (self.flow_label[1] as u32) << 8 + ((self.flow_label[0] as u32) << 16) + | ((self.flow_label[1] as u32) << 8) | (self.flow_label[2] as u32) )), ]), diff --git a/oryx-tui/src/section/alert/syn_flood.rs b/oryx-tui/src/section/alert/syn_flood.rs index c93dfc1..13b5813 100644 --- a/oryx-tui/src/section/alert/syn_flood.rs +++ b/oryx-tui/src/section/alert/syn_flood.rs @@ -15,8 +15,9 @@ use ratatui::{ }; use crate::packet::{ + direction::TrafficDirection, network::{IpPacket, IpProto}, - AppPacket, + AppPacket, NetworkPacket, }; const WIN_SIZE: usize = 100_000; @@ -42,12 +43,19 @@ impl SynFlood { let packets = packets.lock().unwrap(); packets.len().saturating_sub(1) }; + thread::sleep(Duration::from_secs(5)); + let app_packets = { let packets = packets.lock().unwrap(); packets.clone() }; + let app_packets: Vec = app_packets + .into_iter() + .filter(|packet| packet.direction == TrafficDirection::Ingress) + .collect(); + let mut map = map.lock().unwrap(); map.clear(); @@ -59,8 +67,8 @@ impl SynFlood { app_packets[start_index..app_packets.len().saturating_sub(1)] .iter() - .for_each(|packet| { - if let AppPacket::Ip(ip_packet) = packet { + .for_each(|app_packet| { + if let NetworkPacket::Ip(ip_packet) = app_packet.packet { if let IpPacket::V4(ipv4_packet) = ip_packet { if let IpProto::Tcp(tcp_packet) = ipv4_packet.proto { if tcp_packet.syn == 1 { @@ -92,7 +100,8 @@ impl SynFlood { } }); - if (nb_syn_packets as f64 / WIN_SIZE as f64) > 0.45 { + // 90% of incoming packets + if (nb_syn_packets as f64 / WIN_SIZE as f64) > 0.95 { detected.store(true, std::sync::atomic::Ordering::Relaxed); } else { detected.store(false, std::sync::atomic::Ordering::Relaxed); diff --git a/oryx-tui/src/section/firewall.rs b/oryx-tui/src/section/firewall.rs index 622e623..c81d85b 100644 --- a/oryx-tui/src/section/firewall.rs +++ b/oryx-tui/src/section/firewall.rs @@ -15,7 +15,7 @@ use std::{fs, net::IpAddr, num::ParseIntError, os::unix::fs::chown, str::FromStr use tui_input::{backend::crossterm::EventHandler, Input}; use uuid; -use crate::{app::AppResult, filter::direction::TrafficDirection, notification::Notification}; +use crate::{app::AppResult, notification::Notification, packet::direction::TrafficDirection}; #[derive(Debug, Clone)] pub enum FirewallSignal { diff --git a/oryx-tui/src/section/inspection.rs b/oryx-tui/src/section/inspection.rs index 43198a0..2e49182 100644 --- a/oryx-tui/src/section/inspection.rs +++ b/oryx-tui/src/section/inspection.rs @@ -20,7 +20,7 @@ use crate::{ notification::{Notification, NotificationLevel}, packet::{ network::{IpPacket, IpProto}, - AppPacket, + AppPacket, NetworkPacket, }, }; @@ -332,15 +332,15 @@ impl Inspection { let packets: Vec = if fuzzy.is_enabled() & !fuzzy.filter.value().is_empty() { packets_to_display .iter() - .map(|app_packet| match app_packet { - AppPacket::Arp(packet) => Row::new(vec![ + .map(|app_packet| match app_packet.packet { + NetworkPacket::Arp(packet) => Row::new(vec![ fuzzy::highlight(pattern, packet.src_mac.to_string()).blue(), Cell::from(Line::from("-").centered()).yellow(), fuzzy::highlight(pattern, packet.dst_mac.to_string()).blue(), Cell::from(Line::from("-").centered()).yellow(), fuzzy::highlight(pattern, "ARP".to_string()).cyan(), ]), - AppPacket::Ip(packet) => match packet { + NetworkPacket::Ip(packet) => match packet { IpPacket::V4(ipv4_packet) => match ipv4_packet.proto { IpProto::Tcp(p) => Row::new(vec![ fuzzy::highlight(pattern, ipv4_packet.src_ip.to_string()).blue(), @@ -393,8 +393,8 @@ impl Inspection { } else { packets_to_display .iter() - .map(|app_packet| match app_packet { - AppPacket::Arp(packet) => Row::new(vec![ + .map(|app_packet| match app_packet.packet { + NetworkPacket::Arp(packet) => Row::new(vec![ Span::from(packet.src_mac.to_string()) .into_centered_line() .blue(), @@ -405,7 +405,7 @@ impl Inspection { Span::from("-").into_centered_line().yellow(), Span::from("ARP".to_string()).into_centered_line().cyan(), ]), - AppPacket::Ip(packet) => match packet { + NetworkPacket::Ip(packet) => match packet { IpPacket::V4(ipv4_packet) => match ipv4_packet.proto { IpProto::Tcp(p) => Row::new(vec![ Span::from(ipv4_packet.src_ip.to_string()) @@ -640,7 +640,7 @@ impl Inspection { let fuzzy = self.fuzzy.lock().unwrap(); let packets = self.packets.lock().unwrap(); - let packet = if fuzzy.is_enabled() { + let app_packet = if fuzzy.is_enabled() { fuzzy.packets[self.packet_index.unwrap()] } else { packets[self.packet_index.unwrap()] @@ -657,9 +657,9 @@ impl Inspection { .border_type(BorderType::Thick), block, ); - match packet { - AppPacket::Ip(ip_packet) => ip_packet.render(block, frame), - AppPacket::Arp(arp_packet) => arp_packet.render(block, frame), + match app_packet.packet { + NetworkPacket::Ip(ip_packet) => ip_packet.render(block, frame), + NetworkPacket::Arp(arp_packet) => arp_packet.render(block, frame), }; } } diff --git a/oryx-tui/src/section/stats.rs b/oryx-tui/src/section/stats.rs index 0f813d2..b266b30 100644 --- a/oryx-tui/src/section/stats.rs +++ b/oryx-tui/src/section/stats.rs @@ -17,10 +17,10 @@ use ratatui::{ use crate::{ bandwidth::Bandwidth, dns::get_hostname, - interface::NetworkInterface, packet::{ + direction::TrafficDirection, network::{IpPacket, IpProto}, - AppPacket, + AppPacket, NetworkPacket, }, }; @@ -41,7 +41,7 @@ pub struct Stats { } impl Stats { - pub fn new(packets: Arc>>, selected_interface: NetworkInterface) -> Self { + pub fn new(packets: Arc>>) -> Self { let packet_stats: Arc> = Arc::new(Mutex::new(PacketStats::default())); thread::spawn({ @@ -51,24 +51,24 @@ impl Stats { loop { thread::sleep(Duration::from_millis(500)); - let packets = { packets.lock().unwrap().clone() }; + let app_packets = { packets.lock().unwrap().clone() }; - if packets.is_empty() { + if app_packets.is_empty() { continue; } + let mut packet_stats = packet_stats.lock().unwrap(); - for packet in packets[last_index..].iter() { - match packet { - AppPacket::Arp(_) => { + + for app_packet in app_packets[last_index..].iter() { + match app_packet.packet { + NetworkPacket::Arp(_) => { packet_stats.link.arp += 1; } - AppPacket::Ip(packet) => match packet { + NetworkPacket::Ip(packet) => match packet { IpPacket::V4(ipv4_packet) => { packet_stats.network.ipv4 += 1; - if !ipv4_packet.dst_ip.is_private() - && !ipv4_packet.dst_ip.is_loopback() - { + if app_packet.direction == TrafficDirection::Egress { if let Some((_, counts)) = packet_stats .addresses .get_mut(&IpAddr::V4(ipv4_packet.dst_ip)) @@ -103,10 +103,7 @@ impl Stats { IpPacket::V6(ipv6_packet) => { packet_stats.network.ipv6 += 1; - if !selected_interface - .addresses - .contains(&IpAddr::V6(ipv6_packet.dst_ip)) - { + if app_packet.direction == TrafficDirection::Egress { if let Some((_, counts)) = packet_stats .addresses .get_mut(&IpAddr::V6(ipv6_packet.dst_ip)) @@ -144,7 +141,7 @@ impl Stats { packet_stats.total += 1; } - last_index = packets.len() - 1; + last_index = app_packets.len() - 1; } } });