Stash commit v2 📦

This commit is contained in:
Sivert V. Sæther 2023-01-20 20:04:02 +01:00
parent b49f55796f
commit a9e1250a77
2 changed files with 94 additions and 27 deletions

View File

@ -14,6 +14,7 @@ use log::{trace, debug, info, error};
#[command(author, version, about, long_about = None)] #[command(author, version, about, long_about = None)]
struct Args { struct Args {
/// Max worker threads to use for multi threaded operations /// Max worker threads to use for multi threaded operations
/// Minimum three during scanning
#[arg(short, long, value_parser, default_value_t = num_cpus::get())] #[arg(short, long, value_parser, default_value_t = num_cpus::get())]
threads: usize, threads: usize,
@ -76,8 +77,13 @@ fn main() -> io::Result<()> {
debug!("Mode is Scan/Recon"); debug!("Mode is Scan/Recon");
unsafe { TIMEOUT = Some(Duration::from_millis(timeout)) }; unsafe { TIMEOUT = Some(Duration::from_millis(timeout)) };
let threads = if args.threads > 3 { args.threads } else {
info!("Args.threads is < 3, setting it to three, the required minimum for scanning");
3
};
let mut scanner = Scanner::load(&args.file); let mut scanner = Scanner::load(&args.file);
get_rt("blues Scanner worker", args.threads).block_on( get_rt("blues Scanner worker", threads).block_on(
scanner.mass_scan(throttle, parallel, limit, rand)); scanner.mass_scan(throttle, parallel, limit, rand));
info!("Saving to file: {}", args.file); info!("Saving to file: {}", args.file);

View File

@ -1,7 +1,9 @@
use std::{ use std::{
collections::HashMap,
sync::{mpsc, Mutex, Arc},
time::{Duration, Instant}, time::{Duration, Instant},
net::{Ipv4Addr, IpAddr}, net::{Ipv4Addr, IpAddr},
thread::sleep, io, thread::sleep, //io,
vec::Vec}; vec::Vec};
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
@ -18,31 +20,37 @@ static PROBE: [u8; SIZE] = [0x66; SIZE];
#[derive(Clone)] #[derive(Clone)]
pub struct Scanner { pub struct Scanner {
timings: Arc<Mutex<HashMap<Ipv4Addr, Instant>>>,
// scanned: Arc<Mutex<Vec<Ipv4Addr>>>,
pub dsts: Vec<Destination>, pub dsts: Vec<Destination>,
pub dead: Vec<Ipv4Addr>, pub dead: Vec<Ipv4Addr>,
} }
#[derive(Deserialize, Serialize, Clone)] #[derive(Deserialize, Serialize, Clone)]
pub struct Destination { pub struct Destination {
pub round_trip: usize, // Round trip in ms pub round_trip: Duration,
pub small: bool, pub small: bool,
pub ip: Ipv4Addr, pub ip: Ipv4Addr,
} }
struct PingResponse { struct PingResponse {
pub round_trip: usize, pub finish: Instant,
// pub data: Vec<u8>,
pub corrupt: bool, pub corrupt: bool,
pub ip: Ipv4Addr,
pub small: bool, pub small: bool,
pub data: [u8; PACKET_SIZE],
} }
pub type PingResult = Result<PingResponse, io::Error>; //pub type PingResult = Result<PingResponse, io::Error>;
pub type ScanResult = Result<Destination, Ipv4Addr>; pub type ScanResult = Result<Destination, Ipv4Addr>;
impl Scanner { impl Scanner {
pub fn new() -> Self { pub fn new() -> Self {
debug!("Initializing a blues::Scanner"); debug!("Initializing a blues::Scanner");
Self { dsts: vec![], dead: vec![] } Self {
timings: Arc::new(Mutex::new(HashMap::new())),
dsts: vec![], dead: vec![]
}
} }
pub fn load(file: &str) -> Self { pub fn load(file: &str) -> Self {
@ -54,9 +62,9 @@ impl Scanner {
} }
#[inline] #[inline]
fn next_ip(&self) -> Ipv4Addr { fn next_ip(&mut self) -> Ipv4Addr {
let mut ip = rand_ip(); // let mut ip = rand_ip();
// let mut ip = IpAddr::V4(Ipv4Addr::new(10, 0, 0, 138)); let mut ip = Ipv4Addr::new(10, 0, 0, 138);
while self.scanned(&ip) { while self.scanned(&ip) {
ip = rand_ip(); } ip = rand_ip(); }
ip ip
@ -64,13 +72,8 @@ impl Scanner {
#[inline] #[inline]
fn scanned(&self, ip: &Ipv4Addr) -> bool { fn scanned(&self, ip: &Ipv4Addr) -> bool {
for dead in &self.dead { for scanned in self.timings.lock().unwrap().keys() {
if ip == dead { return true; } if *ip == *scanned { return true; }
}
for dst in &self.dsts {
if ip == &dst.ip {
return true;
}
} }
false false
} }
@ -79,29 +82,52 @@ impl Scanner {
info!("Starting mass scan with a limit of {} and {} to randomized IP order!", limit, rand); info!("Starting mass scan with a limit of {} and {} to randomized IP order!", limit, rand);
let duration = Duration::from_millis(throttle as u64); let duration = Duration::from_millis(throttle as u64);
let mut futs: Vec<task::JoinHandle<()>> = vec![]; let mut futs: Vec<task::JoinHandle<()>> = vec![];
let listner = task::spawn(listner()); let (tx, rx) = mpsc::channel();
let listner = task::spawn(listner(rx));
for _i in 0..limit { for _ in 0..limit {
if futs.len() >= parallel { if futs.len() >= parallel {
pop_futs(&mut futs).await; pop_futs(&mut futs).await;
} }
futs.push(task::spawn(ping(self.next_ip(), &PROBE))); let ip = self.next_ip();
futs.push(task::spawn(ping(ip, &PROBE)));
self.timings.lock().unwrap().insert(ip, Instant::now());
sleep(duration); sleep(duration);
} }
while !futs.is_empty() { pop_futs(&mut futs).await; } while !futs.is_empty() { pop_futs(&mut futs).await; }
listner.abort(); if let Err(err) = tx.send(()) {
panic!("Error sending exit signal to the listner thread: {err:?}");
};
let pings = listner.await.unwrap();
for ping in pings {
if ping.corrupt || ping.small {
self.dead.push(ping.ip);
}
let timings = self.timings.lock().unwrap();
let start = match timings.get(&ping.ip) {
None => {
error!("No timing found for IP: {}, assuming it's dead!", ping.ip);
continue
},
Some(start) => *start,
};
self.dsts.push(Destination {
round_trip: ping.finish.duration_since(start),
small: ping.small, ip: ping.ip
});
}
} }
} }
async fn pop_futs(futs: &mut Vec<task::JoinHandle<()>>) { async fn pop_futs(futs: &mut Vec<task::JoinHandle<()>>) {
futs.pop().expect("Unable to pop of futures vec during mass_scan()!").await; futs.pop().expect("Unable to pop of futures vec during mass_scan()!").await.unwrap();
} }
async fn ping(ip: Ipv4Addr, data: &[u8]) { async fn ping(ip: Ipv4Addr, data: &[u8]) {
trace!("Scanning IP \"{ip}\""); trace!("Scanning IP \"{ip}\"");
let mut pack = ICMP_PACKET.to_vec(); let mut pack = ICMP_PACKET.to_vec();
pack[4..7].copy_from_slice(&ip.octets()); pack[3..7].copy_from_slice(&ip.octets());
pack.append(&mut data.to_vec()); pack.append(&mut data.to_vec());
let checksum = checksum(&pack); let checksum = checksum(&pack);
@ -109,15 +135,16 @@ async fn ping(ip: Ipv4Addr, data: &[u8]) {
pack[3] = checksum[1]; pack[3] = checksum[1];
let mut socket = connect(IpAddr::V4(ip)); let mut socket = connect(IpAddr::V4(ip));
let start = Instant::now();
match socket.send(&pack) { match socket.send(&pack) {
Ok(size) => if size != pack.len() { debug!("Sent {size} bytes of {} bytes to {ip}", pack.len()) }, Ok(size) => if size != pack.len() { debug!("Sent {size} bytes of {} bytes to {ip}", pack.len()) },
Err(err) => debug!("Unable to ping IP {ip}: {err:?}"), Err(err) => debug!("Unable to ping IP {ip}: {err:?}"),
} }
trace!("Ping packet sent to IP \"{ip}\"");
} }
async fn listner() -> ! { async fn listner(chan: mpsc::Receiver<()>) -> Vec<PingResponse> {
trace!("Listner started");
let socket = match IcmpSocket::connect(IpAddr::V4(Ipv4Addr::new(0, 0, 0, 0))) { let socket = match IcmpSocket::connect(IpAddr::V4(Ipv4Addr::new(0, 0, 0, 0))) {
Err(err) => panic!("Unable to open listening socket: {err:?}"), Err(err) => panic!("Unable to open listening socket: {err:?}"),
Ok(sock) => sock, Ok(sock) => sock,
@ -129,11 +156,45 @@ async fn listner() -> ! {
Ok(size) => handles.push(task::spawn(handler(response, size))), Ok(size) => handles.push(task::spawn(handler(response, size))),
Err(err) => info!("Error reading a ping reply: {err:?}"), Err(err) => info!("Error reading a ping reply: {err:?}"),
} }
match chan.try_recv() {
Err(err) => match err {
mpsc::TryRecvError::Disconnected => {
error!("Listner threads message queue is disconnected!");
break
},
mpsc::TryRecvError::Empty => (),
} }
Ok(_) => break,
}
}
info!("Listner stopped");
let mut pings = vec![];
for handle in handles {
match handle.await {
Err(err) => error!("Awaiting future {err:?}"),
Ok(res) => {
pings.push(res);
},
};
}
pings
} }
async fn handler(response: [u8; PACKET_SIZE], size: usize) { async fn handler(res: [u8; PACKET_SIZE], size: usize) -> PingResponse {
todo!(); let data = res[PACKET_SIZE - SIZE..PACKET_SIZE].to_vec();
let ip = Ipv4Addr::new(res[4], res[5], res[6], res[7]);
trace!("Handling response from \"{ip}\"");
let mut corrupt = false;
let small = false;
// if size != { error!(); }
if data != PROBE {
// TODO small?
corrupt = true;
}
PingResponse {
finish: Instant::now(), corrupt, small, ip
//, data
}
} }
impl Default for Scanner { impl Default for Scanner {