Add double verification step.

If no `--no-verify` is provided, every resolved host is double-checked against a list of trustable DNS resolvers, ensuring that only **real** alive hosts are given to the user.

Signed-off-by: Edu4rdSHL <edu4rdshl@protonmail.com>
This commit is contained in:
Edu4rdSHL 2021-05-19 18:57:01 -05:00
parent 8cbcb2d39b
commit 9de7ab225c
No known key found for this signature in database
GPG key ID: 3A574A4009F553E5

View file

@ -68,6 +68,12 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
.takes_value(false) .takes_value(false)
.help("Show the discovered IP addresses. Default: false"), .help("Show the discovered IP addresses. Default: false"),
) )
.arg(
Arg::with_name("no-verify")
.long("no-verify")
.takes_value(false)
.help("Disables the double verification algorithm for valid subdomains -NOT RECOMMENDED-. Default: false"),
)
.arg( .arg(
Arg::with_name("quiet") Arg::with_name("quiet")
.short("q") .short("q")
@ -83,6 +89,8 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
let timeout = value_t!(matches.value_of("timeout"), u64).unwrap_or_else(|_| 1); let timeout = value_t!(matches.value_of("timeout"), u64).unwrap_or_else(|_| 1);
let retries = value_t!(matches.value_of("retries"), usize).unwrap_or_else(|_| 0); let retries = value_t!(matches.value_of("retries"), usize).unwrap_or_else(|_| 0);
let quiet_flag = matches.is_present("quiet"); let quiet_flag = matches.is_present("quiet");
let custom_resolvers = matches.is_present("resolvers");
let disable_double_check = matches.is_present("no-verify") && custom_resolvers;
// Resolver opts // Resolver opts
let options = ResolverOpts { let options = ResolverOpts {
@ -93,41 +101,44 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
..Default::default() ..Default::default()
}; };
// Create resolvers let built_in_nameservers: HashSet<String> = vec![
let mut nameserver_ips = HashSet::new(); // Cloudflare
"1.1.1.1:53",
"1.0.0.1:53",
// Google
"8.8.8.8:53",
"8.8.4.4:53",
// Quad9
"9.9.9.9:53",
"149.112.112.112:53",
// OpenDNS
"208.67.222.222:53",
"208.67.220.220:53",
// Verisign
"64.6.64.6:53",
"64.6.65.6:53",
// UncensoredDNS
"91.239.100.100:53",
"89.233.43.71:53",
// dns.watch
"84.200.69.80:53",
"84.200.70.40:53",
]
.iter()
.map(|x| x.to_string())
.collect();
if matches.is_present("resolvers") { // Create resolvers
let nameserver_ips;
if custom_resolvers {
nameserver_ips = nameserver_ips =
return_file_lines(value_t!(matches.value_of("resolvers"), String).unwrap()).await; return_file_lines(value_t!(matches.value_of("resolvers"), String).unwrap()).await;
} else { } else {
let built_in_nameservers = vec![ nameserver_ips = built_in_nameservers.clone();
// Cloudflare
"1.1.1.1:53",
"1.0.0.1:53",
// Google
"8.8.8.8:53",
"8.8.4.4:53",
// Quad9
"9.9.9.9:53",
"149.112.112.112:53",
// OpenDNS
"208.67.222.222:53",
"208.67.220.220:53",
// Verisign
"64.6.64.6:53",
"64.6.65.6:53",
// UncensoredDNS
"91.239.100.100:53",
"89.233.43.71:53",
// dns.watch
"84.200.69.80:53",
"84.200.70.40:53",
];
for ip in built_in_nameservers {
nameserver_ips.insert(ip.to_string());
}
} }
let resolvers = return_tokio_asyncresolver(nameserver_ips, options); let resolvers = return_tokio_asyncresolver(nameserver_ips, options);
let trustable_resolver = return_tokio_asyncresolver(built_in_nameservers, options);
let mut wildcard_ips = HashSet::new(); let mut wildcard_ips = HashSet::new();
// Read stdin // Read stdin
@ -148,13 +159,22 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
futures::stream::iter(hosts.into_iter().map(|host| { futures::stream::iter(hosts.into_iter().map(|host| {
let resolver_fut = resolvers.ipv4_lookup(host.clone()); let resolver_fut = resolvers.ipv4_lookup(host.clone());
let trustable_resolver_fut = trustable_resolver.ipv4_lookup(host.clone());
let wildcard_ips = wildcard_ips.clone(); let wildcard_ips = wildcard_ips.clone();
async move { async move {
if let Ok(ip) = resolver_fut.await { if let Ok(ip) = resolver_fut.await {
let ips = ip let mut ips = HashSet::new();
.into_iter() if disable_double_check {
.map(|x| x.to_string()) ips = ip
.collect::<HashSet<String>>(); .into_iter()
.map(|x| x.to_string())
.collect::<HashSet<String>>();
} else if let Ok(ip) = trustable_resolver_fut.await {
ips = ip
.into_iter()
.map(|x| x.to_string())
.collect::<HashSet<String>>();
}
if show_ip_adress && !ips.iter().all(|ip| wildcard_ips.contains(ip)) { if show_ip_adress && !ips.iter().all(|ip| wildcard_ips.contains(ip)) {
println!("{};{:?}", host, ips) println!("{};{:?}", host, ips)
} else if !ips.iter().all(|ip| wildcard_ips.contains(ip)) { } else if !ips.iter().all(|ip| wildcard_ips.contains(ip)) {