diff --git a/src/lib.rs b/src/lib.rs index 2ee8ef8..58940b4 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -18,15 +18,24 @@ use tower_http::{timeout::TimeoutLayer, trace::TraceLayer}; #[derive(Clone)] struct AppState { attack: Arc>, + url: String, + qps: usize, } pub struct Config { pub listen_port: u16, + pub target_url: String, + pub qps: usize, } pub async fn run(config: Config, token: CancellationToken) -> Result<(), io::Error> { + let url = config.target_url.clone(); + let qps = config.qps; + let state = AppState { attack: Arc::new(Mutex::new(true)), + url: config.target_url, + qps: config.qps, }; let attack = state.attack.clone(); @@ -41,7 +50,7 @@ pub async fn run(config: Config, token: CancellationToken) -> Result<(), io::Err )) .with_state(state); - tokio::spawn(dos(attack)); + tokio::spawn(dos(attack, url, qps)); let listener = TcpListener::bind(("0.0.0.0", config.listen_port)) .await @@ -63,21 +72,30 @@ async fn stop(State(state): State) -> impl IntoResponse { async fn reset(State(state): State) -> impl IntoResponse { let mut attack = state.attack.lock().await; + let mut reset_attack = false; + if !*attack { + reset_attack = true; + } *attack = true; + if reset_attack { + tokio::spawn(dos(state.attack.clone(), state.url, state.qps)); + } } async fn index_page(State(state): State) -> impl IntoResponse { let attack = state.attack.lock().await.clone(); - let template = IndexTemplate { attack }; + let template = IndexTemplate { + attack, + url: state.url, + qps: state.qps, + }; HtmlTemplate(template) } -async fn dos(attack: Arc>) { +async fn dos(attack: Arc>, url: String, qps: usize) { let client = reqwest::Client::new(); - let url = "https://pms.szamtech.ktk.bme.hu/en/login"; - - let state = TokenBucketState::new(100, 10, Duration::from_millis(100)); + let state = TokenBucketState::new(qps, qps / 10, Duration::from_millis(100)); let state_mutex = Arc::new(Mutex::new(state)); let mut rl = TokenBucketRateLimiter::new(state_mutex); @@ -85,6 +103,7 @@ async fn dos(attack: Arc>) { if let false = attack.lock().await.clone() { break; } + let url = url.clone(); rl.wait_with_cost(1).await; let client = client.clone(); tokio::spawn(async move { @@ -97,6 +116,8 @@ async fn dos(attack: Arc>) { #[template(path = "index.html")] struct IndexTemplate { attack: bool, + url: String, + qps: usize, } struct HtmlTemplate(T); diff --git a/src/main.rs b/src/main.rs index 743be5c..9aa36a7 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,10 +1,10 @@ +use aoszdos::Config; use core::panic; use std::str::FromStr; use std::{env, fmt::Display}; use tokio::signal::unix::{signal, SignalKind}; use tokio_util::sync::CancellationToken; use tracing_subscriber::{fmt, prelude::*, EnvFilter}; -use aoszdos::Config; #[tokio::main] async fn main() -> Result<(), String> { @@ -32,6 +32,8 @@ async fn main() -> Result<(), String> { // Parse environment variables and create a Config struct let config = Config { listen_port: parse_env("LISTEN_PORT", 8080), + target_url: parse_env("TARGET_URL", String::from("localhost")), + qps: parse_env("TARGET_QPS", 100), }; let (Ok(mut sigterm), Ok(mut sigint)) = ( diff --git a/templates/index.html b/templates/index.html index 974b064..ebb939f 100644 --- a/templates/index.html +++ b/templates/index.html @@ -1,80 +1,210 @@ - + - - -Attack Status - - - + 0 0 20px #ff2e2e, + 0 0 50px #ff0000, + 0 10px 20px rgba(0, 0, 0, 0.6); + font-size: 2.4rem; + font-weight: bold; + color: #fff; + cursor: pointer; + display: none; + transition: all 0.15s ease-in-out; + position: relative; + margin-top: 35px; + } -
- + #stopBtn::before { + content: ""; + position: absolute; + top: 10px; + left: 50px; + width: 60px; + height: 60px; + background: rgba(255, 255, 255, 0.25); + border-radius: 50%; + filter: blur(12px); + } - + const message = document.getElementById("message"); + const stopBtn = document.getElementById("stopBtn"); - + const infoPanel = document.getElementById("infoPanel"); + const targetSpan = document.getElementById("targetSpan"); + const qpsSpan = document.getElementById("qpsSpan"); + + const green = () => { + document.body.style.backgroundColor = "#004d00"; + message.innerHTML = "🎄✨ Sikeresen megallitottatok Gr(F)inch-et ✨🎄"; + message.classList.remove("alertShimmer"); + stopBtn.style.display = "none"; + infoPanel.style.display = "none"; + }; + + stopBtn.onclick = async () => { + await fetch("/stop"); + green(); + }; + + if (attack) { + document.body.style.backgroundColor = "#3b0000"; + message.textContent = "⚠️ Gr(F)inch anti-Karacsony DoS tamadas aktiv... ⚠️"; + message.classList.add("alertShimmer"); + + // print target & qps + targetSpan.textContent = target; + qpsSpan.textContent = qps; + + infoPanel.style.display = "block"; + stopBtn.style.display = "inline-block"; + } else { + green(); + } + +