misc updates for ipblc #6

Merged
paulbsd merged 5 commits from develop into master 2023-11-02 11:29:49 +01:00
8 changed files with 112 additions and 122 deletions
Showing only changes of commit 6e0dc256b0 - Show all commits

84
Cargo.lock generated
View File

@ -122,6 +122,12 @@ version = "1.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
[[package]]
name = "bitflags"
version = "2.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "327762f6e5a765692301e5bb513e0d9fef63be86bbc14528052b1cd3e6f03e07"
[[package]]
name = "block-buffer"
version = "0.10.4"
@ -537,7 +543,7 @@ dependencies = [
[[package]]
name = "ipblc"
version = "1.2.2"
version = "1.3.0"
dependencies = [
"chrono",
"clap",
@ -569,9 +575,9 @@ checksum = "af150ab688ff2122fcef229be89cb50dd66af9e01a4ff320cc137eecc9bacc38"
[[package]]
name = "js-sys"
version = "0.3.64"
version = "0.3.65"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c5f195fe497f702db0f318b07fdd68edb16955aed830df8363d837542f8f935a"
checksum = "54c0c35952f67de54bb584e9fd912b3023117cbafc0a77d8f3dee1fb5f572fe8"
dependencies = [
"wasm-bindgen",
]
@ -610,15 +616,6 @@ version = "2.6.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f665ee40bc4a3c5590afb1e9677db74a508659dfd71e126420da8274909a0167"
[[package]]
name = "memoffset"
version = "0.7.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5de893c32cde5f383baa4c04c5d6dbdd735cfd4a794b0debdb2bb1b421da5ff4"
dependencies = [
"autocfg",
]
[[package]]
name = "mime"
version = "0.3.17"
@ -672,7 +669,7 @@ version = "0.6.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e9201688bd0bc571dfa4c21ce0a525480c8b782776cf88e12571fa89108dd920"
dependencies = [
"bitflags",
"bitflags 1.3.2",
"err-derive",
"log",
"nftnl-sys",
@ -691,15 +688,13 @@ dependencies = [
[[package]]
name = "nix"
version = "0.26.4"
version = "0.27.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "598beaf3cc6fdd9a5dfb1630c2800c7acd31df7aaf0f565796fba2b53ca1af1b"
checksum = "2eb04e9c688eff1c89d72b407f168cf79bb9e867a9d3323ed6c01519eb9cc053"
dependencies = [
"bitflags",
"bitflags 2.4.1",
"cfg-if",
"libc",
"memoffset",
"pin-utils",
]
[[package]]
@ -879,7 +874,7 @@ version = "0.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4722d768eff46b75989dd134e5c353f0d6296e5aaa3132e776cbdb56be7731aa"
dependencies = [
"bitflags",
"bitflags 1.3.2",
]
[[package]]
@ -1057,7 +1052,7 @@ version = "2.9.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "05b64fb303737d99b81884b2c63433e9ae28abebe5eb5045dcdd175dc2ecf4de"
dependencies = [
"bitflags",
"bitflags 1.3.2",
"core-foundation",
"core-foundation-sys",
"libc",
@ -1096,9 +1091,9 @@ dependencies = [
[[package]]
name = "serde_json"
version = "1.0.107"
version = "1.0.108"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6b420ce6e3d8bd882e9b243c6eed35dbc9a6110c9769e74b584e0d68d1f20c65"
checksum = "3d1c7e3eac408d115102c4c24ad393e0821bb3a5df4d506a80f85f7a742a526b"
dependencies = [
"itoa",
"ryu",
@ -1224,7 +1219,7 @@ version = "0.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ba3a3adc5c275d719af8cb4272ea1c4a6d668a777f37e115f6d11ddbc1c8e0e7"
dependencies = [
"bitflags",
"bitflags 1.3.2",
"core-foundation",
"system-configuration-sys",
]
@ -1361,9 +1356,9 @@ checksum = "3528ecfd12c466c6f163363caf2d02a71161dd5e1cc6ae7b34207ea2d42d81ed"
[[package]]
name = "tungstenite"
version = "0.19.0"
version = "0.20.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "15fba1a6d6bb030745759a9a2a588bfe8490fc8b4751a277db3a0be1c9ebbf67"
checksum = "9e3dac10fd62eaf6617d3a904ae222845979aec67c615d1c842b4002c7666fb9"
dependencies = [
"byteorder",
"bytes",
@ -1378,7 +1373,6 @@ dependencies = [
"thiserror",
"url",
"utf-8",
"webpki",
]
[[package]]
@ -1466,9 +1460,9 @@ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
[[package]]
name = "wasm-bindgen"
version = "0.2.87"
version = "0.2.88"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7706a72ab36d8cb1f80ffbf0e071533974a60d0a308d01a5d0375bf60499a342"
checksum = "7daec296f25a1bae309c0cd5c29c4b260e510e6d813c286b19eaadf409d40fce"
dependencies = [
"cfg-if",
"wasm-bindgen-macro",
@ -1476,9 +1470,9 @@ dependencies = [
[[package]]
name = "wasm-bindgen-backend"
version = "0.2.87"
version = "0.2.88"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5ef2b6d3c510e9625e5fe6f509ab07d66a760f0885d858736483c32ed7809abd"
checksum = "e397f4664c0e4e428e8313a469aaa58310d302159845980fd23b0f22a847f217"
dependencies = [
"bumpalo",
"log",
@ -1491,9 +1485,9 @@ dependencies = [
[[package]]
name = "wasm-bindgen-futures"
version = "0.4.37"
version = "0.4.38"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c02dbc21516f9f1f04f187958890d7e6026df8d16540b7ad9492bc34a67cea03"
checksum = "9afec9963e3d0994cac82455b2b3502b81a7f40f9a0d32181f7528d9f4b43e02"
dependencies = [
"cfg-if",
"js-sys",
@ -1503,9 +1497,9 @@ dependencies = [
[[package]]
name = "wasm-bindgen-macro"
version = "0.2.87"
version = "0.2.88"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dee495e55982a3bd48105a7b947fd2a9b4a8ae3010041b9e0faab3f9cd028f1d"
checksum = "5961017b3b08ad5f3fe39f1e79877f8ee7c23c5e5fd5eb80de95abc41f1f16b2"
dependencies = [
"quote",
"wasm-bindgen-macro-support",
@ -1513,9 +1507,9 @@ dependencies = [
[[package]]
name = "wasm-bindgen-macro-support"
version = "0.2.87"
version = "0.2.88"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "54681b18a46765f095758388f2d0cf16eb8d4169b639ab575a8f5693af210c7b"
checksum = "c5353b8dab669f5e10f5bd76df26a9360c748f054f862ff5f3f8aae0c7fb3907"
dependencies = [
"proc-macro2",
"quote",
@ -1526,30 +1520,20 @@ dependencies = [
[[package]]
name = "wasm-bindgen-shared"
version = "0.2.87"
version = "0.2.88"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ca6ad05a4870b2bf5fe995117d3728437bd27d7cd5f06f13c17443ef369775a1"
checksum = "0d046c5d029ba91a1ed14da14dca44b68bf2f124cfbaf741c54151fdb3e0750b"
[[package]]
name = "web-sys"
version = "0.3.64"
version = "0.3.65"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9b85cbef8c220a6abc02aefd892dfc0fc23afb1c6a426316ec33253a3877249b"
checksum = "5db499c5f66323272151db0e666cd34f78617522fb0c1604d31a27c50c206a85"
dependencies = [
"js-sys",
"wasm-bindgen",
]
[[package]]
name = "webpki"
version = "0.22.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ed63aea5ce73d0ff405984102c42de94fc55a6b75765d621c65262469b3c9b53"
dependencies = [
"ring",
"untrusted",
]
[[package]]
name = "webpki-roots"
version = "0.25.2"

View File

@ -1,6 +1,6 @@
[package]
name = "ipblc"
version = "1.2.2"
version = "1.3.0"
edition = "2021"
authors = ["PaulBSD <paul@paulbsd.com>"]
description = "ipblc is a tool that search and send attacking ip addresses to ipbl"
@ -10,19 +10,19 @@ repository = "https://git.paulbsd.com/paulbsd/ipblc"
[dependencies]
chrono = { version = "0.4", features = ["serde"] }
clap = { version = "4.2", features = ["string"] }
clap = { version = "4.4", features = ["string"] }
git-version = "0.3"
ipnet = "2.7"
ipnet = "2.9"
lazy_static = "1.4"
mnl = "0.2"
nftnl = "0.6"
nix = "0.26"
regex = "1.8"
reqwest = { version = "0.11", default-features = false, features = ["json","rustls-tls"] }
nix = { version = "0.27", features = ["hostname", "inotify"] }
regex = "1.10"
reqwest = { version = "0.11", default-features = false, features = ["json", "rustls-tls"] }
serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0"
tokio = { version = "1.28", features = ["full", "sync"] }
tungstenite = { version = "0.19", features = ["handshake","rustls-tls-native-roots"] }
tokio = { version = "1.33", features = ["full", "sync"] }
tungstenite = { version = "0.20", features = ["handshake", "rustls-tls-native-roots"] }
## to optimize binary size (slow compile time)
#[profile.release]

View File

@ -6,7 +6,7 @@ use chrono::Duration;
use clap::{Arg, ArgAction, ArgMatches, Command};
use git_version::git_version;
use ipnet::IpNet;
use nix::sys::inotify::{AddWatchFlags, InitFlags, Inotify, WatchDescriptor};
use nix::sys::inotify::{AddWatchFlags, Inotify, WatchDescriptor};
use regex::Regex;
use reqwest::{Client, Error as ReqError, Response};
use serde::{Deserialize, Serialize};
@ -20,13 +20,12 @@ const WSSUBSCRIPTION: &str = "ipbl";
const CONFIG_RETRY: u64 = 1;
const WEB_CLIENT_TIMEOUT: i64 = 5;
#[derive(Debug, Clone)]
#[derive(Debug)]
pub struct Context {
pub blocklist: HashMap<String, BlockIpData>,
pub cfg: Config,
pub discovery: Discovery,
pub flags: Flags,
pub instance: Box<Inotify>,
pub sas: HashMap<String, SetMap>,
pub hashwd: HashMap<String, WatchDescriptor>,
}
@ -48,7 +47,7 @@ pub struct Flags {
}
impl Context {
pub async fn new() -> Self {
pub async fn new(inotify: &Inotify) -> Self {
// Get flags
let argp: ArgMatches = Context::argparse();
let debug: bool = argp.get_one::<bool>("debug").unwrap().to_owned();
@ -63,13 +62,12 @@ impl Context {
urls: HashMap::new(),
},
sas: HashMap::new(),
instance: Box::new(Inotify::init(InitFlags::empty()).unwrap()),
blocklist: HashMap::new(),
hashwd: HashMap::new(),
};
print!("Loading config ... ");
ctx.load().await.unwrap();
ctx.load(&inotify).await.unwrap();
ctx
}
@ -113,7 +111,7 @@ impl Context {
Ok(data)
}
pub async fn load(&mut self) -> Result<(), Box<dyn std::error::Error>> {
pub async fn load(&mut self, inotify: &Inotify) -> Result<(), Box<dyn std::error::Error>> {
if cfg!(test) {
return Ok(());
}
@ -137,7 +135,7 @@ impl Context {
if last_in_err {
println!("creating sas");
}
self.create_sas().await?;
self.create_sas(&inotify).await?;
if last_in_err {
println!("created sas");
}
@ -153,9 +151,9 @@ impl Context {
res
}
pub async fn get_blocklist_toblock(&mut self) -> Vec<IpData> {
pub async fn get_blocklist_toblock(&self) -> Vec<IpData> {
let mut res: Vec<IpData> = vec![];
for (_, block) in self.blocklist.iter_mut() {
for (_, block) in self.blocklist.iter() {
match self.cfg.sets.get(&block.ipdata.src) {
Some(set) => {
if block.tryfail >= set.tryfail {
@ -228,15 +226,17 @@ impl Context {
removed
}
pub async fn create_sas(&mut self) -> Result<(), Box<dyn std::error::Error>> {
pub async fn create_sas(
&mut self,
inotify: &Inotify,
) -> Result<(), Box<dyn std::error::Error>> {
for (src, set) in self.cfg.sets.iter() {
let p = Path::new(set.path.as_str());
if p.is_dir() {
let wd = match self.hashwd.get(&set.path.to_string()) {
Some(wd) => *wd,
None => {
let res = self
.instance
let res = inotify
.add_watch(set.path.as_str(), AddWatchFlags::IN_MODIFY)
.unwrap();
self.hashwd.insert(set.path.to_string(), res);
@ -559,10 +559,12 @@ impl Hash for Set {
mod test {
use super::*;
use crate::ip::*;
use nix::sys::inotify::InitFlags;
use Context;
pub async fn prepare_test_data() -> Context {
let mut ctx = Context::new().await;
let inotify = Inotify::init(InitFlags::empty()).unwrap();
let mut ctx = Context::new(&inotify).await;
let now: DateTime<Local> = Local::now().trunc_subsecs(0);
ctx.blocklist = HashMap::new();

View File

@ -8,31 +8,35 @@ use std::{
net::{Ipv4Addr, Ipv6Addr},
};
pub fn fwinit(t: isize) -> (Batch, Table) {
pub enum FwTableType {
IPv4,
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))
}
fn fwinit(t: FwTableType) -> (Batch, Table) {
let table_name: String;
let table: Table;
match t {
4 => {
table_name = format!("{PKG_NAME}{t}");
table = Table::new(
&CString::new(format!("{table_name}")).unwrap(),
ProtoFamily::Ipv4,
);
}
6 => {
table_name = format!("{PKG_NAME}{t}");
table = Table::new(
&CString::new(format!("{table_name}")).unwrap(),
ProtoFamily::Ipv6,
);
}
_ => {
FwTableType::IPv4 => {
table_name = format!("{PKG_NAME}4");
table = Table::new(
&CString::new(format!("{table_name}")).unwrap(),
ProtoFamily::Ipv4,
);
}
FwTableType::IPv6 => {
table_name = format!("{PKG_NAME}6");
table = Table::new(
&CString::new(format!("{table_name}")).unwrap(),
ProtoFamily::Ipv6,
);
}
}
let mut batch = Batch::new();
@ -48,8 +52,7 @@ pub fn fwblock(
ret: &mut Vec<String>,
fwlen: &mut usize,
) -> std::result::Result<(), Error> {
let (mut batch4, table4) = fwinit(4);
let (mut batch6, table6) = fwinit(6);
let ((mut batch4, table4), (mut batch6, table6)) = fwglobalinit();
// build chain for ipv4
let mut chain4 = Chain::new(&CString::new(PKG_NAME).unwrap(), &table4);

View File

@ -174,7 +174,7 @@ fn parse_date(input: regex::Captures) -> DateTime<Local> {
match Local.with_ymd_and_hms(ymd[0] as i32, ymd[1], ymd[2], hms[0], hms[1], hms[2]) {
LocalResult::Single(s) => s,
LocalResult::Ambiguous(a, _b) => a,
LocalResult::None => Local::now(),
LocalResult::None => Local::now().trunc_subsecs(0),
};
date
}

View File

@ -1,5 +1,5 @@
use crate::config::{Context, GIT_VERSION};
use crate::fw::{fwblock, fwinit};
use crate::fw::{fwblock, fwglobalinit};
use crate::ip::{filter, IpData, IpEvent};
use crate::ipevent;
use crate::monitoring::apiserver;
@ -10,7 +10,7 @@ use crate::websocket::{send_to_ipbl_websocket, websocketpubsub, websocketreqrep}
use chrono::prelude::*;
use chrono::prelude::{DateTime, Local};
use chrono::Duration;
use nix::sys::inotify::InotifyEvent;
use nix::sys::inotify::{InitFlags, Inotify, InotifyEvent};
use std::collections::HashMap;
use std::sync::Arc;
use tokio::sync::mpsc::{channel, Receiver, Sender};
@ -22,16 +22,17 @@ const WS_CHAN_SIZE: usize = 64;
const LOOP_MAX_WAIT: u64 = 5;
pub async fn run() {
let globalctx = Context::new().await;
let inotify = Inotify::init(InitFlags::empty()).unwrap();
let globalctx = Context::new(&inotify).await;
let ctxarc = Arc::new(RwLock::new(globalctx));
let mut fwlen: usize = 0;
let pkgversion = format!("{}@{}", env!("CARGO_PKG_VERSION"), GIT_VERSION);
let mut last_cfg_reload: DateTime<Local> = Local::now().trunc_subsecs(0);
println!("Launching {}, version {}", PKG_NAME, pkgversion);
fwinit(4);
fwinit(6);
fwglobalinit();
let ctxapi = Arc::clone(&ctxarc);
apiserver(&ctxapi).await.unwrap();
@ -49,7 +50,9 @@ pub async fn run() {
let mut wssocketrr = websocketreqrep(&ctxwsrr).await;
// init file watcher
let mut blrx = watchfiles(&ctxarc).await;
let inoarc = Arc::new(RwLock::new(inotify));
let inoclone = Arc::clone(&inoarc);
let mut blrx = watchfiles(inoclone).await;
let ctxclone = Arc::clone(&ctxarc);
let ipeventclone = Arc::clone(&ipeventtxarc);
@ -68,7 +71,7 @@ pub async fn run() {
let (toblock,server);
{
let mut ctx = ctxclone.write().await;
let ctx = ctxclone.read().await;
toblock = ctx.get_blocklist_toblock().await;
server = ctx.flags.server.clone();
}
@ -117,15 +120,21 @@ pub async fn run() {
}
let ctxclone = Arc::clone(&ctxarc);
handle_cfg_reload(&ctxclone, &mut last_cfg_reload).await;
let inoclone = Arc::clone(&inoarc);
handle_cfg_reload(&ctxclone, &mut last_cfg_reload, inoclone).await;
}
}
async fn handle_cfg_reload(ctxclone: &Arc<RwLock<Context>>, last_cfg_reload: &mut DateTime<Local>) {
async fn handle_cfg_reload(
ctxclone: &Arc<RwLock<Context>>,
last_cfg_reload: &mut DateTime<Local>,
inoarc: Arc<RwLock<Inotify>>,
) {
let now_cfg_reload = Local::now().trunc_subsecs(0);
if (now_cfg_reload - *last_cfg_reload) > Duration::seconds(LOOP_MAX_WAIT as i64) {
let mut ctx = ctxclone.write().await;
match ctx.load().await {
let inotify = inoarc.read().await;
match ctx.load(&inotify).await {
Ok(_) => {
*last_cfg_reload = Local::now().trunc_subsecs(0);
}
@ -137,9 +146,12 @@ async fn handle_cfg_reload(ctxclone: &Arc<RwLock<Context>>, last_cfg_reload: &mu
}
async fn handle_fwblock(ctxclone: Arc<RwLock<Context>>, ret: &mut Vec<String>, fwlen: &mut usize) {
let toblock = {
{
let mut ctx = ctxclone.write().await;
ctx.gc_blocklist().await;
}
let toblock = {
let ctx = ctxclone.read().await;
ctx.get_blocklist_toblock().await
};
@ -152,19 +164,11 @@ async fn handle_fwblock(ctxclone: Arc<RwLock<Context>>, ret: &mut Vec<String>, f
};
}
async fn watchfiles(ctxarc: &Arc<RwLock<Context>>) -> Receiver<FileEvent> {
async fn watchfiles(inoarc: Arc<RwLock<Inotify>>) -> Receiver<FileEvent> {
let (bltx, blrx): (Sender<FileEvent>, Receiver<FileEvent>) = channel(BL_CHAN_SIZE);
let ctxclone = Arc::clone(ctxarc);
tokio::spawn(async move {
loop {
let events;
let instance;
{
let ctx = ctxclone.read().await;
instance = ctx.instance.clone();
}
events = instance.read_events().unwrap();
let events = inoarc.read().await.read_events().unwrap();
for inevent in events {
let date: DateTime<Local> = Local::now().trunc_subsecs(0);
@ -201,7 +205,7 @@ async fn compare_files_changes(
let sas;
{
let ctx = ctxarc.read().await;
sas = ctx.clone().sas;
sas = ctx.sas.clone();
sask = sas.keys();
tnets = ctx.cfg.build_trustnets();
}
@ -251,7 +255,7 @@ async fn compare_files_changes(
}
for ip in iplist {
let ipe = ipevent!("add", "file", gethostname(true), ip);
let ipetx = ipeventtx.write().await;
let ipetx = ipeventtx.read().await;
ipetx.send(ipe).await.unwrap();
}
}

View File

@ -22,7 +22,6 @@ pub async fn apiserver(ctxarc: &Arc<RwLock<Context>>) -> io::Result<()> {
tokio::spawn(async move {
loop {
//apitx.send(String::from("")).await.unwrap();
match listener.accept().await {
Ok((stream, _addr)) => {
//let mut buf = [0; 1024];

View File

@ -41,7 +41,7 @@ pub async fn websocketpubsub(
tokio::spawn(async move {
loop {
let mut ws = websocket.write().await;
match ws.read_message() {
match ws.read() {
Ok(msg) => {
let tosend: IpEvent = match serde_json::from_str(msg.to_string().as_str()) {
Ok(o) => o,
@ -52,7 +52,7 @@ pub async fn websocketpubsub(
if tosend.ipdata.hostname != gethostname(true)
|| tosend.msgtype == "init".to_string()
{
let txps = txpubsub.write().await;
let txps = txpubsub.read().await;
txps.send(tosend).await.unwrap();
}
}
@ -90,9 +90,7 @@ pub async fn websocketconnect<'a>(
}
println!("connected to {endpoint}");
let msg = json!({ "hostname": hostname });
socket
.write_message(Message::Text(msg.to_string()))
.unwrap();
socket.send(Message::Text(msg.to_string())).unwrap();
Ok(socket)
}
@ -103,7 +101,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.write_message(Message::Text(msg)) {
match ws.send(Message::Text(msg)) {
Ok(_) => {}
Err(e) => {
println!("err send read: {e:?}");
@ -115,7 +113,7 @@ pub async fn send_to_ipbl_websocket(
};
if ws.can_read() {
match ws.read_message() {
match ws.read() {
Ok(_) => {}
Err(e) => {
println!("err send read: {e:?}");