From 318585481f02cf89f34c60a89e29447a49db4de7 Mon Sep 17 00:00:00 2001 From: onsali Date: Mon, 9 Dec 2024 01:47:42 -0500 Subject: [PATCH 1/2] Implemented interval function for scan interval per port --- src/input.rs | 7 +++++++ src/main.rs | 28 +++++++++++++++++---------- src/scanner/mod.rs | 47 ++++++++++++++++++++++++++++------------------ 3 files changed, 54 insertions(+), 28 deletions(-) diff --git a/src/input.rs b/src/input.rs index a38752118..de74f48aa 100644 --- a/src/input.rs +++ b/src/input.rs @@ -154,6 +154,10 @@ pub struct Opts { /// UDP scanning mode, finds UDP ports that send back responses #[arg(long)] pub udp: bool, + + /// Scan interval per port (in seconds) + #[structopt(long, default_value = "0")] + pub interval: u64, } #[cfg(not(tarpaulin_include))] @@ -242,6 +246,7 @@ impl Default for Opts { config_path: None, exclude_ports: None, udp: false, + interval: 0, } } } @@ -267,6 +272,7 @@ pub struct Config { scripts: Option, exclude_ports: Option>, udp: Option, + interval: Option, } #[cfg(not(tarpaulin_include))] @@ -341,6 +347,7 @@ mod tests { scripts: None, exclude_ports: None, udp: Some(false), + interval: None, } } } diff --git a/src/main.rs b/src/main.rs index 181831fd4..06385bc4e 100644 --- a/src/main.rs +++ b/src/main.rs @@ -88,6 +88,8 @@ fn main() { // // Added by brendanglancy - 5/19/2024: // udp is an option to do a udp scan + // Added by onsali - 09/12/2024: + // interval is an interval defined in seconds between each port scan let scanner = Scanner::new( &ips, batch_size, @@ -98,6 +100,7 @@ fn main() { opts.accessible, opts.exclude_ports.unwrap_or_default(), opts.udp, + Duration::from_secs(opts.interval), ); debug!("Scanner finished building: {:?}", scanner); @@ -200,17 +203,22 @@ fn main() { #[allow(clippy::items_after_statements, clippy::needless_raw_string_hashes)] fn print_opening(opts: &Opts) { debug!("Printing opening"); - let s = r#".----. .-. .-. .----..---. .----. .---. .--. .-. .-. -| {} }| { } |{ {__ {_ _}{ {__ / ___} / {} \ | `| | -| .-. \| {_} |.-._} } | | .-._} }\ }/ /\ \| |\ | -`-' `-'`-----'`----' `-' `----' `---' `-' `-'`-' `-' -The Modern Day Port Scanner."#; - + let s = format!( + "{}\n{}\n{}\n{}\n{}", + r#".----. .-. .-. .----..---. .----. .---. .--. .-. .-."#, + r#"| {} }| { } |{ {__ {_ _}{ {__ / ___} / {} \ | `| |"#, + r#"| .-. \| {_} |.-._} } | | .-._} }\ }/ /\ \| |\ |"#, + r#"`-' `-'`-----'`----' `-' `----' `---' `-' `-'`-' `-'"#, + r#"The Modern Day Port Scanner."# + ); println!("{}", s.gradient(Color::Green).bold()); - let info = r#"________________________________________ -: http://discord.skerritt.blog : -: https://github.com/RustScan/RustScan : - --------------------------------------"#; + let info = format!( + "{}\n{}\n{}\n{}", + r#"________________________________________"#, + r#": http://discord.skerritt.blog :"#, + r#": https://github.com/RustScan/RustScan :"#, + r#" --------------------------------------"# + ); println!("{}", info.gradient(Color::Yellow).bold()); funny_opening!(); diff --git a/src/scanner/mod.rs b/src/scanner/mod.rs index a4a0fb916..91ce05346 100644 --- a/src/scanner/mod.rs +++ b/src/scanner/mod.rs @@ -8,6 +8,7 @@ use socket_iterator::SocketIterator; use async_std::net::TcpStream; use async_std::prelude::*; +use async_std::task::sleep; use async_std::{io, net::UdpSocket}; use colored::Colorize; use futures::stream::FuturesUnordered; @@ -25,6 +26,8 @@ use std::{ /// batch_size is how many ports at a time should be scanned /// Timeout is the time RustScan should wait before declaring a port closed. As datatype Duration. /// greppable is whether or not RustScan should print things, or wait until the end to print only the ip and open ports. +/// Added by ons - 12/09/2024: +/// interval is a user defined cli flag for time between scans on each port /// Added by wasuaje - 01/26/2024: /// exclude_ports is an exclusion port list #[cfg(not(tarpaulin_include))] @@ -39,6 +42,7 @@ pub struct Scanner { accessible: bool, exclude_ports: Vec, udp: bool, + interval: Duration, } // Allowing too many arguments for clippy. @@ -54,6 +58,7 @@ impl Scanner { accessible: bool, exclude_ports: Vec, udp: bool, + interval: Duration, ) -> Self { Self { batch_size, @@ -65,6 +70,7 @@ impl Scanner { accessible, exclude_ports, udp, + interval, } } @@ -81,41 +87,46 @@ impl Scanner { .filter(|&port| !self.exclude_ports.contains(port)) .copied() .collect(); - let mut socket_iterator: SocketIterator = SocketIterator::new(&self.ips, &ports); + let mut open_sockets: Vec = Vec::new(); - let mut ftrs = FuturesUnordered::new(); let mut errors: HashSet = HashSet::new(); let udp_map = get_parsed_data(); - for _ in 0..self.batch_size { - if let Some(socket) = socket_iterator.next() { - ftrs.push(self.scan_socket(socket, udp_map.clone())); - } else { - break; - } - } - debug!("Start scanning sockets. \nBatch size {}\nNumber of ip-s {}\nNumber of ports {}\nTargets all together {} ", self.batch_size, self.ips.len(), &ports.len(), (self.ips.len() * ports.len())); - while let Some(result) = ftrs.next().await { - if let Some(socket) = socket_iterator.next() { + // Scan one port at a time + for port in ports { + let mut ftrs = FuturesUnordered::new(); + + // Scan this port across all IPs simultaneously + for ip in &self.ips { + let socket = SocketAddr::new(*ip, port); ftrs.push(self.scan_socket(socket, udp_map.clone())); } - match result { - Ok(socket) => open_sockets.push(socket), - Err(e) => { - let error_string = e.to_string(); - if errors.len() < self.ips.len() * 1000 { - errors.insert(error_string); + // Wait for all IPs to complete for this port + while let Some(result) = ftrs.next().await { + match result { + Ok(socket) => open_sockets.push(socket), + Err(e) => { + let error_string = e.to_string(); + if errors.len() < self.ips.len() * 1000 { + errors.insert(error_string); + } } } } + + // Wait for interval before moving to next port + if self.interval > Duration::from_secs(0) { + sleep(self.interval).await; + } } + debug!("Typical socket connection errors {:?}", errors); debug!("Open Sockets found: {:?}", &open_sockets); open_sockets From d4df49c66b3ffd237b9827405fe42b7386e4ccd2 Mon Sep 17 00:00:00 2001 From: onsali Date: Mon, 9 Dec 2024 01:53:12 -0500 Subject: [PATCH 2/2] Fixed formatting --- src/main.rs | 25 ++++++++++--------------- 1 file changed, 10 insertions(+), 15 deletions(-) diff --git a/src/main.rs b/src/main.rs index 06385bc4e..17654a47e 100644 --- a/src/main.rs +++ b/src/main.rs @@ -203,22 +203,17 @@ fn main() { #[allow(clippy::items_after_statements, clippy::needless_raw_string_hashes)] fn print_opening(opts: &Opts) { debug!("Printing opening"); - let s = format!( - "{}\n{}\n{}\n{}\n{}", - r#".----. .-. .-. .----..---. .----. .---. .--. .-. .-."#, - r#"| {} }| { } |{ {__ {_ _}{ {__ / ___} / {} \ | `| |"#, - r#"| .-. \| {_} |.-._} } | | .-._} }\ }/ /\ \| |\ |"#, - r#"`-' `-'`-----'`----' `-' `----' `---' `-' `-'`-' `-'"#, - r#"The Modern Day Port Scanner."# - ); + let s = r#".----. .-. .-. .----..---. .----. .---. .--. .-. .-. + | {} }| { } |{ {__ {_ _}{ {__ / ___} / {} \ | `| | + | .-. \| {_} |.-._} } | | .-._} }\ }/ /\ \| |\ | + `-' `-'`-----'`----' `-' `----' `---' `-' `-'`-' `-' + The Modern Day Port Scanner."#; + println!("{}", s.gradient(Color::Green).bold()); - let info = format!( - "{}\n{}\n{}\n{}", - r#"________________________________________"#, - r#": http://discord.skerritt.blog :"#, - r#": https://github.com/RustScan/RustScan :"#, - r#" --------------------------------------"# - ); + let info = r#"________________________________________ + : http://discord.skerritt.blog : + : https://github.com/RustScan/RustScan : + --------------------------------------"#; println!("{}", info.gradient(Color::Yellow).bold()); funny_opening!();