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)
.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::with_name("quiet")
.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 retries = value_t!(matches.value_of("retries"), usize).unwrap_or_else(|_| 0);
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
let options = ResolverOpts {
@ -93,14 +101,7 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
..Default::default()
};
// Create resolvers
let mut nameserver_ips = HashSet::new();
if matches.is_present("resolvers") {
nameserver_ips =
return_file_lines(value_t!(matches.value_of("resolvers"), String).unwrap()).await;
} else {
let built_in_nameservers = vec![
let built_in_nameservers: HashSet<String> = vec![
// Cloudflare
"1.1.1.1:53",
"1.0.0.1:53",
@ -122,12 +123,22 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
// dns.watch
"84.200.69.80:53",
"84.200.70.40:53",
];
for ip in built_in_nameservers {
nameserver_ips.insert(ip.to_string());
}
]
.iter()
.map(|x| x.to_string())
.collect();
// Create resolvers
let nameserver_ips;
if custom_resolvers {
nameserver_ips =
return_file_lines(value_t!(matches.value_of("resolvers"), String).unwrap()).await;
} else {
nameserver_ips = built_in_nameservers.clone();
}
let resolvers = return_tokio_asyncresolver(nameserver_ips, options);
let trustable_resolver = return_tokio_asyncresolver(built_in_nameservers, options);
let mut wildcard_ips = HashSet::new();
// Read stdin
@ -148,13 +159,22 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
futures::stream::iter(hosts.into_iter().map(|host| {
let resolver_fut = resolvers.ipv4_lookup(host.clone());
let trustable_resolver_fut = trustable_resolver.ipv4_lookup(host.clone());
let wildcard_ips = wildcard_ips.clone();
async move {
if let Ok(ip) = resolver_fut.await {
let ips = ip
let mut ips = HashSet::new();
if disable_double_check {
ips = ip
.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)) {
println!("{};{:?}", host, ips)
} else if !ips.iter().all(|ip| wildcard_ips.contains(ip)) {