summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--Cargo.lock7
-rw-r--r--desktop/packages/mullvad-vpn/src/renderer/components/select-location/RelayListContext.tsx12
-rw-r--r--desktop/packages/mullvad-vpn/src/renderer/lib/filter-locations.ts24
-rw-r--r--desktop/packages/mullvad-vpn/test/e2e/mock-data.ts2
-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.rs9
-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
14 files changed, 81 insertions, 14 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/desktop/packages/mullvad-vpn/src/renderer/components/select-location/RelayListContext.tsx b/desktop/packages/mullvad-vpn/src/renderer/components/select-location/RelayListContext.tsx
index 89f9edaee5..59a48c4130 100644
--- a/desktop/packages/mullvad-vpn/src/renderer/components/select-location/RelayListContext.tsx
+++ b/desktop/packages/mullvad-vpn/src/renderer/components/select-location/RelayListContext.tsx
@@ -81,6 +81,7 @@ export function RelayListContextProvider(props: RelayListContextProviderProps) {
const relaySettings = useNormalRelaySettings();
const tunnelProtocol = useTunnelProtocol();
const multihop = relaySettings?.wireguard.useMultihop ?? false;
+ const ipVersion = relaySettings?.wireguard.ipVersion ?? 'any';
// Filters the relays to only keep the ones of the desired endpoint type, e.g. "wireguard",
// "openvpn" or "bridge"
@@ -103,8 +104,15 @@ export function RelayListContextProvider(props: RelayListContextProviderProps) {
// Only show relays that have QUIC endpoints when QUIC obfuscation is enabled.
const relayListForQuic = useMemo(() => {
- return filterLocationsByQuic(relayListForDaita, quic, tunnelProtocol, locationType, multihop);
- }, [quic, relayListForDaita, locationType, tunnelProtocol, multihop]);
+ return filterLocationsByQuic(
+ relayListForDaita,
+ quic,
+ tunnelProtocol,
+ locationType,
+ multihop,
+ ipVersion,
+ );
+ }, [quic, relayListForDaita, locationType, tunnelProtocol, multihop, ipVersion]);
// Filters the relays to only keep the relays matching the currently selected filters, e.g.
// ownership and providers
diff --git a/desktop/packages/mullvad-vpn/src/renderer/lib/filter-locations.ts b/desktop/packages/mullvad-vpn/src/renderer/lib/filter-locations.ts
index d219bb099f..2c125cdb9a 100644
--- a/desktop/packages/mullvad-vpn/src/renderer/lib/filter-locations.ts
+++ b/desktop/packages/mullvad-vpn/src/renderer/lib/filter-locations.ts
@@ -1,4 +1,6 @@
import {
+ IpVersion,
+ LiftedConstraint,
Ownership,
RelayEndpointType,
RelayLocation,
@@ -17,6 +19,7 @@ import {
IRelayLocationCountryRedux,
IRelayLocationRelayRedux,
} from '../redux/settings/reducers';
+import { IpAddress, IPv4Address, IPv6Address } from './ip';
export enum EndpointType {
any,
@@ -38,8 +41,10 @@ export function filterLocationsByQuic(
tunnelProtocol: TunnelProtocol,
locationType: LocationType,
multihop: boolean,
+ ipVersion: LiftedConstraint<IpVersion>,
): IRelayLocationCountryRedux[] {
- const quickOnRelay = (relay: IRelayLocationRelayRedux) => relay.quic !== undefined;
+ const quickOnRelay = (relay: IRelayLocationRelayRedux) =>
+ relay.quic !== undefined && containsIpVersionAddr(relay.quic.addrIn, ipVersion);
return quicFilterActive(quic, locationType, tunnelProtocol, multihop)
? filterLocationsImpl(locations, quickOnRelay)
: locations;
@@ -95,6 +100,23 @@ export function filterLocations(
: locations;
}
+function containsIpVersionAddr(addrs: string[], version: LiftedConstraint<IpVersion>): boolean {
+ if (version === 'any') {
+ return addrs.length > 0;
+ }
+ return addrs.some((strAddr) => {
+ try {
+ const addr = IpAddress.fromString(strAddr);
+ return (
+ (addr instanceof IPv4Address && version === 'ipv4') ||
+ (addr instanceof IPv6Address && version === 'ipv6')
+ );
+ } catch {
+ return false;
+ }
+ });
+}
+
function getTunnelProtocolFilter(
endpointType: EndpointType,
tunnelProtocol: TunnelProtocol,
diff --git a/desktop/packages/mullvad-vpn/test/e2e/mock-data.ts b/desktop/packages/mullvad-vpn/test/e2e/mock-data.ts
index efbac88f83..4bd4436772 100644
--- a/desktop/packages/mullvad-vpn/test/e2e/mock-data.ts
+++ b/desktop/packages/mullvad-vpn/test/e2e/mock-data.ts
@@ -56,7 +56,7 @@ const relayList: IRelayList = {
endpointType: 'wireguard',
daita: true,
quic: {
- addrIn: [],
+ addrIn: ['10.0.0.4'],
domain: '',
token: '',
},
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 52f0cc600a..6b76eecef8 100644
--- a/mullvad-relay-selector/src/relay_selector/matcher.rs
+++ b/mullvad-relay-selector/src/relay_selector/matcher.rs
@@ -145,7 +145,14 @@ fn filter_on_obfuscation(
)
}
// QUIC is only enabled on some relays
- ObfuscationQuery::Quic => relay.wireguard().is_some_and(|wg| wg.quic().is_some()),
+ 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"