summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorEmīls <emils@mullvad.net>2023-02-01 11:13:24 +0000
committerEmīls <emils@mullvad.net>2023-02-01 13:03:24 +0000
commit7efe795c9d5b6fae98c179d45d82d1844be919d6 (patch)
tree4c438dc94d088202d4960c324f101d9d1609d20e
parent5e86e08df425ee94d901c00cd406bc38fc9c24f7 (diff)
downloadmullvadvpn-7efe795c9d5b6fae98c179d45d82d1844be919d6.tar.xz
mullvadvpn-7efe795c9d5b6fae98c179d45d82d1844be919d6.zip
Respond to more captive portal DNS queries
Since there can be more than a single captive portal domain, the macOS resolver should respond to all known queries.
-rw-r--r--CHANGELOG.md4
-rw-r--r--talpid-core/src/resolver.rs29
2 files changed, 22 insertions, 11 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 0c739113eb..e106777aa3 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -35,6 +35,10 @@ Line wrap the file at 100 chars. Th
#### Android
- Fix adaptive app icon which previously had a displaced nose and some other oddities.
+#### MacOS
+- Improved reliability of the connectivity check workaround by adding an extra captive portal check
+ domain
+
## [2023.1-beta1] - 2023-01-26
### Added
diff --git a/talpid-core/src/resolver.rs b/talpid-core/src/resolver.rs
index 9bcd12817f..8e69157aca 100644
--- a/talpid-core/src/resolver.rs
+++ b/talpid-core/src/resolver.rs
@@ -30,7 +30,16 @@ use trust_dns_server::{
};
const ALLOWED_RECORD_TYPES: &[RecordType] = &[RecordType::A, RecordType::AAAA, RecordType::CNAME];
-const CAPTIVE_PORTAL_DOMAIN: &str = "captive.apple.com";
+const CAPTIVE_PORTAL_DOMAINS: &[&str] = &["captive.apple.com", "netcts.cdn-apple.com"];
+
+lazy_static::lazy_static! {
+ static ref ALLOWED_DOMAINS: Vec<LowerName> =
+ CAPTIVE_PORTAL_DOMAINS
+ .iter()
+ .map(|domain| LowerName::from(Name::from_str(domain).unwrap()))
+ .collect();
+}
+
const TTL_SECONDS: u32 = 3;
/// An IP address to be used in the DNS response to the captive domain query. The address itself
/// belongs to the documentation range so should never be reachable.
@@ -166,9 +175,7 @@ impl FilteringResolver {
/// Determines whether a DNS query is allowable. Currently, this implies that the query is
/// either a `A`, `AAAA` or a `CNAME` query for `captive.apple.com`.
fn allow_query(&self, query: &LowerQuery) -> bool {
- let captive_apple_com: LowerName =
- LowerName::from(Name::from_str(CAPTIVE_PORTAL_DOMAIN).unwrap());
- ALLOWED_RECORD_TYPES.contains(&query.query_type()) && query.name() == &captive_apple_com
+ ALLOWED_RECORD_TYPES.contains(&query.query_type()) && ALLOWED_DOMAINS.contains(query.name())
}
}
@@ -296,13 +303,13 @@ mod test {
let handle = rt.block_on(start_resolver());
let test_resolver = get_test_resolver(handle.listening_port());
- let captive_portal_domain = LowerName::from(Name::from_str(CAPTIVE_PORTAL_DOMAIN).unwrap());
- let resolver_result = rt.block_on(async move {
- test_resolver
- .lookup(captive_portal_domain, RecordType::A)
- .await
- });
- resolver_result.expect("Failed to resolve test domain");
+ rt.block_on(async move {
+ for domain in &*ALLOWED_DOMAINS {
+ test_resolver.lookup(domain, RecordType::A).await?;
+ }
+ Ok::<(), trust_dns_server::resolver::error::ResolveError>(())
+ })
+ .expect("Resolution of domains failed");
}
#[test]