From c38834f18c4e868a35b301599eb522ed1c4949b4 Mon Sep 17 00:00:00 2001 From: Paul Date: Sun, 1 Dec 2024 19:49:54 +0100 Subject: [PATCH] chore: wip code --- src/config.rs | 11 ++-- src/fw.rs | 153 +++++++++++++++++++++++++++++++------------------- src/ip.rs | 1 + src/ipblc.rs | 23 +++++++- 4 files changed, 125 insertions(+), 63 deletions(-) diff --git a/src/config.rs b/src/config.rs index 75da5ae..1313e68 100644 --- a/src/config.rs +++ b/src/config.rs @@ -155,11 +155,11 @@ impl Context { pub async fn get_blocklist_toblock(&self) -> Vec { let mut res: Vec = vec![]; - for (_, block) in self.blocklist.iter() { - match self.cfg.sets.get(&block.ipdata.src) { + for (_, ipblock) in self.blocklist.iter() { + match self.cfg.sets.get(&ipblock.ipdata.src) { Some(set) => { - if block.tryfail >= set.tryfail { - res.push(block.ipdata.clone()); + if ipblock.tryfail >= set.tryfail && !ipblock.blocked { + res.push(ipblock.ipdata.clone()); } } None => {} @@ -176,6 +176,7 @@ impl Context { .unwrap() .with_timezone(&chrono::Local); let blocktime = set.blocktime; + let blocked = false; if ipevent.mode == "file".to_string() && gethostname(true) == ipevent.hostname { let block = self.blocklist @@ -185,6 +186,7 @@ impl Context { tryfail: 0, starttime, blocktime, + blocked, }); block.tryfail += 1; block.blocktime = blocktime; @@ -199,6 +201,7 @@ impl Context { tryfail: set.tryfail, starttime, blocktime, + blocked, }); } } diff --git a/src/fw.rs b/src/fw.rs index d5aa021..92c8bdf 100644 --- a/src/fw.rs +++ b/src/fw.rs @@ -12,23 +12,24 @@ pub enum FwTableType { IPv6, } -pub fn fwglobalinit<'a>() -> ((Batch, Table), (Batch, Table)) { - let (batch4, table4) = fwinit(FwTableType::IPv4); - let (batch6, table6) = fwinit(FwTableType::IPv6); - ((batch4, table4), (batch6, table6)) +pub enum FwAction { + Add, + Delete, } macro_rules! initrules { - ($batch:expr, $table:expr, $chain:ident) => { + ($batch:expr, $table:expr, $chain:ident, $reset:expr) => { $chain.set_hook(Hook::new(HookClass::In, 1)); $batch.add(&$chain, MsgType::Add); - $batch.add(&Rule::new(&$chain).unwrap(), MsgType::Del); + if $reset { + $batch.add(&Rule::new(&$chain).unwrap(), MsgType::Del); + } }; } -macro_rules! createrules { - ($ipdata:ident, $chain:ident, $batch:ident, $t:ty, $ip_t:ident) => { +macro_rules! makerules { + ($ipdata:ident, $chain:ident, $batch:ident, $t:ty, $ip_t:ident,$action:ty) => { let ip = $ipdata.ip.parse::<$t>().unwrap(); Rule::new(&$chain) .unwrap() @@ -38,66 +39,46 @@ macro_rules! createrules { }; } -fn fwinit(t: FwTableType) -> (Batch, Table) { +pub fn fwglobalinit(t: FwTableType, reset: bool) -> (Batch, Chain) { let table_name: String; let table: Table; + let mut chain: Chain; match t { FwTableType::IPv4 => { table_name = format!("{PKG_NAME}4"); - table = Table::new(ProtocolFamily::Ipv4).with_name(table_name) + table = Table::new(ProtocolFamily::Ipv4).with_name(table_name); + chain = Chain::new(&table) + .with_policy(ChainPolicy::Accept) + .with_name(PKG_NAME); } FwTableType::IPv6 => { table_name = format!("{PKG_NAME}6"); table = Table::new(ProtocolFamily::Ipv6).with_name(table_name); + chain = Chain::new(&table) + .with_policy(ChainPolicy::Accept) + .with_name(PKG_NAME); } } let mut batch = Batch::new(); batch.add(&table, MsgType::Add); - (batch, table) + initrules!(batch, table, chain, reset); + + (batch, chain) } -pub fn fwblock<'a>( - ips_add_all: &Vec, - ret: &mut Vec, - fwlen: &mut usize, -) -> std::result::Result<(), Error> { - let ((mut batch4, table4), (mut batch6, table6)) = fwglobalinit(); +pub fn fwblock<'a>(ip_add: &IpData) -> std::result::Result<(), error::QueryError> { + let (mut batch4, chain4) = fwglobalinit(FwTableType::IPv4, false); + let (mut batch6, chain6) = fwglobalinit(FwTableType::IPv6, false); - let mut chain4 = Chain::new(&table4) - .with_policy(ChainPolicy::Accept) - .with_name(PKG_NAME); - let mut chain6 = Chain::new(&table6) - .with_policy(ChainPolicy::Accept) - .with_name(PKG_NAME); - initrules!(batch4, table4, chain4); - initrules!(batch6, table6, chain6); - - let mut factor = 1; - if ips_add_all.len() > 100 { - factor = (ips_add_all.len() / 10) as usize - } - - let ips_add_tmp: Vec = ips_add_all.clone().iter().map(|x| x.clone()).collect(); - let mut ips_add_iter = ips_add_tmp.chunks(factor); - let mut ips_add: Vec<&[IpData]> = vec![]; - while let Some(x) = ips_add_iter.next() { - ips_add.push(x); - } - - // build and add rules - for ipdata_group in ips_add.clone() { - for ipdata in ipdata_group { - match ipdata.t { - 4 => { - createrules!(ipdata, chain4, batch4, Ipv4Addr, ipv4); - } - 6 => { - createrules!(ipdata, chain6, batch6, Ipv6Addr, ipv6); - } - _ => {} - } + match ip_add.t { + 4 => { + makerules!(ip_add, chain4, batch4, Ipv4Addr, ipv4, FwAction::Add); } + 6 => { + makerules!(ip_add, chain6, batch6, Ipv6Addr, ipv6, FwAction::Add); + } + _ => {} } // validate and send batch @@ -106,16 +87,74 @@ pub fn fwblock<'a>( Ok(_) => {} Err(e) => { println!("error sending batch: {e}"); + return Err(e); } }; } - if fwlen != &mut ips_add_all.len() { - ret.push(format!( - "{length} ip in firewall", - length = ips_add_all.len() - )); - } - *fwlen = ips_add_all.len(); Ok(()) } + +pub fn fwunblock<'a>(ips_del: &Vec) -> std::result::Result<(), Error> { + let (mut batch4, chain4) = fwglobalinit(FwTableType::IPv4, false); + let (mut batch6, chain6) = fwglobalinit(FwTableType::IPv6, false); + + // to implement + /*for ip_del in ips_del { + match ip_del.t { + 4 => { + makerules!(ip_del, chain4, batch4, Ipv4Addr, ipv4, FwAction::Del); + } + 6 => { + makerules!(ip_del, chain6, batch6, Ipv6Addr, ipv6, FwAction::Del); + } + _ => {} + } + }*/ + Ok(()) +} + +pub fn get_current_rules(table_name: &str, chain_name: &str) -> Result<(), Error> { + let get_table = || -> Result, Error> { + let tables = list_tables().unwrap(); + for table in tables { + if let Some(name) = table.get_name() { + println!("Found table {}", name); + + if *name == table_name { + return Ok(Some(table)); + } + } + } + + Ok(None) + }; + + let get_chain = |table: &Table| -> Result, Error> { + let chains = list_chains_for_table(table).unwrap(); + for chain in chains { + if let Some(name) = chain.get_name() { + println!("Found chain {}", name); + + if *name == chain_name { + return Ok(Some(chain)); + } + } + } + + Ok(None) + }; + + let table = get_table()?.expect("no table?"); + let chain = get_chain(&table)?.expect("no chain?"); + + let rules = list_rules_for_chain(&chain).unwrap(); + for mut rule in rules { + println!("{:?}", rule); + } + Ok(()) +} + +pub fn fw_rules_count() -> i64 { + 0 +} diff --git a/src/ip.rs b/src/ip.rs index 510fbe7..93a705b 100644 --- a/src/ip.rs +++ b/src/ip.rs @@ -51,6 +51,7 @@ pub struct BlockIpData { pub tryfail: i64, pub blocktime: i64, pub starttime: DateTime, + pub blocked: bool, } #[derive(Clone, Debug, Serialize, Deserialize, Eq)] diff --git a/src/ipblc.rs b/src/ipblc.rs index e11b880..9f5d004 100644 --- a/src/ipblc.rs +++ b/src/ipblc.rs @@ -1,5 +1,5 @@ use crate::config::{Context, GIT_VERSION}; -use crate::fw::fwblock; +use crate::fw::*; use crate::ip::{filter, IpData, IpEvent}; use crate::ipevent; use crate::monitoring::apiserver; @@ -33,6 +33,10 @@ pub async fn run() { let inotify = Inotify::init(InitFlags::empty()).unwrap(); let globalctx = Context::new(&inotify).await; let ctxarc = Arc::new(RwLock::new(globalctx)); + let (batch4, _) = fwglobalinit(FwTableType::IPv4, true); + let (batch6, _) = fwglobalinit(FwTableType::IPv6, true); + batch4.send().unwrap(); + batch6.send().unwrap(); let mut fwlen: usize = 0; @@ -132,8 +136,23 @@ pub async fn run() { let ctx = ctxclone.read().await; ctx.get_blocklist_toblock().await }; + // apply firewall blocking - match fwblock(&toblock, &mut ret, &mut fwlen) { + for b in toblock { + match fwblock(&b) { + Ok(_) => { + let mut ctx = ctxclone.write().await; + if let Some(x) = ctx.blocklist.get_mut(&b.ip) { + x.blocked = true; + } + } + Err(e) => { + println!("err: {e}, unable to push firewall rules, use super user") + } + }; + } + get_current_rules("ipblc4", "ipblc").unwrap(); + match fwunblock(&tounblock) { Ok(_) => {} Err(e) => { println!("err: {e}, unable to push firewall rules, use super user")