use crate::tools::{config, tools};
use crate::transport::bootstrap_provider::bootstrap_provider::BootstrapProvider;
use hickory_resolver::{
config::{LookupIpStrategy, ResolverConfig},
name_server::TokioConnectionProvider,
Resolver, TokioResolver,
};
use log::warn;
use std::collections::HashSet;
pub struct DnssecBootstrapProvider {
resolvers: Vec<TokioResolver>,
}
impl DnssecBootstrapProvider {
pub fn new() -> Self {
let resolver_configs = [
ResolverConfig::cloudflare_https(),
ResolverConfig::google_https(),
];
let resolvers = resolver_configs
.into_iter()
.map(|resolver_config| {
let mut builder = Resolver::builder_with_config(resolver_config, TokioConnectionProvider::default());
builder.options_mut().validate = true;
builder.options_mut().ip_strategy = LookupIpStrategy::Ipv4Only;
builder.build()
})
.collect();
Self { resolvers }
}
}
#[async_trait::async_trait]
impl BootstrapProvider for DnssecBootstrapProvider {
async fn get_bootstrap_addresses(&self) -> Vec<String> {
let mut addresses = HashSet::new();
for domain in config::BOOTSTRAP_DOMAINS {
for resolver in &self.resolvers {
match resolver.lookup_ip(*domain).await {
Ok(response) => {
for ip in response.iter() {
addresses.insert(format!("{}:443", ip));
}
}
Err(e) => {
warn!("DNSSEC bootstrap lookup failed for {}: {}", domain, e);
}
}
}
}
let mut addresses: Vec<String> = addresses.drain().collect();
tools::shuffle(&mut addresses);
addresses
}
}