Skip to content

Commit f7f3661

Browse files
committed
Merge branch 'ignore-specific-obfs-settings'
2 parents 5feceae + 240a1f7 commit f7f3661

File tree

6 files changed

+98
-50
lines changed

6 files changed

+98
-50
lines changed

CHANGELOG.md

+2
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,8 @@ Line wrap the file at 100 chars. Th
2626
- Add DAITA (Defence against AI-guided Traffic Analysis) setting for Linux and macOS.
2727

2828
### Changed
29+
- Ignore obfuscation protocol constraints when the obfuscation mode is set to auto.
30+
2931
#### macOS
3032
- Enable quantum resistant tunnels by default (when set to `auto`).
3133

mullvad-api/src/lib.rs

+1-2
Original file line numberDiff line numberDiff line change
@@ -139,8 +139,7 @@ pub struct ApiEndpoint {
139139
/// Whether bridges/proxies can be used to access the API or not. This is
140140
/// useful primarily for testing purposes.
141141
///
142-
/// * If `force_direct` is `true`, bridges and proxies will not be used to
143-
/// reach the API.
142+
/// * If `force_direct` is `true`, bridges and proxies will not be used to reach the API.
144143
/// * If `force_direct` is `false`, bridges and proxies can be used to reach the API.
145144
///
146145
/// # Note

mullvad-relay-selector/src/relay_selector/helpers.rs

+9-10
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ pub fn pick_random_relay_weighted<RelayType>(
5858
}
5959

6060
pub fn get_udp2tcp_obfuscator(
61-
obfuscation_settings_constraint: &Constraint<Udp2TcpObfuscationSettings>,
61+
obfuscation_settings_constraint: &Udp2TcpObfuscationSettings,
6262
udp2tcp_ports: &[u16],
6363
relay: Relay,
6464
endpoint: &MullvadWireguardEndpoint,
@@ -73,17 +73,16 @@ pub fn get_udp2tcp_obfuscator(
7373
}
7474

7575
pub fn get_udp2tcp_obfuscator_port(
76-
obfuscation_settings_constraint: &Constraint<Udp2TcpObfuscationSettings>,
76+
obfuscation_settings: &Udp2TcpObfuscationSettings,
7777
udp2tcp_ports: &[u16],
7878
) -> Option<u16> {
79-
match obfuscation_settings_constraint {
80-
Constraint::Only(obfuscation_settings) if obfuscation_settings.port.is_only() => {
81-
udp2tcp_ports
82-
.iter()
83-
.find(|&candidate| obfuscation_settings.port == Constraint::Only(*candidate))
84-
.copied()
85-
}
79+
if let Constraint::Only(desired_port) = obfuscation_settings.port {
80+
udp2tcp_ports
81+
.iter()
82+
.find(|&candidate| desired_port == *candidate)
83+
.copied()
84+
} else {
8685
// There are no specific obfuscation settings to take into consideration in this case.
87-
Constraint::Any | Constraint::Only(_) => udp2tcp_ports.choose(&mut thread_rng()).copied(),
86+
udp2tcp_ports.choose(&mut thread_rng()).copied()
8887
}
8988
}

mullvad-relay-selector/src/relay_selector/mod.rs

+9-14
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ pub mod query;
99
use chrono::{DateTime, Local};
1010
use itertools::Itertools;
1111
use once_cell::sync::Lazy;
12+
use query::ObfuscationQuery;
1213
use rand::{seq::IteratorRandom, thread_rng};
1314
use std::{
1415
path::Path,
@@ -24,7 +25,7 @@ use mullvad_types::{
2425
relay_constraints::{
2526
BridgeSettings, BridgeState, InternalBridgeConstraints, ObfuscationSettings,
2627
OpenVpnConstraints, RelayConstraints, RelayOverride, RelaySettings, ResolvedBridgeSettings,
27-
SelectedObfuscation, WireguardConstraints,
28+
WireguardConstraints,
2829
},
2930
relay_list::{Relay, RelayEndpointData, RelayList},
3031
settings::Settings,
@@ -342,8 +343,7 @@ impl<'a> From<NormalSelectorConfig<'a>> for RelayQuery {
342343
ip_version,
343344
use_multihop: Constraint::Only(use_multihop),
344345
entry_location,
345-
obfuscation: obfuscation_settings.selected_obfuscation,
346-
udp2tcp_port: Constraint::Only(obfuscation_settings.udp2tcp.clone()),
346+
obfuscation: ObfuscationQuery::from(obfuscation_settings),
347347
daita: Constraint::Only(daita),
348348
}
349349
}
@@ -790,23 +790,18 @@ impl RelaySelector {
790790
endpoint: &MullvadWireguardEndpoint,
791791
parsed_relays: &ParsedRelays,
792792
) -> Result<Option<SelectedObfuscator>, Error> {
793-
match query.wireguard_constraints.obfuscation {
794-
SelectedObfuscation::Off | SelectedObfuscation::Auto => Ok(None),
795-
SelectedObfuscation::Udp2Tcp => {
793+
match &query.wireguard_constraints.obfuscation {
794+
ObfuscationQuery::Off | ObfuscationQuery::Auto => Ok(None),
795+
ObfuscationQuery::Udp2tcp { port } => {
796796
let obfuscator_relay = match relay {
797797
WireguardConfig::Singlehop { exit } => exit,
798798
WireguardConfig::Multihop { entry, .. } => entry,
799799
};
800800
let udp2tcp_ports = &parsed_relays.parsed_list().wireguard.udp2tcp_ports;
801801

802-
helpers::get_udp2tcp_obfuscator(
803-
&query.wireguard_constraints.udp2tcp_port,
804-
udp2tcp_ports,
805-
obfuscator_relay,
806-
endpoint,
807-
)
808-
.map(Some)
809-
.ok_or(Error::NoObfuscator)
802+
helpers::get_udp2tcp_obfuscator(port, udp2tcp_ports, obfuscator_relay, endpoint)
803+
.map(Some)
804+
.ok_or(Error::NoObfuscator)
810805
}
811806
}
812807
}

mullvad-relay-selector/src/relay_selector/query.rs

+68-13
Original file line numberDiff line numberDiff line change
@@ -32,8 +32,8 @@ use crate::AdditionalWireguardConstraints;
3232
use mullvad_types::{
3333
constraints::Constraint,
3434
relay_constraints::{
35-
BridgeConstraints, LocationConstraint, OpenVpnConstraints, Ownership, Providers,
36-
RelayConstraints, RelaySettings, SelectedObfuscation, TransportPort,
35+
BridgeConstraints, LocationConstraint, ObfuscationSettings, OpenVpnConstraints, Ownership,
36+
Providers, RelayConstraints, RelaySettings, SelectedObfuscation, TransportPort,
3737
Udp2TcpObfuscationSettings, WireguardConstraints,
3838
},
3939
Intersection,
@@ -150,11 +150,50 @@ pub struct WireguardRelayQuery {
150150
pub ip_version: Constraint<IpVersion>,
151151
pub use_multihop: Constraint<bool>,
152152
pub entry_location: Constraint<LocationConstraint>,
153-
pub obfuscation: SelectedObfuscation,
154-
pub udp2tcp_port: Constraint<Udp2TcpObfuscationSettings>,
153+
pub obfuscation: ObfuscationQuery,
155154
pub daita: Constraint<bool>,
156155
}
157156

157+
#[derive(Default, Debug, Clone, Eq, PartialEq)]
158+
pub enum ObfuscationQuery {
159+
Off,
160+
#[default]
161+
Auto,
162+
Udp2tcp {
163+
port: Udp2TcpObfuscationSettings,
164+
},
165+
}
166+
167+
impl From<ObfuscationSettings> for ObfuscationQuery {
168+
/// A query for obfuscation settings.
169+
///
170+
/// Note that this drops obfuscation protocol specific constraints from [`ObfuscationSettings`]
171+
/// when the selected obfuscation type is auto.
172+
fn from(obfuscation: ObfuscationSettings) -> Self {
173+
match obfuscation.selected_obfuscation {
174+
SelectedObfuscation::Off => ObfuscationQuery::Off,
175+
SelectedObfuscation::Auto => ObfuscationQuery::Auto,
176+
SelectedObfuscation::Udp2Tcp => ObfuscationQuery::Udp2tcp {
177+
port: obfuscation.udp2tcp,
178+
},
179+
}
180+
}
181+
}
182+
183+
impl Intersection for ObfuscationQuery {
184+
fn intersection(self, other: Self) -> Option<Self> {
185+
match (self, other) {
186+
(ObfuscationQuery::Off, _) | (_, ObfuscationQuery::Off) => Some(ObfuscationQuery::Off),
187+
(ObfuscationQuery::Auto, other) | (other, ObfuscationQuery::Auto) => Some(other),
188+
(ObfuscationQuery::Udp2tcp { port: a }, ObfuscationQuery::Udp2tcp { port: b }) => {
189+
Some(ObfuscationQuery::Udp2tcp {
190+
port: a.intersection(b)?,
191+
})
192+
}
193+
}
194+
}
195+
}
196+
158197
impl WireguardRelayQuery {
159198
pub fn multihop(&self) -> bool {
160199
matches!(self.use_multihop, Constraint::Only(true))
@@ -168,8 +207,7 @@ impl WireguardRelayQuery {
168207
ip_version: Constraint::Any,
169208
use_multihop: Constraint::Any,
170209
entry_location: Constraint::Any,
171-
obfuscation: SelectedObfuscation::Auto,
172-
udp2tcp_port: Constraint::Any,
210+
obfuscation: ObfuscationQuery::Auto,
173211
daita: Constraint::Any,
174212
}
175213
}
@@ -310,7 +348,7 @@ pub mod builder {
310348
};
311349
use talpid_types::net::TunnelType;
312350

313-
use super::{BridgeQuery, RelayQuery};
351+
use super::{BridgeQuery, ObfuscationQuery, RelayQuery};
314352

315353
// Re-exports
316354
pub use mullvad_types::relay_constraints::{
@@ -505,8 +543,8 @@ pub mod builder {
505543
obfuscation: obfuscation.clone(),
506544
daita: self.protocol.daita,
507545
};
508-
self.query.wireguard_constraints.udp2tcp_port = Constraint::Only(obfuscation);
509-
self.query.wireguard_constraints.obfuscation = SelectedObfuscation::Udp2Tcp;
546+
self.query.wireguard_constraints.obfuscation =
547+
ObfuscationQuery::Udp2tcp { port: obfuscation };
510548
RelayQueryBuilder {
511549
query: self.query,
512550
protocol,
@@ -519,8 +557,9 @@ pub mod builder {
519557
/// protocol should use to connect to a relay.
520558
pub fn udp2tcp_port(mut self, port: u16) -> Self {
521559
self.protocol.obfuscation.port = Constraint::Only(port);
522-
self.query.wireguard_constraints.udp2tcp_port =
523-
Constraint::Only(self.protocol.obfuscation.clone());
560+
self.query.wireguard_constraints.obfuscation = ObfuscationQuery::Udp2tcp {
561+
port: self.protocol.obfuscation.clone(),
562+
};
524563
self
525564
}
526565
}
@@ -639,10 +678,13 @@ pub mod builder {
639678

640679
#[cfg(test)]
641680
mod test {
642-
use mullvad_types::constraints::Constraint;
681+
use mullvad_types::{
682+
constraints::Constraint,
683+
relay_constraints::{ObfuscationSettings, SelectedObfuscation, Udp2TcpObfuscationSettings},
684+
};
643685
use proptest::prelude::*;
644686

645-
use super::Intersection;
687+
use super::{Intersection, ObfuscationQuery};
646688

647689
// Define proptest combinators for the `Constraint` type.
648690

@@ -719,5 +761,18 @@ mod test {
719761
};
720762
prop_assert_eq!(left, right);
721763
}
764+
765+
/// When obfuscation is set to automatic in [`ObfuscationSettings`], the query should not
766+
/// contain any specific obfuscation protocol settings.
767+
#[test]
768+
fn test_auto_obfuscation_settings(port in constraint(proptest::arbitrary::any::<u16>())) {
769+
let query = ObfuscationQuery::from(ObfuscationSettings {
770+
selected_obfuscation: SelectedObfuscation::Auto,
771+
udp2tcp: Udp2TcpObfuscationSettings {
772+
port,
773+
},
774+
});
775+
assert_eq!(query, ObfuscationQuery::Auto);
776+
}
722777
}
723778
}

mullvad-relay-selector/tests/relay_selector.rs

+9-11
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ use talpid_types::net::{
1111
};
1212

1313
use mullvad_relay_selector::{
14-
query::{builder::RelayQueryBuilder, BridgeQuery, OpenVpnRelayQuery},
14+
query::{builder::RelayQueryBuilder, BridgeQuery, ObfuscationQuery, OpenVpnRelayQuery},
1515
Error, GetRelay, RelaySelector, RuntimeParameters, SelectorConfig, WireguardConfig,
1616
RETRY_ORDER,
1717
};
@@ -20,7 +20,7 @@ use mullvad_types::{
2020
endpoint::MullvadEndpoint,
2121
relay_constraints::{
2222
BridgeConstraints, BridgeState, GeographicLocationConstraint, Ownership, Providers,
23-
SelectedObfuscation, TransportPort,
23+
TransportPort,
2424
},
2525
relay_list::{
2626
BridgeEndpointData, OpenVpnEndpoint, OpenVpnEndpointData, Relay, RelayEndpointData,
@@ -311,10 +311,10 @@ fn test_retry_order() {
311311
.wireguard_constraints
312312
.port
313313
.matches_eq(&endpoint.peer.endpoint.port()));
314-
assert!(match query.wireguard_constraints.obfuscation {
315-
SelectedObfuscation::Auto => true,
316-
SelectedObfuscation::Off => obfuscator.is_none(),
317-
SelectedObfuscation::Udp2Tcp => obfuscator.is_some(),
314+
assert!(match &query.wireguard_constraints.obfuscation {
315+
ObfuscationQuery::Auto => true,
316+
ObfuscationQuery::Off => obfuscator.is_none(),
317+
ObfuscationQuery::Udp2tcp { .. } => obfuscator.is_some(),
318318
});
319319
}
320320
GetRelay::OpenVpn {
@@ -737,15 +737,13 @@ fn test_selecting_wireguard_endpoint_with_udp2tcp_obfuscation() {
737737
/// multihop is explicitly turned off. Assert that the relay selector does *not* return an
738738
/// obfuscator config.
739739
///
740-
/// # Note
741-
/// This is a highly specific test which details how the relay selector should behave at the time of
742-
/// writing this test. The cost (in latency primarily) of using obfuscation is deemed to be too high
743-
/// to enable it as an auto-configuration.
740+
/// [`RelaySelector::get_relay`] may still enable obfuscation if it is present in [`RETRY_ORDER`].
744741
#[test]
745742
fn test_selecting_wireguard_endpoint_with_auto_obfuscation() {
746743
let relay_selector = default_relay_selector();
744+
747745
let mut query = RelayQueryBuilder::new().wireguard().build();
748-
query.wireguard_constraints.obfuscation = SelectedObfuscation::Auto;
746+
query.wireguard_constraints.obfuscation = ObfuscationQuery::Auto;
749747

750748
for _ in 0..100 {
751749
let relay = relay_selector.get_relay_by_query(query.clone()).unwrap();

0 commit comments

Comments
 (0)