Add support for using DNS from file.

Signed-off-by: Edu4rdSHL <edu4rdshl@protonmail.com>
This commit is contained in:
Edu4rdSHL 2021-05-10 04:30:40 -05:00
parent 91654a4898
commit 87bee0c01b
No known key found for this signature in database
GPG key ID: 3A574A4009F553E5
2 changed files with 122 additions and 46 deletions

25
resolvers.txt Normal file
View file

@ -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

View file

@ -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<dyn std::error::Error>> {
// Eval args
let matches = App::new("Rusolver")
.version("0.1.0")
.version(clap::crate_version!())
.author("Eduard Tolosa <edu4rdshl@protonmail.com>")
.about("Fast DNS resolver written in Rust.")
.arg(
@ -29,6 +29,13 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
.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<dyn std::error::Error>> {
};
// 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<dyn std::error::Error>> {
.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<String> {
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<String>,
options: ResolverOpts,
) -> Vec<AsyncResolver<GenericConnection, GenericConnectionProvider<TokioRuntime>>> {
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
}