use rsubdomain::{
brute_force_subdomains, export_subdomain_results, run_speed_test, OutputFormat, QueryType,
PacketTransport, SubdomainBruteConfig, SubdomainBruteEngine, SubdomainResult,
};
use std::error::Error;
#[tokio::main]
async fn main() -> Result<(), Box<dyn Error>> {
println!("=== 示例1: 基本域名暴破 ===");
basic_brute_force().await?;
println!("\n=== 示例2: 高级域名暴破 ===");
advanced_brute_force().await?;
println!("\n=== 示例3: 完整功能暴破 ===");
full_featured_brute_force().await?;
println!("\n=== 示例4: 网速测试 ===");
speed_test_example().await?;
println!("\n=== 所有示例执行完成 ===");
Ok(())
}
async fn basic_brute_force() -> Result<(), Box<dyn Error>> {
let domains = vec!["example.com".to_string()];
let dictionary_file = None;
match brute_force_subdomains(
domains,
dictionary_file,
None, true, None, false, false, true, None, )
.await
{
Ok(results) => {
println!("发现 {} 个子域名:", results.len());
for result in results.iter().take(10) {
println!(
" {} -> {} ({})",
result.domain, result.value, result.record_type
);
}
}
Err(e) => println!("暴破失败: {}", e),
}
Ok(())
}
async fn advanced_brute_force() -> Result<(), Box<dyn Error>> {
let config = SubdomainBruteConfig {
dictionary: None, domains: vec!["example.com".to_string(), "test.com".to_string()],
resolvers: vec!["8.8.8.8".to_string(), "1.1.1.1".to_string()],
dictionary_file: Some("wordlist.txt".to_string()), skip_wildcard: true,
bandwidth_limit: Some("5M".to_string()),
verify_mode: false,
max_retries: 5,
dns_timeout_seconds: 10,
max_wait_seconds: 10,
verify_timeout_seconds: 10,
verify_concurrency: 50,
resolve_records: false,
cdn_detect: true,
cdn_collapse: true,
query_types: vec![QueryType::A],
silent: false,
raw_records: false,
device: None, transport: PacketTransport::Ethernet,
progress_callback: None,
};
match SubdomainBruteEngine::new(config).await {
Ok(engine) => match engine.run_brute_force().await {
Ok(results) => {
println!("高级暴破发现 {} 个子域名:", results.len());
for result in results.iter().take(5) {
println!(
" {} -> {} ({})",
result.domain, result.value, result.record_type
);
}
}
Err(e) => println!("高级暴破失败: {}", e),
},
Err(e) => println!("引擎创建失败: {}", e),
}
Ok(())
}
async fn full_featured_brute_force() -> Result<(), Box<dyn Error>> {
let config = SubdomainBruteConfig {
domains: vec!["example.com".to_string()],
resolvers: vec!["8.8.8.8".to_string()],
dictionary_file: None,
skip_wildcard: true,
dictionary: None,
bandwidth_limit: Some("3M".to_string()),
verify_mode: true, max_retries: 5,
dns_timeout_seconds: 10,
max_wait_seconds: 10,
verify_timeout_seconds: 10,
verify_concurrency: 50,
resolve_records: true, cdn_detect: true,
cdn_collapse: true,
query_types: vec![QueryType::A],
silent: false,
raw_records: false,
device: Some("eth0".to_string()), transport: PacketTransport::Ethernet,
progress_callback: None,
};
match SubdomainBruteEngine::new(config).await {
Ok(engine) => {
match engine.run_brute_force().await {
Ok(results) => {
println!("完整暴破发现 {} 个子域名:", results.len());
for result in results.iter().take(3) {
println!("域名: {}", result.domain);
println!(" 记录值: {}", result.value);
println!(" 记录类型: {}", result.record_type);
if let Some(ref verified) = result.verified {
println!(" HTTP状态: {:?}", verified.http_status);
println!(" HTTPS状态: {:?}", verified.https_status);
println!(" 标题: {:?}", verified.title);
}
if let Some(ref dns_records) = result.dns_records {
println!(" DNS记录: {:?}", dns_records.records.len());
}
println!();
}
export_results_example(&results).await?;
}
Err(e) => println!("完整暴破失败: {}", e),
}
}
Err(e) => println!("引擎创建失败: {}", e),
}
Ok(())
}
async fn speed_test_example() -> Result<(), Box<dyn Error>> {
println!("执行10秒网速测试...");
run_speed_test(10).await?;
Ok(())
}
async fn export_results_example(results: &[SubdomainResult]) -> Result<(), Box<dyn Error>> {
export_subdomain_results(results, "results.json", &OutputFormat::Json)?;
export_subdomain_results(results, "results.csv", &OutputFormat::Csv)?;
println!("结果已导出到 results.json 和 results.csv");
Ok(())
}
#[allow(dead_code)]
fn process_results_custom(results: &[SubdomainResult]) {
println!("=== 自定义结果处理 ===");
let mut by_type: std::collections::HashMap<String, Vec<&SubdomainResult>> =
std::collections::HashMap::new();
for result in results {
by_type
.entry(result.record_type.clone())
.or_default()
.push(result);
}
for (record_type, domains) in by_type {
println!("{} 记录 ({} 个):", record_type, domains.len());
for domain in domains.iter().take(3) {
println!(" {} -> {}", domain.domain, domain.value);
}
if domains.len() > 3 {
println!(" ... 还有 {} 个", domains.len() - 3);
}
println!();
}
let alive_count = results
.iter()
.filter(|r| {
r.verified
.as_ref()
.map_or(false, |v| v.http_alive || v.https_alive)
})
.count();
println!("存活域名: {} / {}", alive_count, results.len());
}
#[allow(dead_code)]
async fn error_handling_example() -> Result<(), Box<dyn Error>> {
let config = SubdomainBruteConfig {
domains: vec!["nonexistent-domain-12345.com".to_string()],
resolvers: vec!["invalid.dns.server".to_string()],
dictionary_file: Some("nonexistent_file.txt".to_string()),
..Default::default()
};
match SubdomainBruteEngine::new(config).await {
Ok(engine) => {
match engine.run_brute_force().await {
Ok(results) => {
println!("意外成功: {} 个结果", results.len());
}
Err(e) => {
println!("预期的暴破错误: {}", e);
}
}
}
Err(e) => {
println!("预期的引擎创建错误: {}", e);
}
}
Ok(())
}