rsubdomain 1.2.11

A high-performance subdomain brute-force tool written in Rust
Documentation
use clap::Parser;

use rsubdomain::{
    device, export_scan_data, print_summary_stats, print_verification_result, Opts, OutputFormat,
    SpeedTester, SubdomainBruteConfig, SubdomainBruteEngine, SubdomainScanData,
};

#[tokio::main]
async fn main() {
    let opts = Opts::parse();

    if opts.list_network {
        device::print_network_devices();
        return;
    }

    if opts.network_test {
        if let Err(error) = run_network_speed_test(&opts.target_ip).await {
            eprintln!("网速测试失败: {}", error);
        }
        return;
    }

    if let Err(error) = run_subdomain_brute(opts).await {
        eprintln!("域名暴破失败: {}", error);
    }
}

async fn run_network_speed_test(target_ip: &str) -> Result<(), Box<dyn std::error::Error>> {
    let tester = SpeedTester::new_with_target(target_ip).await?;
    let result = tester.run_speed_test(10).await;
    tester.display_result(&result);
    Ok(())
}

async fn run_subdomain_brute(opts: Opts) -> Result<(), Box<dyn std::error::Error>> {
    let engine = SubdomainBruteEngine::new(SubdomainBruteConfig {
        domains: opts.domain.clone(),
        resolvers: opts.resolvers.clone(),
        dictionary_file: opts.file.clone(),
        dictionary: None,
        skip_wildcard: opts.skip_wildcard,
        bandwidth_limit: Some(opts.bandwidth.clone()),
        verify_mode: opts.verify,
        resolve_records: opts.resolve_records,
        silent: opts.slient,
        device: opts.device.clone(),
        progress_callback: None,
    })
    .await?;

    let results = engine.run_brute_force().await?;
    let scan_data = SubdomainScanData::from_results(&results);

    if opts.verify {
        for result in &scan_data.verification_results {
            print_verification_result(result);
        }
    }

    if opts.summary {
        print_summary_stats(&scan_data.summary);
    }

    if let Some(output_path) = opts.output {
        let format = opts.format.parse::<OutputFormat>().unwrap_or_else(|error| {
            eprintln!("输出格式解析错误: {}, 使用默认JSON格式", error);
            OutputFormat::Json
        });

        export_scan_data(&scan_data, &output_path, &format)?;
    }

    Ok(())
}