diff options
| -rw-r--r-- | gui/src/main/daemon-rpc.ts | 13 | ||||
| -rw-r--r-- | mullvad-cli/src/cmds/relay.rs | 49 | ||||
| -rw-r--r-- | mullvad-daemon/src/relays.rs | 66 | ||||
| -rw-r--r-- | mullvad-management-interface/proto/management_interface.proto | 12 | ||||
| -rw-r--r-- | mullvad-management-interface/src/types.rs | 43 | ||||
| -rw-r--r-- | mullvad-types/src/relay_constraints.rs | 33 |
6 files changed, 136 insertions, 80 deletions
diff --git a/gui/src/main/daemon-rpc.ts b/gui/src/main/daemon-rpc.ts index 1c3e9a67ba..24594c5e4d 100644 --- a/gui/src/main/daemon-rpc.ts +++ b/gui/src/main/daemon-rpc.ts @@ -1154,8 +1154,12 @@ function convertFromOpenVpnConstraints( function convertFromWireguardConstraints( constraints: grpcTypes.WireguardConstraints, ): IWireguardConstraints { - const port = convertFromConstraint(constraints.getPort()); - return { port }; + const transportPort = convertFromConstraint(constraints.getPort()); + if (transportPort !== 'any' && 'only' in transportPort) { + const port = convertFromConstraint(transportPort.only.getPort()); + return { port }; + } + return { port: 'any' }; } function convertFromTunnelTypeConstraint( @@ -1260,7 +1264,10 @@ function convertToWireguardConstraints( const wireguardConstraints = new grpcTypes.WireguardConstraints(); const port = liftConstraint(constraint.port); if (port) { - wireguardConstraints.setPort(port); + const portConstraints = new grpcTypes.TransportPort(); + portConstraints.setPort(port); + portConstraints.setProtocol(grpcTypes.TransportProtocol.UDP); + wireguardConstraints.setPort(portConstraints); } return wireguardConstraints; } diff --git a/mullvad-cli/src/cmds/relay.rs b/mullvad-cli/src/cmds/relay.rs index e4fdfff478..64cb4c3e4b 100644 --- a/mullvad-cli/src/cmds/relay.rs +++ b/mullvad-cli/src/cmds/relay.rs @@ -12,7 +12,7 @@ use mullvad_management_interface::types::{ connection_config::{self, OpenvpnConfig, WireguardConfig}, relay_settings, relay_settings_update, ConnectionConfig, CustomRelaySettings, IpVersion, IpVersionConstraint, NormalRelaySettingsUpdate, OpenvpnConstraints, ProviderUpdate, - RelayListCountry, RelayLocation, RelaySettingsUpdate, TransportProtocol, + RelayListCountry, RelayLocation, RelaySettingsUpdate, TransportPort, TransportProtocol, TransportProtocolConstraint, TunnelType, TunnelTypeConstraint, TunnelTypeUpdate, WireguardConstraints, }; @@ -164,15 +164,18 @@ impl Command for Relay { .arg( clap::Arg::with_name("port") .help("Port to use. Either 'any' or a specific port") - .required(true) + .long("port") + .takes_value(true) + .requires("transport protocol"), ) .arg( clap::Arg::with_name("transport protocol") .help("Transport protocol. If TCP is selected, traffic is \ sent over TCP using a udp-over-tcp proxy") .long("protocol") - .default_value("any") - .possible_values(&["any", "udp", "tcp"]), + .takes_value(true) + .possible_values(&["udp", "tcp"]) + .requires("port"), ) .arg( clap::Arg::with_name("ip version") @@ -535,8 +538,19 @@ impl Relay { } async fn set_wireguard_constraints(&self, matches: &clap::ArgMatches<'_>) -> Result<()> { - let port = parse_port_constraint(matches.value_of("port").unwrap())?; - let protocol = parse_protocol_constraint(matches.value_of("transport protocol").unwrap()); + let protocol = matches.value_of("transport protocol").map(parse_protocol); + let port = match matches.value_of("port").map(parse_port_constraint) { + None => None, + Some(Err(error)) => return Err(error), + Some(Ok(Constraint::Any)) => Some(TransportPort { + protocol: protocol.unwrap() as i32, + port: 0, + }), + Some(Ok(Constraint::Only(port))) => Some(TransportPort { + protocol: protocol.unwrap() as i32, + port: u32::from(port), + }), + }; let ip_version = parse_ip_version_constraint(matches.value_of("ip version").unwrap()); let entry_location = parse_entry_location_constraint(matches.values_of("entry location").unwrap()); @@ -545,12 +559,7 @@ impl Relay { r#type: Some(relay_settings_update::Type::Normal( NormalRelaySettingsUpdate { wireguard_constraints: Some(WireguardConstraints { - port: port.unwrap_or(0) as u32, - protocol: protocol - .option() - .map(|protocol| TransportProtocolConstraint { - protocol: protocol as i32, - }), + port, ip_version: ip_version.option().map(|protocol| IpVersionConstraint { protocol: protocol as i32, }), @@ -750,12 +759,12 @@ impl Relay { if let Some(constraints) = constraints { let mut out = format!( "{} over {} over {}", - Self::format_port(constraints.port), + Self::format_port(constraints.port.as_ref().map(|port| port.port).unwrap_or(0)), Self::format_transport_protocol( constraints - .protocol + .port .clone() - .map(|protocol| TransportProtocol::from_i32(protocol.protocol).unwrap()) + .map(|port| TransportProtocol::from_i32(port.protocol).unwrap()) ), Self::format_ip_version( constraints @@ -832,8 +841,14 @@ fn parse_port_constraint(raw_port: &str) -> Result<Constraint<u16>> { fn parse_protocol_constraint(raw_protocol: &str) -> Constraint<TransportProtocol> { match raw_protocol { "any" => Constraint::Any, - "udp" => Constraint::Only(TransportProtocol::Udp), - "tcp" => Constraint::Only(TransportProtocol::Tcp), + protocol => Constraint::Only(parse_protocol(protocol)), + } +} + +fn parse_protocol(raw_protocol: &str) -> TransportProtocol { + match raw_protocol { + "udp" => TransportProtocol::Udp, + "tcp" => TransportProtocol::Tcp, _ => unreachable!(), } } diff --git a/mullvad-daemon/src/relays.rs b/mullvad-daemon/src/relays.rs index 019c6ac2c1..186e4ed76b 100644 --- a/mullvad-daemon/src/relays.rs +++ b/mullvad-daemon/src/relays.rs @@ -15,7 +15,7 @@ use mullvad_types::{ location::Location, relay_constraints::{ BridgeState, Constraint, InternalBridgeConstraints, LocationConstraint, Match, - OpenVpnConstraints, Providers, RelayConstraints, Set, WireguardConstraints, + OpenVpnConstraints, Providers, RelayConstraints, Set, TransportPort, WireguardConstraints, }, relay_list::{OpenVpnEndpointData, Relay, RelayList, RelayTunnels, WireguardEndpointData}, }; @@ -53,8 +53,10 @@ const EXPONENTIAL_BACKOFF_FACTOR: u32 = 8; const DEFAULT_WIREGUARD_PORT: u16 = 51820; const WIREGUARD_EXIT_CONSTRAINTS: WireguardConstraints = WireguardConstraints { - port: Constraint::Only(DEFAULT_WIREGUARD_PORT), - protocol: Constraint::Only(TransportProtocol::Udp), + port: Constraint::Only(TransportPort { + protocol: TransportProtocol::Udp, + port: Constraint::Only(DEFAULT_WIREGUARD_PORT), + }), ip_version: Constraint::Only(IpVersion::V4), entry_location: None, }; @@ -388,7 +390,11 @@ impl RelaySelector { } if relay_constraints.wireguard_constraints.port.is_any() { - relay_constraints.wireguard_constraints.port = preferred_port; + relay_constraints.wireguard_constraints.port = + Constraint::Only(TransportPort { + protocol: preferred_protocol, + port: preferred_port, + }); } relay_constraints.tunnel_protocol = Constraint::Only(preferred_tunnel); @@ -408,19 +414,17 @@ impl RelaySelector { } } Constraint::Only(TunnelType::Wireguard) => { - if relay_constraints.wireguard_constraints.protocol - != Constraint::Only(TransportProtocol::Tcp) - { - relay_constraints.wireguard_constraints = - original_constraints.wireguard_constraints.clone(); - // This ensures that if after the first 2 failed attempts the daemon does not - // connect, then afterwards 2 of each 4 successive attempts will try to connect - // on port 53. - if retry_attempt % 4 > 1 - && relay_constraints.wireguard_constraints.port.is_any() - { - relay_constraints.wireguard_constraints.port = Constraint::Only(53); - } + relay_constraints.wireguard_constraints = + original_constraints.wireguard_constraints.clone(); + // This ensures that if after the first 2 failed attempts the daemon does not + // connect, then afterwards 2 of each 4 successive attempts will try to connect + // on port 53. + if retry_attempt % 4 > 1 && relay_constraints.wireguard_constraints.port.is_any() { + relay_constraints.wireguard_constraints.port = + Constraint::Only(TransportPort { + protocol: TransportProtocol::Udp, + port: Constraint::Only(53), + }); } } } @@ -757,9 +761,9 @@ impl RelaySelector { tunnels: &RelayTunnels, constraints: &WireguardConstraints, ) -> Vec<WireguardEndpointData> { - if constraints.protocol == Constraint::Only(TransportProtocol::Tcp) { - match constraints.port { - Constraint::Only(port) => { + match constraints.port { + Constraint::Only(port) if port.protocol == TransportProtocol::Tcp => { + if let Constraint::Only(port) = port.port { if !WIREGUARD_TCP_PORTS .iter() .any(|range| port >= range.0 && port <= range.1) @@ -767,9 +771,9 @@ impl RelaySelector { return vec![]; } } - _ => (), + return tunnels.wireguard.clone(); } - return tunnels.wireguard.clone(); + _ => (), } tunnels .wireguard @@ -881,7 +885,10 @@ impl RelaySelector { public_key: data.public_key, endpoint: SocketAddr::new(host, port), allowed_ips: all_of_the_internet(), - protocol: constraints.protocol.unwrap_or(TransportProtocol::Udp), + protocol: constraints + .port + .map(|port| port.protocol) + .unwrap_or(TransportProtocol::Udp), }; Some(MullvadEndpoint::Wireguard { peer: peer_config, @@ -907,12 +914,19 @@ impl RelaySelector { data: &WireguardEndpointData, constraints: &WireguardConstraints, ) -> Option<u16> { - let port_ranges = match constraints.protocol { - Constraint::Only(TransportProtocol::Tcp) => &WIREGUARD_TCP_PORTS[..], + let port_ranges = match constraints.port { + Constraint::Only(port) if port.protocol == TransportProtocol::Tcp => { + &WIREGUARD_TCP_PORTS[..] + } _ => &data.port_ranges, }; - match constraints.port { + match constraints + .port + .as_ref() + .map(|port| port.port) + .unwrap_or(Constraint::Any) + { Constraint::Any => { let get_port_amount = |range: &(u16, u16)| -> u64 { (1 + range.1 - range.0) as u64 }; diff --git a/mullvad-management-interface/proto/management_interface.proto b/mullvad-management-interface/proto/management_interface.proto index 1d3b40258b..489b8982d3 100644 --- a/mullvad-management-interface/proto/management_interface.proto +++ b/mullvad-management-interface/proto/management_interface.proto @@ -317,6 +317,11 @@ message TransportProtocolConstraint { TransportProtocol protocol = 1; } +message TransportPort { + TransportProtocol protocol = 1; + uint32 port = 2; +} + message OpenvpnConstraints { uint32 port = 1; TransportProtocolConstraint protocol = 2; @@ -332,10 +337,9 @@ message IpVersionConstraint { } message WireguardConstraints { - uint32 port = 1; - TransportProtocolConstraint protocol = 2; - IpVersionConstraint ip_version = 3; - RelayLocation entry_location = 4; + TransportPort port = 1; + IpVersionConstraint ip_version = 2; + RelayLocation entry_location = 3; } message CustomRelaySettings { diff --git a/mullvad-management-interface/src/types.rs b/mullvad-management-interface/src/types.rs index 79a450e2c3..cf3a624d3d 100644 --- a/mullvad-management-interface/src/types.rs +++ b/mullvad-management-interface/src/types.rs @@ -319,6 +319,15 @@ impl From<IpVersion> for IpVersionConstraint { } } +impl From<mullvad_types::relay_constraints::TransportPort> for TransportPort { + fn from(port: mullvad_types::relay_constraints::TransportPort) -> Self { + TransportPort { + protocol: TransportProtocol::from(port.protocol) as i32, + port: port.port.map(u32::from).unwrap_or(0), + } + } +} + impl From< mullvad_types::relay_constraints::Constraint< @@ -491,14 +500,11 @@ impl From<mullvad_types::relay_constraints::RelaySettings> for RelaySettings { }), wireguard_constraints: Some(WireguardConstraints { - port: u32::from(constraints.wireguard_constraints.port.unwrap_or(0)), - protocol: constraints + port: constraints .wireguard_constraints - .protocol - .as_ref() + .port .option() - .map(|protocol| TransportProtocol::from(*protocol)) - .map(TransportProtocolConstraint::from), + .map(TransportPort::from), ip_version: constraints .wireguard_constraints .ip_version @@ -892,16 +898,22 @@ impl TryFrom<RelaySettingsUpdate> for mullvad_types::relay_constraints::RelaySet } else { None }; - let wireguard_transport_protocol = + let wireguard_transport_port = if let Some(ref constraints) = settings.wireguard_constraints { - match &constraints.protocol { - Some(constraint) => Some( - TransportProtocol::from_i32(constraint.protocol) + match &constraints.port { + Some(port) => { + let protocol = TransportProtocol::from_i32(port.protocol) .ok_or(FromProtobufTypeError::InvalidArgument( "invalid transport protocol", ))? - .into(), - ), + .into(); + let port = if port.port != 0 { + Constraint::Only(port.port as u16) + } else { + Constraint::Any + }; + Some(mullvad_constraints::TransportPort { protocol, port }) + } None => None, } } else { @@ -950,12 +962,7 @@ impl TryFrom<RelaySettingsUpdate> for mullvad_types::relay_constraints::RelaySet tunnel_protocol, wireguard_constraints: settings.wireguard_constraints.map(|constraints| { mullvad_constraints::WireguardConstraints { - port: if constraints.port != 0 { - Constraint::Only(constraints.port as u16) - } else { - Constraint::Any - }, - protocol: Constraint::from(wireguard_transport_protocol), + port: Constraint::from(wireguard_transport_port), ip_version: Constraint::from(ip_version), entry_location: constraints.entry_location.map( Constraint::< diff --git a/mullvad-types/src/relay_constraints.rs b/mullvad-types/src/relay_constraints.rs index 100daa2088..5e300716b9 100644 --- a/mullvad-types/src/relay_constraints.rs +++ b/mullvad-types/src/relay_constraints.rs @@ -445,6 +445,12 @@ impl Match<WireguardEndpointData> for TunnelConstraints { } } +#[derive(Debug, Copy, Clone, Eq, PartialEq, Deserialize, Serialize)] +pub struct TransportPort { + pub protocol: TransportProtocol, + pub port: Constraint<u16>, +} + /// [`Constraint`]s applicable to OpenVPN relay servers. #[derive(Debug, Default, Copy, Clone, Eq, PartialEq, Deserialize, Serialize)] pub struct OpenVpnConstraints { @@ -476,8 +482,7 @@ impl Match<OpenVpnEndpointData> for OpenVpnConstraints { #[derive(Debug, Default, Clone, Eq, PartialEq, Deserialize, Serialize)] #[serde(default)] pub struct WireguardConstraints { - pub port: Constraint<u16>, - pub protocol: Constraint<TransportProtocol>, + pub port: Constraint<TransportPort>, pub ip_version: Constraint<IpVersion>, pub entry_location: Option<Constraint<LocationConstraint>>, } @@ -486,12 +491,13 @@ impl fmt::Display for WireguardConstraints { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> { match self.port { Constraint::Any => write!(f, "any port")?, - Constraint::Only(port) => write!(f, "port {}", port)?, - } - write!(f, " over ")?; - match self.protocol { - Constraint::Any => write!(f, "any protocol")?, - Constraint::Only(protocol) => write!(f, "{}", protocol)?, + Constraint::Only(port) => { + match port.port { + Constraint::Any => write!(f, "any port")?, + Constraint::Only(port) => write!(f, "port {}", port)?, + } + write!(f, " over {}", port.protocol)?; + } } write!(f, " over ")?; match self.ip_version { @@ -510,10 +516,13 @@ impl Match<WireguardEndpointData> for WireguardConstraints { fn matches(&self, endpoint: &WireguardEndpointData) -> bool { match self.port { Constraint::Any => true, - Constraint::Only(port) => endpoint - .port_ranges - .iter() - .any(|range| (port >= range.0 && port <= range.1)), + Constraint::Only(port) => match port.port { + Constraint::Any => true, + Constraint::Only(port) => endpoint + .port_ranges + .iter() + .any(|range| (port >= range.0 && port <= range.1)), + }, } } } |
