专业编程基础技术教程

网站首页 > 基础教程 正文

rust 扫描内网ip端口(rust局域网)

ccvgpt 2025-06-12 11:12:59 基础教程 3 ℃
1,Cargo.toml
[package]
name = "ip-scan"
version = "0.1.0"
edition = "2024"

[dependencies]
clap = { version = "3.2.25", features = ["derive"] }   

2, main.rs
use clap::{App, Arg};
use std::net::{IpAddr, Ipv4Addr, SocketAddr};
use std::sync::mpsc;
use std::sync::Arc;
use std::thread;
use std::time::Duration;
use std::net::TcpStream;

fn main() {
    let matches = App::new("IP Scanner")
        .version("1.0")
        .author("Your Name")
        .about("Scans IP addresses and ports")
        .arg(
            Arg::with_name("start_ip")
                .short('s')
                .long("start")
                .value_name("START_IP")
                .help("Starting IP address")
                .takes_value(true)
                .required(true),
        )
        .arg(
            Arg::with_name("end_ip")
                .short('e')
                .long("end")
                .value_name("END_IP")
                .help("Ending IP address")
                .takes_value(true)
                .required(true),
        )
        .arg(
            Arg::with_name("start_port")
                .short('p')
                .long("port")
                .value_name("START_PORT")
                .help("Starting port (default: 1)")
                .takes_value(true),
        )
        .arg(
            Arg::with_name("end_port")
                .short('P')
                .long("ports")
                .value_name("END_PORT")
                .help("Ending port (default: 1000)")
                .takes_value(true),
        )
        .arg(
            Arg::with_name("threads")
                .short('t')
                .long("threads")
                .value_name("THREADS")
                .help("Number of threads (default: 100)")
                .takes_value(true),
        )
        .get_matches();

    let start_ip_str = matches.value_of("start_ip").unwrap();
    let end_ip_str = matches.value_of("end_ip").unwrap();
    
    let start_ip = parse_ip(start_ip_str).expect("Invalid start IP address");
    let end_ip = parse_ip(end_ip_str).expect("Invalid end IP address");
    
    let start_port = matches.value_of("start_port").unwrap_or("1").parse::<u16>().expect("Invalid start port");
    let end_port = matches.value_of("end_port").unwrap_or("1000").parse::<u16>().expect("Invalid end port");
    
    let num_threads = matches.value_of("threads").unwrap_or("100").parse::<usize>().expect("Invalid thread count");

    println!("Scanning IP range: {} - {}", start_ip, end_ip);
    println!("Scanning ports: {} - {}", start_port, end_port);
    println!("Using {} threads", num_threads);

    let (tx, rx) = mpsc::channel();
    let tx = Arc::new(tx);

    let mut handles = vec![];

    // Split the port range into chunks for each thread
    let total_ports = (end_port - start_port + 1) as usize;
    let ports_per_thread = (total_ports + num_threads - 1) / num_threads;

    for thread_id in 0..num_threads {
        let tx = Arc::clone(&tx);
        let start_port_chunk = start_port + (thread_id * ports_per_thread) as u16;
        let end_port_chunk = std::cmp::min(start_port_chunk + ports_per_thread as u16 - 1, end_port);

        let handle = thread::spawn(move || {
            // Iterate over the IP range
            for ip_int in ip_to_int(start_ip)..=ip_to_int(end_ip) {
                let ip = int_to_ip(ip_int);
                
                // Scan the assigned ports for this IP
                for port in start_port_chunk..=end_port_chunk {
                    let socket_addr = SocketAddr::new(IpAddr::V4(ip), port);
                    
                    if TcpStream::connect_timeout(&socket_addr, Duration::from_secs(1)).is_ok() {
                        tx.send((ip, port)).unwrap();
                    }
                }
            }
        });

        handles.push(handle);
    }

    // Drop the original sender so the receiver knows when all threads are done
    drop(tx);

    // Collect and print the results
    let mut results = vec![];
    for (ip, port) in rx {
        results.push((ip, port));
    }

    // Wait for all threads to finish
    for handle in handles {
        handle.join().unwrap();
    }

    // Sort the results by IP and port
    results.sort_by_key(|&(ip, port)| (ip_to_int(ip), port));

    // Print the results
    println!("\nScan Results:");
    println!("=============");
    for (ip, port) in results {
        println!("{}:{} is open", ip, port);
    }
}

fn parse_ip(ip_str: &str) -> Option<Ipv4Addr> {
    ip_str.parse().ok()
}

fn ip_to_int(ip: Ipv4Addr) -> u32 {
    let octets = ip.octets();
    (octets[0] as u32) << 24 | (octets[1] as u32) << 16 | (octets[2] as u32) << 8 | (octets[3] as u32)
}

fn int_to_ip(int: u32) -> Ipv4Addr {
    Ipv4Addr::new(
        ((int >> 24) & 0xFF) as u8,
        ((int >> 16) & 0xFF) as u8,
        ((int >> 8) & 0xFF) as u8,
        (int & 0xFF) as u8,
    )
}    


3, 运行 cargo build --release
./target/release/ip-scan -s 192.168.5.110 -e 192.168.5.120 -p 80 -P 80 -t 100

  • Scanning IP range: 192.168.5.110 - 192.168.5.120
  • Scanning ports: 80 - 80
  • Using 100 threads
  • Scan Results:=============
  • 192.168.5.110:80 is open

  • rust 扫描内网ip端口(rust局域网)





    Tags:

    最近发表
    标签列表