pub mod iptables_save; pub mod login_attempt; pub mod tpc_command_server; use crate::tpc_command_server::start_tcp_command_server; use linemux::MuxedLines; use login_attempt::LoginAttempt; use std::thread; use std::{collections::HashMap, thread::sleep, time::Duration}; #[tokio::main] async fn main() -> std::io::Result<()> { let iptables = iptables::new(false).unwrap(); let mut lines = MuxedLines::new()?; lines.add_file("/host_ssh/auth.log").await?; let mut login_attempts: HashMap = HashMap::new(); let seconds_iptables = Duration::from_secs(60); println!( "starting iptables-save, run every {} seconds", seconds_iptables.as_secs() ); thread::spawn(move || loop { sleep(seconds_iptables); iptables_save::save_iptables(); println!("saved iptables rules"); }); thread::spawn(|| { start_tcp_command_server(); }); println!("listening to changes over /host_ssh/auth.log"); while let Ok(Some(line)) = lines.next_line().await { if let Some(login_attempt) = LoginAttempt::capture(line.line()) { println!( "failed login attempt from {}@{}:{}", login_attempt.user, login_attempt.ip, login_attempt.port ); match login_attempts.get_mut(&login_attempt.ip) { Some(count) => { *count += 1; if *count == 3 { match iptables.append_unique( "filter", "INPUT", &format!("--source {} -j DROP", login_attempt.ip), ) { Ok(_) => { println!("{} banned", login_attempt.ip); } Err(_) => { println!("{} already banned", login_attempt.ip); } } login_attempts.remove(&login_attempt.ip); } } None => { login_attempts.insert(login_attempt.ip.clone(), 1); } } } } Ok(()) }