use { std::collections::HashMap, std::fs::File, std::io::{BufRead, BufReader}, pushover::API, pushover::requests::message::SendMessage, chrono::Local, uuid::Uuid, }; fn main() -> std::io::Result<()> { let date = Local::now().format("%Y-%m-%d").to_string(); let log_path = "/var/log/kern.log"; let file = File::open(log_path)?; let reader = BufReader::new(file); let mut lines = Vec::new(); let mut ip_count: HashMap = HashMap::new(); let mut proto_count: HashMap = HashMap::new(); let mut port_count: HashMap = HashMap::new(); let mut total_count: u32 = 0; let mut total_bytes: u64 = 0; for line in reader.lines() { let line = line?; if !line.contains("IPTables-In") { continue; } for part in line.split_whitespace() { lines.push(line.clone()); if part.starts_with("SRC=") { let ip = part.trim_start_matches("SRC=").to_string(); *ip_count.entry(ip).or_insert(0) += 1; } if part.starts_with("PROTO=") { let proto = part.trim_start_matches("PROTO=").to_string(); *proto_count.entry(proto).or_insert(0) += 1; } if part.starts_with("DPT=") { let port = part.trim_start_matches("DPT=").to_string(); *port_count.entry(port).or_insert(0) += 1; } if part.starts_with("LEN=") { total_count += 1; if let Ok(len) = part.trim_start_matches("LEN=").parse::() { total_bytes += len; } } } } generate_summary(ip_count.clone(), total_bytes); generate_log(date, ip_count, proto_count, port_count, total_count, total_bytes, lines); Ok(()) } fn send_message(message: String) { let api = API::new(); //very bad practice to hardcode keys, but eh let user_key = "u7mwq3g4rpg26bd4rzcbq3khta9zsi"; let token = "aeasowifnfwzwgkw4h2ararzu2fp84"; let msg = SendMessage::new(token, user_key, message); let _ = api.send(&msg); } fn generate_summary(ip_count: HashMap, total_bytes: u64) { // pushover message summary // Convert the map into a vector so we can sort by count. let mut counts: Vec<(String, u32)> = ip_count.into_iter().collect(); counts.sort_by(|a, b| b.1.cmp(&a.1)); let top_ips: Vec<_> = counts.into_iter().take(5).collect(); let summary = format!( "Top IPs:\n{:#?}\n\ Total MegaBytes: {}\n", top_ips, total_bytes/1024/1024); send_message(summary); } fn generate_log(date: String, ip_count: HashMap, proto_count: HashMap, port_count: HashMap, total_count: u32, total_bytes: u64, lines: Vec) { // full log of packets, file output let uuid = Uuid::new_v4(); let filename = format!("/etc/nginx/logr/{}.html", uuid); let mut file = File::create(&filename).expect("Unable to create file"); use std::io::Write; writeln!(file, "Log Report for {}", date).unwrap(); writeln!(file, "

Log Report for {}

", date).unwrap(); writeln!(file, "

Total Packets: {}

", total_count).unwrap(); writeln!(file, "

Total Bytes: {}

", total_bytes).unwrap(); writeln!(file, "

IP Counts

    ").unwrap(); let mut ip_counts: Vec<(String, u32)> = ip_count.into_iter().collect(); ip_counts.sort_by(|a, b| b.1.cmp(&a.1)); for (ip, count) in ip_counts { writeln!(file, "
  • {}: {}
  • ", ip, count).unwrap(); } writeln!(file, "
").unwrap(); writeln!(file, "

Protocol Counts

    ").unwrap(); let mut proto_counts: Vec<(String, u32)> = proto_count.into_iter().collect(); proto_counts.sort_by(|a, b| b.1.cmp(&a.1)); for (proto, count) in proto_counts { writeln!(file, "
  • {}: {}
  • ", proto, count).unwrap(); } writeln!(file, "
").unwrap(); writeln!(file, "

Port Counts

    ").unwrap(); let mut port_counts: Vec<(String, u32)> = port_count.into_iter().collect(); port_counts.sort_by(|a, b| b.1.cmp(&a.1)); for (port, count) in port_counts { writeln!(file, "
  • {}: {}
  • ", port, count).unwrap(); } writeln!(file, "
").unwrap(); writeln!(file, "

Whole log: {}

", lines.join("
")).unwrap(); writeln!(file, "").unwrap(); }