Añadir src/main.rs
This commit is contained in:
parent
72ed05bfa7
commit
5ea643dd9a
147
src/main.rs
Normal file
147
src/main.rs
Normal file
@ -0,0 +1,147 @@
|
||||
use clap::Parser;
|
||||
use reqwest::Client;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::{collections::HashSet, net::Ipv4Addr, path::Path, sync::Arc};
|
||||
use tokio::{fs, sync::{Semaphore, Mutex}};
|
||||
|
||||
const MAX_CONCURRENT_SCANS: usize = 500;
|
||||
const PROGRESS_FILE: &str = "progress.json";
|
||||
const IPS_UP_FILE: &str = "ips_up.json";
|
||||
|
||||
#[derive(Parser, Debug)]
|
||||
#[command(author, version, about = "Async IP Scanner", long_about = None)]
|
||||
struct Args {
|
||||
/// IP to start scanning from
|
||||
#[arg(short, long, default_value = "0.0.0.0")]
|
||||
start: String,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
struct Progress {
|
||||
current_ip: String,
|
||||
}
|
||||
|
||||
fn increment_ip(ip: Ipv4Addr) -> Option<Ipv4Addr> {
|
||||
let mut octets = ip.octets();
|
||||
for i in (0..4).rev() {
|
||||
if octets[i] < 255 {
|
||||
octets[i] += 1;
|
||||
return Some(Ipv4Addr::from(octets));
|
||||
} else {
|
||||
octets[i] = 0;
|
||||
}
|
||||
}
|
||||
None
|
||||
}
|
||||
|
||||
async fn load_progress() -> Option<Progress> {
|
||||
if Path::new(PROGRESS_FILE).exists() {
|
||||
if let Ok(data) = fs::read_to_string(PROGRESS_FILE).await {
|
||||
if let Ok(progress) = serde_json::from_str::<Progress>(&data) {
|
||||
return Some(progress);
|
||||
}
|
||||
}
|
||||
}
|
||||
None
|
||||
}
|
||||
|
||||
async fn save_progress_background(ip: Ipv4Addr) {
|
||||
tokio::spawn(async move {
|
||||
let progress = Progress {
|
||||
current_ip: ip.to_string(),
|
||||
};
|
||||
if let Ok(data) = serde_json::to_string(&progress) {
|
||||
let _ = fs::write(PROGRESS_FILE, data).await;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
async fn load_ips_up() -> HashSet<String> {
|
||||
if Path::new(IPS_UP_FILE).exists() {
|
||||
if let Ok(data) = fs::read_to_string(IPS_UP_FILE).await {
|
||||
if let Ok(ips) = serde_json::from_str::<HashSet<String>>(&data) {
|
||||
return ips;
|
||||
}
|
||||
}
|
||||
}
|
||||
HashSet::new()
|
||||
}
|
||||
|
||||
async fn save_ips_up_background(ips: Arc<Mutex<HashSet<String>>>) {
|
||||
let ips_clone = ips.clone();
|
||||
tokio::spawn(async move {
|
||||
let lock = ips_clone.lock().await;
|
||||
if let Ok(data) = serde_json::to_string(&*lock) {
|
||||
let _ = fs::write(IPS_UP_FILE, data).await;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
async fn scan_ip(ip: String, client: Client, sem: Arc<Semaphore>, ips_up: Arc<Mutex<HashSet<String>>>) {
|
||||
let _permit = sem.acquire().await.unwrap();
|
||||
let url = format!("http://{}", ip);
|
||||
match client.get(&url).send().await {
|
||||
Ok(response) if response.status().is_success() => {
|
||||
println!("{} is UP", ip);
|
||||
let mut lock = ips_up.lock().await;
|
||||
lock.insert(ip);
|
||||
}
|
||||
Ok(response) => {
|
||||
println!("{} is DOWN (status {})", ip, response.status());
|
||||
}
|
||||
Err(err) => {
|
||||
println!("{} is DOWN (error: {})", ip, err);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[tokio::main]
|
||||
async fn main() {
|
||||
let args = Args::parse();
|
||||
|
||||
let starting_ip = args.start.parse::<Ipv4Addr>().unwrap_or(Ipv4Addr::new(0, 0, 0, 0));
|
||||
let saved_progress = load_progress().await;
|
||||
let mut current_ip = saved_progress
|
||||
.map(|p| p.current_ip.parse().unwrap_or(starting_ip))
|
||||
.unwrap_or(starting_ip);
|
||||
|
||||
let ips_up = Arc::new(Mutex::new(load_ips_up().await));
|
||||
let client = Client::builder()
|
||||
.timeout(std::time::Duration::from_secs(2))
|
||||
.build()
|
||||
.unwrap();
|
||||
let sem = Arc::new(Semaphore::new(MAX_CONCURRENT_SCANS));
|
||||
let end_ip = Ipv4Addr::new(255, 255, 255, 255);
|
||||
|
||||
while current_ip <= end_ip {
|
||||
let mut handles = vec![];
|
||||
let mut ip_batch = vec![];
|
||||
|
||||
for _ in 0..MAX_CONCURRENT_SCANS {
|
||||
ip_batch.push(current_ip);
|
||||
if let Some(next_ip) = increment_ip(current_ip) {
|
||||
current_ip = next_ip;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
for ip in &ip_batch {
|
||||
let ip_str = ip.to_string();
|
||||
let client_clone = client.clone();
|
||||
let sem_clone = sem.clone();
|
||||
let ips_clone = ips_up.clone();
|
||||
|
||||
handles.push(tokio::spawn(scan_ip(ip_str, client_clone, sem_clone, ips_clone)));
|
||||
}
|
||||
|
||||
for h in handles {
|
||||
let _ = h.await;
|
||||
}
|
||||
|
||||
save_progress_background(current_ip).await;
|
||||
save_ips_up_background(ips_up.clone()).await;
|
||||
}
|
||||
|
||||
println!("Finished scanning."); // lol, lmao even
|
||||
}
|
Loading…
Reference in New Issue
Block a user