summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorDavid Lönnhager <david.l@mullvad.net>2025-08-18 09:02:21 +0200
committerDavid Lönnhager <david.l@mullvad.net>2025-08-18 10:51:58 +0200
commitba966fee57d9de61997bef4d7dcf6539af26c037 (patch)
tree3299982d13cfd1a53f7166257a9af1fc1e8469d9
parent0abee355c21eb00a221842b39ab41bc26fa0b663 (diff)
downloadmullvadvpn-ba966fee57d9de61997bef4d7dcf6539af26c037.tar.xz
mullvadvpn-ba966fee57d9de61997bef4d7dcf6539af26c037.zip
Fail if QUIC address set is empty
-rw-r--r--Cargo.lock7
-rw-r--r--mullvad-api/Cargo.toml1
-rw-r--r--mullvad-api/src/relay_list.rs10
-rw-r--r--mullvad-management-interface/Cargo.toml1
-rw-r--r--mullvad-management-interface/src/types/conversions/relay_list.rs4
-rw-r--r--mullvad-relay-selector/Cargo.toml1
-rw-r--r--mullvad-relay-selector/src/relay_selector/matcher.rs19
-rw-r--r--mullvad-relay-selector/tests/relay_selector.rs3
-rw-r--r--mullvad-types/Cargo.toml1
-rw-r--r--mullvad-types/src/relay_list.rs13
-rw-r--r--test/Cargo.lock7
11 files changed, 46 insertions, 21 deletions
diff --git a/Cargo.lock b/Cargo.lock
index 885f34c313..2f5e37fc2c 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -2877,6 +2877,7 @@ dependencies = [
"tokio-socks",
"tower 0.5.1",
"uuid",
+ "vec1",
]
[[package]]
@@ -3082,6 +3083,7 @@ dependencies = [
"tonic",
"tonic-build",
"tower 0.5.1",
+ "vec1",
]
[[package]]
@@ -3164,6 +3166,7 @@ dependencies = [
"serde_json",
"talpid-types",
"thiserror 2.0.9",
+ "vec1",
]
[[package]]
@@ -3222,6 +3225,7 @@ dependencies = [
"talpid-types",
"thiserror 2.0.9",
"uuid",
+ "vec1",
]
[[package]]
@@ -6274,6 +6278,9 @@ name = "vec1"
version = "1.12.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "eab68b56840f69efb0fefbe3ab6661499217ffdc58e2eef7c3f6f69835386322"
+dependencies = [
+ "serde",
+]
[[package]]
name = "version_check"
diff --git a/mullvad-api/Cargo.toml b/mullvad-api/Cargo.toml
index 5764d9378b..1ffd0bc08c 100644
--- a/mullvad-api/Cargo.toml
+++ b/mullvad-api/Cargo.toml
@@ -47,6 +47,7 @@ tokio-rustls = { version = "0.26.0", features = [
tokio-socks = "0.5.1"
rustls-pemfile = "2.1.3"
uuid = { version = "1.4.1", features = ["v4"] }
+vec1 = { workspace = true, features = ["serde"] }
mullvad-api-constants = { path = "./mullvad-api-constants" }
mullvad-encrypted-dns-proxy = { path = "../mullvad-encrypted-dns-proxy" }
diff --git a/mullvad-api/src/relay_list.rs b/mullvad-api/src/relay_list.rs
index 28ce37aec0..6fdc073efd 100644
--- a/mullvad-api/src/relay_list.rs
+++ b/mullvad-api/src/relay_list.rs
@@ -5,6 +5,7 @@ use crate::rest;
use hyper::{StatusCode, body::Incoming, header};
use mullvad_types::{location, relay_list};
use talpid_types::net::wireguard;
+use vec1::Vec1;
use std::{
collections::{BTreeMap, HashSet},
@@ -386,9 +387,12 @@ struct Daita {}
struct Quic {
/// In-addresses for the QUIC obfuscator.
///
- /// There may be 0, 1 or 2 in IPs, depending on how many masque-proxy daemons running on the
- /// relay. Hopefully the API will tell use the correct amount🤞.
- addr_in: Vec<IpAddr>,
+ /// # Note
+ ///
+ /// This set must be non-empty.
+ ///
+ /// The primary IPs of the relay will be included if and only if they are listed here.
+ addr_in: Vec1<IpAddr>,
/// Authorization token
token: String,
/// Hostname where masque proxy is hosted
diff --git a/mullvad-management-interface/Cargo.toml b/mullvad-management-interface/Cargo.toml
index e502ddeecf..29c84537be 100644
--- a/mullvad-management-interface/Cargo.toml
+++ b/mullvad-management-interface/Cargo.toml
@@ -25,6 +25,7 @@ prost = { workspace = true }
prost-types = { workspace = true }
futures = { workspace = true }
tokio = { workspace = true, features = ["rt"] }
+vec1 = { workspace = true }
parity-tokio-ipc = { workspace = true }
[target.'cfg(unix)'.dependencies]
diff --git a/mullvad-management-interface/src/types/conversions/relay_list.rs b/mullvad-management-interface/src/types/conversions/relay_list.rs
index 08ec379ba9..f7979725fe 100644
--- a/mullvad-management-interface/src/types/conversions/relay_list.rs
+++ b/mullvad-management-interface/src/types/conversions/relay_list.rs
@@ -5,6 +5,8 @@ use std::{
str::FromStr,
};
+use vec1::Vec1;
+
use crate::types::{FromProtobufTypeError, conversions::bytes_to_pubkey, proto};
use super::net::try_transport_protocol_from_i32;
@@ -186,6 +188,8 @@ impl TryFrom<proto::relay::relay_data::wireguard::Quic> for mullvad_types::relay
.into_iter()
.map(parse_addr)
.collect::<Result<Vec<IpAddr>, FromProtobufTypeError>>()?;
+ let addr_in = Vec1::try_from_vec(addr_in)
+ .map_err(|_err| FromProtobufTypeError::InvalidArgument("Invalid QUIC object"))?;
Ok(Self::new(addr_in, token, domain))
}
}
diff --git a/mullvad-relay-selector/Cargo.toml b/mullvad-relay-selector/Cargo.toml
index dc3da3a5d6..3bb0f7665e 100644
--- a/mullvad-relay-selector/Cargo.toml
+++ b/mullvad-relay-selector/Cargo.toml
@@ -20,6 +20,7 @@ rand = "0.8.5"
serde_json = { workspace = true }
talpid-types = { path = "../talpid-types" }
+vec1 = { workspace = true }
mullvad-types = { path = "../mullvad-types" }
intersection-derive = { path = "../mullvad-types/intersection-derive"}
diff --git a/mullvad-relay-selector/src/relay_selector/matcher.rs b/mullvad-relay-selector/src/relay_selector/matcher.rs
index f6bf70f494..6b76eecef8 100644
--- a/mullvad-relay-selector/src/relay_selector/matcher.rs
+++ b/mullvad-relay-selector/src/relay_selector/matcher.rs
@@ -145,18 +145,13 @@ fn filter_on_obfuscation(
)
}
// QUIC is only enabled on some relays
- ObfuscationQuery::Quic => relay.wireguard().is_some_and(|wg| {
- if let Some(quic) = wg.quic() {
- // Only include relay if it has addresses for the selected IP version
- matches!(
- (query.ip_version, quic.in_ipv4(), quic.in_ipv6()),
- (Constraint::Only(IpVersion::V4), Some(_), _)
- | (Constraint::Only(IpVersion::V6), _, Some(_))
- | (Constraint::Any, _, _)
- )
- } else {
- false
- }
+ ObfuscationQuery::Quic => relay.wireguard().is_some_and(|wg| match wg.quic() {
+ Some(quic) => match query.ip_version {
+ Constraint::Any => true,
+ Constraint::Only(IpVersion::V4) => quic.in_ipv4().is_some(),
+ Constraint::Only(IpVersion::V6) => quic.in_ipv6().is_some(),
+ },
+ None => false,
}),
// Other relays are compatible with this query
ObfuscationQuery::Off | ObfuscationQuery::Auto | ObfuscationQuery::Udp2tcp(_) => true,
diff --git a/mullvad-relay-selector/tests/relay_selector.rs b/mullvad-relay-selector/tests/relay_selector.rs
index ad91c192d5..87a089af62 100644
--- a/mullvad-relay-selector/tests/relay_selector.rs
+++ b/mullvad-relay-selector/tests/relay_selector.rs
@@ -32,6 +32,7 @@ use mullvad_types::{
WireguardRelayEndpointData,
},
};
+use vec1::vec1;
static DUMMY_LOCATION: LazyLock<Location> = LazyLock::new(|| Location {
country: "Sweden".to_string(),
@@ -72,7 +73,7 @@ static RELAYS: LazyLock<RelayList> = LazyLock::new(|| RelayList {
WireguardRelayEndpointData::new(WIREGUARD_PUBKEY.clone())
.set_daita(true)
.set_quic(Quic::new(
- vec![
+ vec1![
"185.213.154.68".parse().unwrap(),
"2a03:1b20:5:f011::a09f".parse().unwrap(),
],
diff --git a/mullvad-types/Cargo.toml b/mullvad-types/Cargo.toml
index 5878767458..36efa91eda 100644
--- a/mullvad-types/Cargo.toml
+++ b/mullvad-types/Cargo.toml
@@ -19,6 +19,7 @@ log = { workspace = true }
regex = "1"
serde = { workspace = true, features = ["derive"] }
uuid = { version = "1.4.1", features = ["v4", "serde" ] }
+vec1 = { workspace = true }
talpid-types = { path = "../talpid-types" }
intersection-derive = { path = "intersection-derive" }
diff --git a/mullvad-types/src/relay_list.rs b/mullvad-types/src/relay_list.rs
index b8f528bba2..ee3c107b7e 100644
--- a/mullvad-types/src/relay_list.rs
+++ b/mullvad-types/src/relay_list.rs
@@ -6,6 +6,7 @@ use std::{
ops::RangeInclusive,
};
use talpid_types::net::{TransportProtocol, proxy::Shadowsocks, wireguard};
+use vec1::Vec1;
/// Stores a list of relays for each country obtained from the API using
/// `mullvad_api::RelayListProxy`. This can also be passed to frontends.
@@ -143,8 +144,11 @@ impl Relay {
pub struct Quic {
/// In-addresses for the QUIC obfuscator.
///
- /// There may be 0, 1 or 2 in IPs, depending on how many masque-proxy daemons running on the
- /// relay. Hopefully the API will tell use the correct amount🤞.
+ /// # Note
+ ///
+ /// This set must be non-empty.
+ ///
+ /// The primary IPs of the relay will be included if and only if they are listed here.
addr_in: HashSet<IpAddr>,
/// Authorization token
token: String,
@@ -153,10 +157,9 @@ pub struct Quic {
}
impl Quic {
- pub fn new(addr_in: impl IntoIterator<Item = IpAddr>, token: String, domain: String) -> Self {
- let addr_in = HashSet::from_iter(addr_in);
+ pub fn new(addr_in: Vec1<IpAddr>, token: String, domain: String) -> Self {
Self {
- addr_in,
+ addr_in: addr_in.into_iter().collect(),
token,
domain,
}
diff --git a/test/Cargo.lock b/test/Cargo.lock
index fe99ba1cab..af17315717 100644
--- a/test/Cargo.lock
+++ b/test/Cargo.lock
@@ -2119,6 +2119,7 @@ dependencies = [
"tokio-socks",
"tower 0.5.1",
"uuid",
+ "vec1",
]
[[package]]
@@ -2167,6 +2168,7 @@ dependencies = [
"tonic",
"tonic-build",
"tower 0.5.1",
+ "vec1",
]
[[package]]
@@ -2194,6 +2196,7 @@ dependencies = [
"serde_json",
"talpid-types",
"thiserror 2.0.3",
+ "vec1",
]
[[package]]
@@ -2211,6 +2214,7 @@ dependencies = [
"talpid-types",
"thiserror 2.0.3",
"uuid",
+ "vec1",
]
[[package]]
@@ -4385,6 +4389,9 @@ name = "vec1"
version = "1.12.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "eab68b56840f69efb0fefbe3ab6661499217ffdc58e2eef7c3f6f69835386322"
+dependencies = [
+ "serde",
+]
[[package]]
name = "version_check"