Skip to content

Commit bf15762

Browse files
committed
Add timeout for DNS lookups
1 parent c7e617e commit bf15762

File tree

1 file changed

+36
-27
lines changed

1 file changed

+36
-27
lines changed

Diff for: mullvad-encrypted-dns-proxy/src/config_resolver.rs

+36-27
Original file line numberDiff line numberDiff line change
@@ -4,41 +4,45 @@ use crate::config;
44
use core::fmt;
55
use hickory_resolver::{config::*, error::ResolveError, TokioAsyncResolver};
66
use rustls::ClientConfig;
7-
use std::{net::IpAddr, sync::Arc};
7+
use std::{net::IpAddr, sync::Arc, time::Duration};
8+
use tokio::time::error::Elapsed;
89

910
/// The port to connect to the DoH resolvers over.
1011
const RESOLVER_PORT: u16 = 443;
12+
const DEFAULT_TIMEOUT: Duration = std::time::Duration::from_secs(10);
1113

1214
pub struct Nameserver {
1315
pub name: String,
1416
pub addr: Vec<IpAddr>,
1517
}
1618

1719
#[derive(Debug)]
18-
pub struct ResolutionError(ResolveError);
20+
pub enum Error {
21+
ResolutionError(ResolveError),
22+
Timeout(Elapsed),
23+
}
1924

20-
impl fmt::Display for ResolutionError {
25+
impl fmt::Display for Error {
2126
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
22-
self.0.fmt(f)
27+
match self {
28+
Error::ResolutionError(err) => err.fmt(f),
29+
Error::Timeout(err) => err.fmt(f),
30+
}
2331
}
2432
}
2533

26-
impl std::error::Error for ResolutionError {
34+
impl std::error::Error for Error {
2735
fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
28-
self.0.source()
36+
match self {
37+
Self::ResolutionError(ref err) => Some(err),
38+
Self::Timeout(ref err) => Some(err),
39+
}
2940
}
3041
}
3142

3243
/// Returns a set of well known public DoH resolvers. A sane default in many cases.
3344
pub fn default_resolvers() -> Vec<Nameserver> {
3445
vec![
35-
Nameserver {
36-
name: "dns.quad9.net".to_owned(),
37-
addr: vec![
38-
"9.9.9.9".parse().unwrap(),
39-
"149.112.112.112".parse().unwrap(),
40-
],
41-
},
4246
Nameserver {
4347
name: "one.one.one.one".to_owned(),
4448
addr: vec!["1.1.1.1".parse().unwrap(), "1.0.0.1".parse().unwrap()],
@@ -47,6 +51,13 @@ pub fn default_resolvers() -> Vec<Nameserver> {
4751
name: "dns.google".to_owned(),
4852
addr: vec!["8.8.8.8".parse().unwrap(), "8.8.4.4".parse().unwrap()],
4953
},
54+
Nameserver {
55+
name: "dns.quad9.net".to_owned(),
56+
addr: vec![
57+
"9.9.9.9".parse().unwrap(),
58+
"149.112.112.112".parse().unwrap(),
59+
],
60+
},
5061
]
5162
}
5263

@@ -55,8 +66,8 @@ pub fn default_resolvers() -> Vec<Nameserver> {
5566
pub async fn resolve_configs(
5667
resolvers: &[Nameserver],
5768
domain: &str,
58-
) -> Result<Vec<config::ProxyConfig>, ResolutionError> {
59-
let mut resolver_config = ResolverConfig::new();
69+
) -> Result<Vec<config::ProxyConfig>, Error> {
70+
let mut nameservers = ResolverConfig::new();
6071
for resolver in resolvers.iter() {
6172
let ns_config_group = NameServerConfigGroup::from_ips_https(
6273
&resolver.addr,
@@ -66,25 +77,28 @@ pub async fn resolve_configs(
6677
)
6778
.into_inner();
6879
for ns_config in ns_config_group {
69-
resolver_config.add_name_server(ns_config);
80+
nameservers.add_name_server(ns_config);
7081
}
7182
}
7283

73-
resolver_config.set_tls_client_config(Arc::new(client_config_tls12()));
84+
nameservers.set_tls_client_config(Arc::new(client_config_tls12()));
85+
let mut resolver_config: ResolverOpts = Default::default();
7486

75-
resolve_config_with_resolverconfig(resolver_config, Default::default(), domain).await
87+
resolver_config.timeout = Duration::from_secs(5);
88+
resolve_config_with_resolverconfig(nameservers, resolver_config, domain, DEFAULT_TIMEOUT).await
7689
}
7790

7891
pub async fn resolve_config_with_resolverconfig(
7992
resolver_config: ResolverConfig,
8093
options: ResolverOpts,
8194
domain: &str,
82-
) -> Result<Vec<config::ProxyConfig>, ResolutionError> {
95+
timeout: Duration,
96+
) -> Result<Vec<config::ProxyConfig>, Error> {
8397
let resolver = TokioAsyncResolver::tokio(resolver_config, options);
84-
let lookup = resolver
85-
.ipv6_lookup(domain)
98+
let lookup = tokio::time::timeout(timeout, resolver.ipv6_lookup(domain))
8699
.await
87-
.map_err(ResolutionError)?;
100+
.map_err(Error::Timeout)?
101+
.map_err(Error::ResolutionError)?;
88102

89103
let addrs = lookup.into_iter().map(|aaaa_record| aaaa_record.0);
90104

@@ -102,11 +116,6 @@ pub async fn resolve_config_with_resolverconfig(
102116
Ok(proxy_configs)
103117
}
104118

105-
pub async fn resolve_default_config() -> Result<Vec<config::ProxyConfig>, ResolutionError> {
106-
resolve_configs(&default_resolvers(), "frakta.eu").await
107-
108-
}
109-
110119
fn client_config_tls12() -> ClientConfig {
111120
use rustls::RootCertStore;
112121
let mut root_store = RootCertStore::empty();

0 commit comments

Comments
 (0)