summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorMarkus Pettersson <markus.pettersson@mullvad.net>2024-10-17 09:52:18 +0200
committerMarkus Pettersson <markus.pettersson@mullvad.net>2024-10-18 15:49:31 +0200
commit6aac72972450ce598b60f4e1e9264cad5860c3a4 (patch)
tree98042a25ec750762a641881173d779e9424afbad
parent58e1123f7844104f36ab326d4f2ee90043034c8e (diff)
downloadmullvadvpn-6aac72972450ce598b60f4e1e9264cad5860c3a4.tar.xz
mullvadvpn-6aac72972450ce598b60f4e1e9264cad5860c3a4.zip
Add test case for smart routing overriding multihop
-rw-r--r--mullvad-relay-selector/src/relay_selector/query.rs4
-rw-r--r--mullvad-relay-selector/tests/relay_selector.rs74
2 files changed, 77 insertions, 1 deletions
diff --git a/mullvad-relay-selector/src/relay_selector/query.rs b/mullvad-relay-selector/src/relay_selector/query.rs
index 3878e2e0c7..162865368a 100644
--- a/mullvad-relay-selector/src/relay_selector/query.rs
+++ b/mullvad-relay-selector/src/relay_selector/query.rs
@@ -932,7 +932,9 @@ impl RelayQueryExt for RelayQuery {
fn use_multihop_if_necessary(&self) -> bool {
self.wireguard_constraints()
.daita_use_multihop_if_necessary
- .is_only_and(|enabled| enabled)
+ // The default value is `Any`, which means that we need to check the intersection.
+ .intersection(Constraint::Only(true))
+ .is_some()
}
fn singlehop(&self) -> bool {
!self.wireguard_constraints().multihop()
diff --git a/mullvad-relay-selector/tests/relay_selector.rs b/mullvad-relay-selector/tests/relay_selector.rs
index 1ce69b0591..d80fe359e9 100644
--- a/mullvad-relay-selector/tests/relay_selector.rs
+++ b/mullvad-relay-selector/tests/relay_selector.rs
@@ -96,6 +96,27 @@ static RELAYS: LazyLock<RelayList> = LazyLock::new(|| RelayList {
location: DUMMY_LOCATION.clone(),
},
Relay {
+ hostname: "se11-wireguard".to_string(),
+ ipv4_addr_in: "185.213.154.69".parse().unwrap(),
+ ipv6_addr_in: Some("2a03:1b20:5:f011::a11f".parse().unwrap()),
+ overridden_ipv4: false,
+ overridden_ipv6: false,
+ include_in_country: true,
+ active: true,
+ owned: false,
+ provider: "provider2".to_string(),
+ weight: 1,
+ endpoint_data: RelayEndpointData::Wireguard(WireguardRelayEndpointData {
+ public_key: PublicKey::from_base64(
+ "BLNHNoGO88LjV/wDBa7CUUwUzPq/fO2UwcGLy56hKy4=",
+ )
+ .unwrap(),
+ daita: true,
+ shadowsocks_extra_addr_in: vec![],
+ }),
+ location: DUMMY_LOCATION.clone(),
+ },
+ Relay {
hostname: "se-got-001".to_string(),
ipv4_addr_in: "185.213.154.131".parse().unwrap(),
ipv6_addr_in: None,
@@ -1401,6 +1422,59 @@ fn test_daita_any_tunnel_protocol() {
);
}
+/// Always use smart routing to select a DAITA-enabled entry relay if both smart routing and multihop is enabled.
+/// This applies even if the entry is set explicitly.
+/// DAITA is a core privacy feature
+#[test]
+fn test_daita_smart_routing_overrides_multihop() {
+ let relay_selector = RelaySelector::from_list(SelectorConfig::default(), RELAYS.clone());
+ let query = RelayQueryBuilder::new()
+ .wireguard()
+ .daita()
+ .daita_use_multihop_if_necessary(true)
+ .multihop()
+ // Set the entry to a relay that explicitly does *not* support DAITA.
+ // Later, we check that the smart routing disregards this choice and selects a DAITA-enabled
+ // relay instead.
+ .entry(NON_DAITA_RELAY_LOCATION.clone())
+ .build();
+
+ for _ in 0..100 {
+ // Make sure a DAITA-enabled relay is always selected due to smart routing.
+ let relay = relay_selector
+ .get_relay_by_query(query.clone())
+ .expect("Expected to find a relay with daita_use_multihop_if_necessary");
+ match relay {
+ GetRelay::Wireguard {
+ inner: WireguardConfig::Multihop { entry, exit: _ },
+ ..
+ } => {
+ assert!(supports_daita(&entry), "entry relay must support DAITA");
+ }
+ wrong_relay => panic!(
+ "Relay selector should have picked two Wireguard relays, instead chose {wrong_relay:?}"
+ ),
+ }
+ }
+
+ // Assert that disabling smart routing for this query will fail to generate a valid multihop
+ // config, thus blocking the user.
+ let query = RelayQueryBuilder::new()
+ .wireguard()
+ .daita()
+ .daita_use_multihop_if_necessary(false)
+ .multihop()
+ .entry(NON_DAITA_RELAY_LOCATION.clone())
+ .build();
+
+ let relay = relay_selector.get_relay_by_query(query);
+
+ assert!(
+ relay.is_err(),
+ "expected there to be no valid multihop configuration! Instead got {relay:#?}"
+ );
+}
+
/// Always select a WireGuard relay when multihop is enabled
/// Multihop is a core privacy feature
#[test]