html terminal
alerts
bendn 2024-02-01
parent e27033d · commit e87db5c
-rw-r--r--.gitignore1
-rw-r--r--src/alerts.rs73
-rw-r--r--src/main.rs3
-rw-r--r--src/server.rs2
-rw-r--r--src/webhook.rs2
5 files changed, 79 insertions, 2 deletions
diff --git a/.gitignore b/.gitignore
index 544ef74..8678e56 100644
--- a/.gitignore
+++ b/.gitignore
@@ -5,3 +5,4 @@ html/
**.vd
Cargo.lock
webhook
+aook
diff --git a/src/alerts.rs b/src/alerts.rs
new file mode 100644
index 0000000..a16ba0e
--- /dev/null
+++ b/src/alerts.rs
@@ -0,0 +1,73 @@
+use emoji::named::*;
+use regex::Regex;
+use std::{
+ sync::{
+ atomic::{
+ AtomicU64,
+ Ordering::{Acquire, Relaxed},
+ },
+ LazyLock,
+ },
+ time::Duration,
+};
+use tokio::{
+ io::{AsyncBufReadExt, AsyncReadExt},
+ sync::broadcast::error::TryRecvError,
+};
+pub async fn run() {
+ let (tx, mut rx) = tokio::sync::broadcast::channel::<u64>(10);
+ static COUNT: AtomicU64 = AtomicU64::new(0);
+ let mut f =
+ tokio::io::BufReader::new(tokio::fs::File::open("/var/log/kern.log").await.unwrap());
+ let mut buf = [0; 1 << 20];
+ while f.read(&mut buf).await.unwrap() != 0 {}
+ static RE: LazyLock<Regex> = LazyLock::new(|| {
+ Regex::new("[^ ]+ [0-9]+ [0-9]+:[0-9]+:[0-9]+ .+ kernel: [[0-9]+.[0-9]+] IN=.+ OUT= MAC=.+ SRC=([0-9]+.[0-9]+.[0-9]+.[0-9]+) DST=[0-9]+.[0-9]+.[0-9]+.[0-9]+ LEN=[0-9]+ TOS=0x[0-9a-f]+ PREC=0x[0-9a-f]+ TTL=[0-9]+ ID=[0-9]+(?: DF)? PROTO=TCP SPT=[0-9]+ DPT=[0-9]+ WINDOW=[0-9]+ RES=0x[a-f0-9]+ SYN URGP=[0-9]").unwrap()
+ });
+ tokio::spawn(async move {
+ loop {
+ let mut s = String::new();
+ f.read_line(&mut s).await.unwrap();
+ if RE.is_match(&s) {
+ COUNT.fetch_add(1, Relaxed);
+ }
+ tokio::time::sleep(tokio::time::Duration::from_millis(5)).await;
+ }
+ });
+ tokio::spawn(async move {
+ let mut alarmed = tokio::time::Instant::now() - Duration::from_secs(5 * 60);
+ loop {
+ let before = COUNT.load(Acquire);
+ tokio::time::sleep(tokio::time::Duration::from_secs(5)).await;
+ let after = COUNT.load(Acquire);
+ let δ = after - before;
+ let now = tokio::time::Instant::now();
+ if δ > 10 && alarmed < now - Duration::from_secs(5 * 60) {
+ alarmed = now;
+ tx.send((δ + 1) / 5).unwrap();
+ }
+ }
+ });
+ let http = serenity::http::Http::new("");
+ let wh =
+ std::env::var("AOOK").unwrap_or(std::fs::read_to_string("aook").expect("wher webhook"));
+ let wh = crate::webhook::Webhook::new(&http, &wh).await;
+ loop {
+ match rx.try_recv() {
+ Ok(x) => {
+ wh.send(|m| {
+ m.content(&format!(
+ "{WARNING} <@&1202414272030974033> attacked by {x} bots/s"
+ ))
+ })
+ .await;
+ }
+ Err(TryRecvError::Closed) => panic!(),
+ Err(TryRecvError::Lagged(_)) => continue,
+ Err(TryRecvError::Empty) => {
+ tokio::time::sleep(Duration::from_secs(4)).await;
+ continue;
+ }
+ }
+ }
+}
diff --git a/src/main.rs b/src/main.rs
index a954441..a05b28c 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -1,7 +1,9 @@
#![feature(lazy_cell, let_chains, iter_intersperse)]
+#![allow(mixed_script_confusables)]
use std::str::FromStr;
#[macro_use]
mod logging;
+mod alerts;
mod bot;
mod process;
mod server;
@@ -12,6 +14,7 @@ use std::net::SocketAddr;
#[tokio::main(flavor = "current_thread")]
async fn main() {
+ tokio::spawn(alerts::run());
Server::spawn(SocketAddr::from((
[0, 0, 0, 0],
std::env::var("PORT").map_or(4001, |x| u16::from_str(&x).unwrap()),
diff --git a/src/server.rs b/src/server.rs
index e12b7cc..a823311 100644
--- a/src/server.rs
+++ b/src/server.rs
@@ -75,7 +75,7 @@ async fn map_file(
pub struct Server;
impl Server {
pub async fn spawn(addr: SocketAddr) {
- let (stdin_tx, stdin) = broadcast::channel(2);
+ let (stdin_tx, stdin) = broadcast::channel(8);
let state = Arc::new(State::new(stdin_tx));
let router = Router::new()
.route("/", html!(index))
diff --git a/src/webhook.rs b/src/webhook.rs
index c67b93d..ea2c320 100644
--- a/src/webhook.rs
+++ b/src/webhook.rs
@@ -28,7 +28,7 @@ impl<'a> Webhook<'a> {
}
}
- async fn send<F>(&self, block: F)
+ pub async fn send<F>(&self, block: F)
where
for<'b> F: FnOnce(ExecuteWebhook) -> ExecuteWebhook,
{