diff --git a/resolvers.txt b/resolvers.txt new file mode 100644 index 0000000..26dcc93 --- /dev/null +++ b/resolvers.txt @@ -0,0 +1,25 @@ +199.255.137.34 +8.8.8.8 +199.85.126.10 +149.112.112.112 +68.87.68.162 +68.87.76.178 +68.87.76.182 +8.20.247.20 +64.6.65.6 +162.243.19.47 +45.33.97.5 +129.250.35.250 +129.250.35.251 +156.154.70.1 +185.228.169.9 +199.2.252.10 +204.117.214.10 +204.194.232.200 +204.194.234.200 +208.67.220.222 +165.87.13.129 +165.87.201.244 +4.2.2.1 +8.0.6.0 +8.0.7.0 diff --git a/src/main.rs b/src/main.rs index 1c1bd5a..ac123cf 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,17 +1,17 @@ -use rand::prelude::SliceRandom; - use { clap::{value_t, App, Arg}, futures::stream::StreamExt, - rand::thread_rng as rng, - std::net::IpAddr, + rand::{prelude::SliceRandom, thread_rng as rng}, + std::{collections::HashSet, net::IpAddr}, tokio::{ self, + fs::File, io::{self, AsyncReadExt}, }, trust_dns_resolver::{ config::{NameServerConfigGroup, ResolverConfig, ResolverOpts}, - TokioAsyncResolver, + name_server::{GenericConnection, GenericConnectionProvider, TokioRuntime}, + AsyncResolver, TokioAsyncResolver, }, }; @@ -19,7 +19,7 @@ use { async fn main() -> Result<(), Box> { // Eval args let matches = App::new("Rusolver") - .version("0.1.0") + .version(clap::crate_version!()) .author("Eduard Tolosa ") .about("Fast DNS resolver written in Rust.") .arg( @@ -29,6 +29,13 @@ async fn main() -> Result<(), Box> { .takes_value(true) .help("Number of threads. Default: 100"), ) + .arg( + Arg::with_name("resolvers") + .short("r") + .long("resolvers") + .takes_value(true) + .help("File with DNS ips."), + ) .arg( Arg::with_name("timeout") .long("timeout") @@ -56,48 +63,39 @@ async fn main() -> Result<(), Box> { }; // Create resolvers - let dns_ips = vec![ - // Cloudflare - "1.1.1.1", - "1.0.0.1", - // Google - "8.8.8.8", - "8.8.4.4", - // Quad9 - "9.9.9.9", - "149.112.112.112", - // OpenDNS - "208.67.222.222", - "208.67.220.220", - // Verisign - "64.6.64.6", - "64.6.65.6", - // UncensoredDNS - "91.239.100.100", - "89.233.43.71", - // dns.watch - "84.200.69.80", - "84.200.70.40", - ]; + let mut dns_ips = HashSet::new(); - let mut resolvers = Vec::new(); - for ip in dns_ips { - resolvers.push( - TokioAsyncResolver::tokio( - ResolverConfig::from_parts( - None, - vec![], - NameServerConfigGroup::from_ips_clear( - &[IpAddr::V4(ip.parse().unwrap())], - 53, - false, - ), - ), - options, - ) - .unwrap(), - ) + if matches.is_present("resolvers") { + dns_ips = return_file_lines(value_t!(matches.value_of("resolvers"), String).unwrap()).await; + } else { + let built_in_dns = vec![ + // Cloudflare + "1.1.1.1", + "1.0.0.1", + // Google + "8.8.8.8", + "8.8.4.4", + // Quad9 + "9.9.9.9", + "149.112.112.112", + // OpenDNS + "208.67.222.222", + "208.67.220.220", + // Verisign + "64.6.64.6", + "64.6.65.6", + // UncensoredDNS + "91.239.100.100", + "89.233.43.71", + // dns.watch + "84.200.69.80", + "84.200.70.40", + ]; + for ip in built_in_dns { + dns_ips.insert(ip.to_string()); + } } + let resolvers = return_tokio_dns(dns_ips, options).await; // Read stdin let mut buffer = String::new(); @@ -131,3 +129,56 @@ async fn main() -> Result<(), Box> { .await; Ok(()) } + +// In the future I may need to implement error propagation, but for now it's fine +// to deal with matches +async fn return_file_lines(file: String) -> HashSet { + let mut f = match File::open(&file).await { + Ok(file) => file, + Err(e) => { + eprintln!("Error opening resolvers file. Error: {}", e); + std::process::exit(1) + } + }; + let mut buffer = String::new(); + + match f.read_to_string(&mut buffer).await { + Ok(a) => a, + _ => unreachable!("Error reading to string."), + }; + buffer.lines().map(str::to_owned).collect() +} + +async fn return_tokio_dns( + dns_ips: HashSet, + options: ResolverOpts, +) -> Vec>> { + let mut resolvers = Vec::new(); + for ip in dns_ips { + resolvers.push( + TokioAsyncResolver::tokio( + ResolverConfig::from_parts( + None, + vec![], + NameServerConfigGroup::from_ips_clear( + &[IpAddr::V4(match ip.parse() { + Ok(a) => a, + Err(e) => { + eprintln!( + "Error adding {} to the list of resolvers, only IPv4 addresses are allowed. Please fix the problem and try again. Error: {}", + ip, e + ); + std::process::exit(1) + } + })], + 53, + false, + ), + ), + options, + ) + .unwrap(), + ) + } + resolvers +}