From 80a035842be532749b795fb5e22566ff5f8029bb Mon Sep 17 00:00:00 2001 From: Badr Date: Fri, 27 Sep 2024 14:07:37 +0200 Subject: [PATCH] add firewall tab --- oryx-tui/src/alerts/alert.rs | 62 ++++++++++------------------- oryx-tui/src/app.rs | 67 +++++++------------------------ oryx-tui/src/firewall.rs | 33 ++++++++++++++++ oryx-tui/src/handler.rs | 12 ++++-- oryx-tui/src/lib.rs | 4 ++ oryx-tui/src/mode.rs | 77 ++++++++++++++++++++++++++++++++++++ 6 files changed, 156 insertions(+), 99 deletions(-) create mode 100644 oryx-tui/src/firewall.rs create mode 100644 oryx-tui/src/mode.rs diff --git a/oryx-tui/src/alerts/alert.rs b/oryx-tui/src/alerts/alert.rs index e305902..d5f1e8e 100644 --- a/oryx-tui/src/alerts/alert.rs +++ b/oryx-tui/src/alerts/alert.rs @@ -1,8 +1,7 @@ use ratatui::{ - layout::{Alignment, Constraint, Direction, Layout, Margin, Rect}, + layout::{Constraint, Direction, Layout, Rect}, style::{Color, Style, Stylize}, - text::{Line, Span, Text}, - widgets::{Block, BorderType, Borders, Padding}, + text::{Span, Text}, Frame, }; use std::sync::{atomic::Ordering, Arc, Mutex}; @@ -38,40 +37,6 @@ impl Alert { } pub fn render(&self, frame: &mut Frame, block: Rect) { - frame.render_widget( - Block::default() - .title({ - Line::from(vec![ - Span::from(" Packet ").fg(Color::DarkGray), - Span::from(" Stats ").fg(Color::DarkGray), - { - if self.detected { - if self.flash_count % 12 == 0 { - Span::from(" Alert 󰐼 ").fg(Color::White).bg(Color::Red) - } else { - Span::from(" Alert 󰐼 ").bg(Color::Red) - } - } else { - Span::styled( - " Alert ", - Style::default().bg(Color::Green).fg(Color::White).bold(), - ) - } - }, - ]) - }) - .title_alignment(Alignment::Left) - .padding(Padding::top(1)) - .borders(Borders::ALL) - .style(Style::default()) - .border_type(BorderType::default()) - .border_style(Style::default().green()), - block.inner(Margin { - horizontal: 1, - vertical: 0, - }), - ); - if !self.detected { let text_block = Layout::default() .direction(Direction::Vertical) @@ -110,15 +75,28 @@ impl Alert { self.syn_flood.render(frame, syn_flood_block); } - pub fn title_span(&self) -> Span<'_> { - if self.detected { + pub fn title_span(&self, selected: bool) -> Span<'_> { + if !selected { + if self.detected { + if self.flash_count % 12 == 0 { + Span::from(" Alert 󰐼 ").fg(Color::White).bg(Color::Red) + } else { + Span::from(" Alert 󰐼 ").fg(Color::Red) + } + } else { + Span::from(" Alert ").fg(Color::DarkGray) + } + } else if self.detected { if self.flash_count % 12 == 0 { - Span::from(" Alert 󰐼 ").fg(Color::White).bg(Color::Red) + Span::from(" Alert 󰐼 ").fg(Color::White) } else { - Span::from(" Alert 󰐼 ").fg(Color::Red) + Span::from(" Alert 󰐼 ").fg(Color::White).bg(Color::Red) } } else { - Span::from(" Alert ").fg(Color::DarkGray) + Span::styled( + " Alert ", + Style::default().bg(Color::Green).fg(Color::White).bold(), + ) } } } diff --git a/oryx-tui/src/app.rs b/oryx-tui/src/app.rs index c9d57b7..657751a 100644 --- a/oryx-tui/src/app.rs +++ b/oryx-tui/src/app.rs @@ -1,7 +1,7 @@ use oryx_common::RawPacket; use ratatui::{ layout::{Alignment, Constraint, Direction, Flex, Layout, Margin, Rect}, - style::{Color, Style, Stylize}, + style::{Style, Stylize}, text::{Line, Span}, widgets::{ Block, BorderType, Borders, Cell, Clear, HighlightSpacing, Padding, Paragraph, Row, @@ -16,8 +16,6 @@ use std::{ }; use tui_big_text::{BigText, PixelSize}; -use crate::alerts::alert::Alert; -use crate::bandwidth::Bandwidth; use crate::filters::{ filter::Filter, fuzzy::{self, Fuzzy}, @@ -30,6 +28,8 @@ use crate::packets::{ packet::AppPacket, }; use crate::stats::Stats; +use crate::{alerts::alert::Alert, firewall::Firewall}; +use crate::{bandwidth::Bandwidth, mode::Mode}; pub type AppResult = std::result::Result>; @@ -47,13 +47,6 @@ pub enum FocusedBlock { Main, } -#[derive(Debug, PartialEq)] -pub enum Mode { - Packet, - Stats, - Alerts, -} - #[derive(Debug)] pub struct DataEventHandler { pub sender: kanal::Sender<[u8; RawPacket::LEN]>, @@ -85,6 +78,7 @@ pub struct App { pub show_packet_infos_popup: bool, pub packet_index: Option, pub alert: Alert, + pub firewall: Firewall, } impl Default for App { @@ -134,6 +128,7 @@ impl App { show_packet_infos_popup: false, packet_index: None, alert: Alert::new(packets.clone()), + firewall: Firewall::new(), } } @@ -200,6 +195,13 @@ impl App { self.filter.render_on_sniffing(frame, filter_block); // Packets/Stats + if self.mode == Mode::Alerts { + self.mode + .render(frame, mode_block, self.alert.title_span(true)); + } else { + self.mode + .render(frame, mode_block, self.alert.title_span(false)); + }; match self.mode { Mode::Packet => { self.render_packets_mode(frame, mode_block); @@ -209,6 +211,7 @@ impl App { } Mode::Stats => self.render_stats_mode(frame, mode_block), Mode::Alerts => self.alert.render(frame, mode_block), + Mode::Firewall => self.firewall.render(frame, mode_block), } // Update filters @@ -523,25 +526,7 @@ impl App { .flex(Flex::SpaceBetween) .highlight_style(Style::new().bg(ratatui::style::Color::DarkGray)) .highlight_spacing(HighlightSpacing::Always) - .block( - Block::default() - .title({ - Line::from(vec![ - Span::styled( - " Packet ", - Style::default().bg(Color::Green).fg(Color::White).bold(), - ), - Span::from(" Stats ").fg(Color::DarkGray), - self.alert.title_span(), - ]) - }) - .title_alignment(Alignment::Left) - .padding(Padding::top(1)) - .borders(Borders::ALL) - .style(Style::default()) - .border_type(BorderType::default()) - .border_style(Style::default().green()), - ); + .block(Block::new().padding(Padding::top(2))); if fuzzy.is_enabled() { frame.render_stateful_widget(table, packet_block, &mut fuzzy.scroll_state); @@ -632,30 +617,6 @@ impl App { (chunks[0], chunks[1]) }; - frame.render_widget( - Block::default() - .title({ - Line::from(vec![ - Span::from(" Packet ").fg(Color::DarkGray), - Span::styled( - " Stats ", - Style::default().bg(Color::Green).fg(Color::White).bold(), - ), - self.alert.title_span(), - ]) - }) - .title_alignment(Alignment::Left) - .padding(Padding::top(1)) - .borders(Borders::ALL) - .style(Style::default()) - .border_type(BorderType::default()) - .border_style(Style::default().green()), - block.inner(Margin { - horizontal: 1, - vertical: 0, - }), - ); - stats.render(frame, stats_block); self.bandwidth.render( diff --git a/oryx-tui/src/firewall.rs b/oryx-tui/src/firewall.rs new file mode 100644 index 0000000..a203f50 --- /dev/null +++ b/oryx-tui/src/firewall.rs @@ -0,0 +1,33 @@ +use std::net::IpAddr; + +use ratatui::{ + layout::{Alignment, Constraint, Direction, Layout, Margin, Rect}, + style::{Color, Style, Stylize}, + text::{Line, Span, Text}, + widgets::{Block, BorderType, Borders, Padding}, + Frame, +}; + +#[derive(Debug, Clone, Default)] +pub struct Firewall { + rules: Vec, +} + +#[derive(Debug, Clone, Default)] +pub struct FirewallRule { + enabled: bool, + ip: Option, + port: Option, +} + +impl Firewall { + pub fn new() -> Self { + Self { rules: Vec::new() } + } + + pub fn add_rule(&mut self, rule: FirewallRule) {} + pub fn remove_rule(&mut self, rule: &FirewallRule) {} + pub fn update_rule(&mut self) {} + + pub fn render(&self, frame: &mut Frame, block: Rect) {} +} diff --git a/oryx-tui/src/handler.rs b/oryx-tui/src/handler.rs index 8efee88..71b90e1 100644 --- a/oryx-tui/src/handler.rs +++ b/oryx-tui/src/handler.rs @@ -3,11 +3,12 @@ use std::{thread, time::Duration}; use tui_input::backend::crossterm::EventHandler; use crate::{ - app::{App, AppResult, FocusedBlock, Mode}, + app::{App, AppResult, FocusedBlock}, ebpf::Ebpf, event::Event, export::export, filters::direction::TrafficDirection, + mode::Mode, notification::{Notification, NotificationLevel}, }; use ratatui::{ @@ -100,7 +101,8 @@ pub fn handle_key_events( match app.mode { Mode::Packet => app.mode = Mode::Stats, Mode::Stats => app.mode = Mode::Alerts, - Mode::Alerts => app.mode = Mode::Packet, + Mode::Alerts => app.mode = Mode::Firewall, + Mode::Firewall => app.mode = Mode::Packet, } } @@ -705,7 +707,8 @@ pub fn handle_key_events( match app.mode { Mode::Packet => app.mode = Mode::Stats, Mode::Stats => app.mode = Mode::Alerts, - Mode::Alerts => app.mode = Mode::Packet, + Mode::Alerts => app.mode = Mode::Firewall, + Mode::Firewall => app.mode = Mode::Packet, }; } else { match &app.focused_block { @@ -796,7 +799,8 @@ pub fn handle_key_events( match app.mode { Mode::Packet => app.mode = Mode::Alerts, Mode::Stats => app.mode = Mode::Packet, - Mode::Alerts => app.mode = Mode::Stats, + Mode::Alerts => app.mode = Mode::Firewall, + Mode::Firewall => app.mode = Mode::Packet, }; } else { match &app.focused_block { diff --git a/oryx-tui/src/lib.rs b/oryx-tui/src/lib.rs index 2534f24..ad450bf 100644 --- a/oryx-tui/src/lib.rs +++ b/oryx-tui/src/lib.rs @@ -42,3 +42,7 @@ pub mod alerts { pub mod alert; pub mod syn_flood; } + +pub mod firewall; + +pub mod mode; diff --git a/oryx-tui/src/mode.rs b/oryx-tui/src/mode.rs new file mode 100644 index 0000000..7d6428c --- /dev/null +++ b/oryx-tui/src/mode.rs @@ -0,0 +1,77 @@ +use ratatui::{ + layout::{Alignment, Rect}, + style::{Color, Style, Stylize}, + text::{Line, Span}, + widgets::{Block, BorderType, Borders, Padding}, + Frame, +}; +#[derive(Debug, PartialEq)] +pub enum Mode { + Packet, + Stats, + Alerts, + Firewall, +} + +impl Mode { + pub fn render(&self, frame: &mut Frame, area: Rect, alert_span: Span<'_>) { + let header = match self { + Self::Packet => { + vec![ + Span::styled( + " Packet ", + Style::default().bg(Color::Green).fg(Color::White).bold(), + ), + Span::from(" Stats ").fg(Color::DarkGray), + alert_span, + Span::from(" Firewall ").fg(Color::DarkGray), + ] + } + + Self::Stats => { + vec![ + Span::from(" Packet ").fg(Color::DarkGray), + Span::styled( + " Stats ", + Style::default().bg(Color::Green).fg(Color::White).bold(), + ), + alert_span, + Span::from(" Firewall ").fg(Color::DarkGray), + ] + } + + Self::Alerts => { + vec![ + Span::from(" Packet ").fg(Color::DarkGray), + Span::from(" Stats ").fg(Color::DarkGray), + alert_span.bold(), + Span::from(" Firewall ").fg(Color::DarkGray), + ] + } + + Self::Firewall => { + vec![ + Span::from(" Packet ").fg(Color::DarkGray), + Span::from(" Stats ").fg(Color::DarkGray), + alert_span, + Span::styled( + " Firewall ", + Style::default().bg(Color::Green).fg(Color::White).bold(), + ), + ] + } + }; + + frame.render_widget( + Block::default() + .title(Line::from(header)) + .title_alignment(Alignment::Left) + .padding(Padding::top(2)) + .borders(Borders::ALL) + .style(Style::default()) + .border_type(BorderType::default()) + .border_style(Style::default().green()), + area, + ); + } +}