Compare commits

...

1 Commits

Author SHA1 Message Date
563fbb557f fix: add better fw handling
All checks were successful
continuous-integration/drone/push Build is passing
* use stabilized rustables fw rule additions
* update dependencies
2025-02-27 00:13:09 +01:00
9 changed files with 348 additions and 240 deletions

509
Cargo.lock generated

File diff suppressed because it is too large Load Diff

View File

@ -12,18 +12,18 @@ repository = "https://git.paulbsd.com/paulbsd/ipblc"
chrono = { version = "0.4", features = ["serde"] }
clap = { version = "4.5", features = ["string"] }
git-version = "0.3"
ipnet = "2.10"
ipnet = "2.11"
lazy_static = "1.5"
nix = { version = "0.29", features = ["hostname", "inotify"] }
regex = "1.11"
reqwest = { version = "0.12", default-features = false, features = ["json", "rustls-tls"] }
rustables = "0.8.5"
rustables = "0.8.6"
rustables-macros = "0.1.2"
serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0"
sd-notify = { version = "0.4" }
tokio = { version = "1.41", features = ["full", "sync"] }
tungstenite = { version = "0.24", features = ["handshake", "rustls-tls-native-roots"] }
tokio = { version = "1.43", features = ["full", "sync"] }
tungstenite = { version = "0.26", features = ["handshake", "rustls-tls-native-roots"] }
## to optimize binary size (slow compile time)
#[profile.release]

View File

@ -2,13 +2,12 @@ use crate::ip::{BlockIpData, IpData, IpEvent};
use crate::utils::{gethostname, sleep_s};
use std::{
collections::HashMap,
collections::{HashMap, HashSet},
hash::{Hash, Hasher},
path::Path,
};
use chrono::prelude::*;
use chrono::Duration;
use chrono::{prelude::*, Duration};
use clap::{Arg, ArgAction, ArgMatches, Command};
use git_version::git_version;
use ipnet::IpNet;
@ -201,7 +200,7 @@ impl Context {
.with_timezone(&chrono::Local);
let blocktime = set.blocktime;
let blocked = false;
let handle = u64::MIN;
let handle = HashSet::new();
if ipevent.mode == "file".to_string() && gethostname(true) == ipevent.hostname {
let block =
self.blocklist

View File

@ -6,9 +6,8 @@ use std::{
sync::Arc,
};
use tokio::sync::RwLock;
use rustables::{expr::*, *};
use tokio::sync::RwLock;
pub enum FwTableType {
IPv4,
@ -38,6 +37,10 @@ macro_rules! makerules {
Rule::new(&$chain)
.unwrap()
.saddr(ip.into())
.with_expr(Conntrack::new(ConntrackKey::State))
.with_expr(Bitwise::new(10u32.to_le_bytes(), 0u32.to_be_bytes()).unwrap())
.with_expr(Cmp::new(CmpOp::Neq, 0u32.to_be_bytes()))
.with_expr(Counter::default())
.drop()
.add_to_batch(&mut $batch);
};
@ -50,14 +53,14 @@ pub fn fwglobalinit(t: FwTableType, reset: bool) -> (Batch, Chain) {
match t {
FwTableType::IPv4 => {
table_name = format!("{PKG_NAME}4");
table = Table::new(ProtocolFamily::Ipv4).with_name(table_name);
table = Table::new(ProtocolFamily::Inet).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);
table = Table::new(ProtocolFamily::Inet).with_name(table_name);
chain = Chain::new(&table)
.with_policy(ChainPolicy::Accept)
.with_name(PKG_NAME);
@ -106,8 +109,10 @@ pub fn fwunblock<'a>(ip_del: &BlockIpData) -> std::result::Result<&String, error
match ip_del.ipdata.t {
4 => {
let r = Rule::new(&chain4).unwrap().with_handle(ip_del.handle);
batch4.add(&r, MsgType::Del);
for h in &ip_del.handle {
let r = Rule::new(&chain4).unwrap().with_handle(*h);
batch4.add(&r, MsgType::Del);
}
match batch4.send() {
Ok(_) => {}
Err(e) => {
@ -116,8 +121,10 @@ pub fn fwunblock<'a>(ip_del: &BlockIpData) -> std::result::Result<&String, error
}
}
6 => {
let r = Rule::new(&chain6).unwrap().with_handle(ip_del.handle);
batch6.add(&r, MsgType::Del);
for h in &ip_del.handle {
let r = Rule::new(&chain6).unwrap().with_handle(*h);
batch6.add(&r, MsgType::Del);
}
match batch6.send() {
Ok(_) => {}
Err(e) => {
@ -136,13 +143,13 @@ pub async fn get_current_rules(
fwlen: &mut usize,
) -> Result<(), Error> {
let mut ips_all_count = 0;
let tables = vec![format!("{PKG_NAME}4"), format!("{PKG_NAME}6")];
let tables: &[String] = &[format!("{PKG_NAME}4"), format!("{PKG_NAME}6")];
for table_name in tables {
let get_table = || -> Result<Option<Table>, Error> {
let tables = list_tables().unwrap();
for table in tables {
if let Some(name) = table.get_name() {
if *name == table_name {
if name == table_name {
return Ok(Some(table));
}
}
@ -170,7 +177,7 @@ pub async fn get_current_rules(
let mut ctx = { ctx.write().await };
let rules = list_rules_for_chain(&chain).unwrap().clone();
for (ip, c) in ctx.blocklist.iter_mut() {
for (ip, b) in ctx.blocklist.iter_mut() {
let ip_parsed: IpAddr = ip.parse().unwrap();
let cmprule = Rule::new(&chain).unwrap().saddr(ip_parsed).drop();
@ -185,8 +192,8 @@ pub async fn get_current_rules(
for expr in rule.get_expressions().unwrap().iter() {
if let Some(expr::ExpressionVariant::Cmp(_)) = expr.get_data() {
if gexpr == expr.clone() {
b.handle.insert(*rule.get_handle().unwrap());
ips_all_count += 1;
c.handle = *rule.get_handle().unwrap();
}
}
}

View File

@ -2,13 +2,13 @@ use crate::utils::gethostname;
use std::{
cmp::Ordering,
collections::HashSet,
fmt::{Display, Formatter},
io::{BufRead, BufReader, Read},
net::IpAddr,
};
use chrono::offset::LocalResult;
use chrono::prelude::*;
use chrono::{offset::LocalResult, prelude::*};
use ipnet::IpNet;
use lazy_static::lazy_static;
use regex::Regex;
@ -55,7 +55,7 @@ pub struct BlockIpData {
pub blocktime: i64,
pub starttime: DateTime<Local>,
pub blocked: bool,
pub handle: u64,
pub handle: HashSet<u64>,
}
#[derive(Clone, Debug, Serialize, Deserialize, Eq)]

View File

@ -9,13 +9,13 @@ use crate::websocket::{send_to_ipbl_websocket, websocketpubsub, websocketreqrep}
use std::{collections::HashMap, sync::Arc};
use chrono::prelude::*;
use chrono::prelude::{DateTime, Local};
use chrono::Duration;
use chrono::{prelude::*, Duration};
use nix::sys::inotify::{InitFlags, Inotify, InotifyEvent};
use sd_notify::*;
use tokio::sync::mpsc::{channel, Receiver, Sender};
use tokio::sync::RwLock;
use tokio::sync::{
mpsc::{channel, Receiver, Sender},
RwLock,
};
pub const PKG_NAME: &str = env!("CARGO_PKG_NAME");
const BL_CHAN_SIZE: usize = 32;

View File

@ -3,9 +3,7 @@ use crate::config::Context;
use std::{io, sync::Arc};
use serde_json;
use tokio::io::AsyncWriteExt;
use tokio::net::TcpListener;
use tokio::sync::RwLock;
use tokio::{io::AsyncWriteExt, net::TcpListener, sync::RwLock};
pub async fn apiserver(ctxarc: &Arc<RwLock<Context>>) -> io::Result<()> {
let ctxarc = ctxarc.clone();

View File

@ -2,8 +2,7 @@ use crate::config::{httpclient, Context};
use crate::ip::{IpData, IpEvent};
use crate::utils::sleep_s;
use reqwest::Client;
use reqwest::Error as ReqError;
use reqwest::{Client, Error as ReqError};
const MAX_FAILED_API_RATE: u64 = 10;

View File

@ -9,10 +9,8 @@ use std::{
};
use serde_json::json;
use tokio::sync::mpsc::Sender;
use tokio::sync::RwLock;
use tungstenite::stream::*;
use tungstenite::*;
use tokio::sync::{mpsc::Sender, RwLock};
use tungstenite::{stream::*, *};
pub async fn websocketreqrep(
ctxarc: &Arc<RwLock<Context>>,
@ -102,7 +100,7 @@ pub async fn websocketconnect<'a>(
}
println!("connected to {endpoint}");
let msg = json!({ "hostname": hostname });
socket.send(Message::Text(msg.to_string())).unwrap();
socket.send(Message::Text(msg.to_string().into())).unwrap();
Ok(socket)
}
@ -113,7 +111,7 @@ pub async fn send_to_ipbl_websocket(
let msg = format!("{val}", val = serde_json::to_string(&ip).unwrap());
if ws.can_write() {
match ws.send(Message::Text(msg)) {
match ws.send(Message::Text(msg.into())) {
Ok(_) => {}
Err(e) => {
println!("err send read: {e:?}");