diff options
| author | Emīls Piņķis <emils@mullvad.net> | 2019-01-14 13:29:16 +0000 |
|---|---|---|
| committer | Emīls Piņķis <emils@mullvad.net> | 2019-01-30 13:41:31 +0000 |
| commit | 7a99bd987ee258ee54a8cb28ab4f580ac03ffe86 (patch) | |
| tree | 0d7fa957b2b321c89a33bbb2382f16e5068e4333 | |
| parent | 4e2b2ff81704fdab21b269948c3ebf2a9f65b07c (diff) | |
| download | mullvadvpn-7a99bd987ee258ee54a8cb28ab4f580ac03ffe86.tar.xz mullvadvpn-7a99bd987ee258ee54a8cb28ab4f580ac03ffe86.zip | |
Refactor mullvad types
| -rw-r--r-- | mullvad-cli/src/cmds/relay.rs | 39 | ||||
| -rw-r--r-- | mullvad-cli/src/cmds/tunnel.rs | 32 | ||||
| -rw-r--r-- | mullvad-daemon/src/lib.rs | 44 | ||||
| -rw-r--r-- | mullvad-daemon/src/management_interface.rs | 8 | ||||
| -rw-r--r-- | mullvad-daemon/src/relays.rs | 14 | ||||
| -rw-r--r-- | mullvad-ipc-client/src/lib.rs | 9 | ||||
| -rw-r--r-- | mullvad-types/Cargo.toml | 1 | ||||
| -rw-r--r-- | mullvad-types/src/custom_tunnel.rs | 81 | ||||
| -rw-r--r-- | mullvad-types/src/endpoint.rs | 111 | ||||
| -rw-r--r-- | mullvad-types/src/lib.rs | 1 | ||||
| -rw-r--r-- | mullvad-types/src/relay_constraints.rs | 3 | ||||
| -rw-r--r-- | mullvad-types/src/relay_list.rs | 49 | ||||
| -rw-r--r-- | mullvad-types/src/settings.rs | 36 |
13 files changed, 352 insertions, 76 deletions
diff --git a/mullvad-cli/src/cmds/relay.rs b/mullvad-cli/src/cmds/relay.rs index 5acee6fd39..2f3d276fce 100644 --- a/mullvad-cli/src/cmds/relay.rs +++ b/mullvad-cli/src/cmds/relay.rs @@ -1,17 +1,15 @@ use crate::{new_rpc_client, Command, Result, ResultExt}; use clap::value_t; -use std::str::FromStr; +use std::{net::Ipv4Addr, str::FromStr}; use mullvad_types::{ relay_constraints::{ Constraint, LocationConstraint, OpenVpnConstraints, RelayConstraintsUpdate, RelaySettingsUpdate, TunnelConstraints, }, - CustomTunnelEndpoint, -}; -use talpid_types::net::{ - OpenVpnEndpointData, TransportProtocol, TunnelEndpointData, WireguardEndpointData, + ConnectionConfig, CustomTunnelEndpoint, }; +use talpid_types::net::{openvpn, Endpoint, TransportProtocol}; pub struct Relay; @@ -57,6 +55,16 @@ impl Command for Relay { .index(4) .default_value("udp") .possible_values(&["udp", "tcp"]), + ) + .arg( + clap::Arg::with_name("username") + .help("Username to be used with the OpenVpn relay") + .index(5), + ) + .arg( + clap::Arg::with_name("password") + .help("Password to be used with the OpenVpn relay") + .index(6), ), ) .subcommand( @@ -146,17 +154,26 @@ impl Relay { fn set_custom(&self, matches: &clap::ArgMatches) -> Result<()> { let host = value_t!(matches.value_of("host"), String).unwrap_or_else(|e| e.exit()); let port = value_t!(matches.value_of("port"), u16).unwrap_or_else(|e| e.exit()); - let tunnel = match matches.value_of("tunnel").unwrap() { - "openvpn" => TunnelEndpointData::OpenVpn(OpenVpnEndpointData { - port, - protocol: value_t!(matches.value_of("protocol"), TransportProtocol).unwrap(), - }), + let config = match matches.value_of("tunnel").unwrap() { + "openvpn" => { + let username = + value_t!(matches.value_of("username"), String).unwrap_or_else(|e| e.exit()); + let password = + value_t!(matches.value_of("password"), String).unwrap_or_else(|e| e.exit()); + let protocol = value_t!(matches.value_of("protocol"), TransportProtocol) + .unwrap_or_else(|e| e.exit()); + ConnectionConfig::OpenVpn(openvpn::ConnectionConfig { + endpoint: Endpoint::new(Ipv4Addr::UNSPECIFIED, port, protocol), + username, + password, + }) + } // TODO: Gather all the data to build a WireguardEndpointData properly. // "wireguard" => TunnelEndpointData::Wireguard(WireguardEndpointData { port }), _ => unreachable!("Invalid tunnel protocol"), }; self.update_constraints(RelaySettingsUpdate::CustomTunnelEndpoint( - CustomTunnelEndpoint { host, tunnel }, + CustomTunnelEndpoint::new(host, config), )) } diff --git a/mullvad-cli/src/cmds/tunnel.rs b/mullvad-cli/src/cmds/tunnel.rs index a45ae31c17..33e75d26d4 100644 --- a/mullvad-cli/src/cmds/tunnel.rs +++ b/mullvad-cli/src/cmds/tunnel.rs @@ -1,10 +1,8 @@ use crate::{new_rpc_client, Command, Result}; use clap::value_t; -use talpid_types::net::{ - LocalOpenVpnProxySettings, OpenVpnProxyAuth, OpenVpnProxySettings, - OpenVpnProxySettingsValidation, RemoteOpenVpnProxySettings, TunnelOptions, -}; +use mullvad_types::settings::TunnelOptions; +use talpid_types::net::openvpn; use std::net::{IpAddr, SocketAddr}; @@ -102,11 +100,13 @@ fn create_openvpn_proxy_subcommand() -> clap::App<'static, 'static> { .arg( clap::Arg::with_name("username") .help("Specifies the username for remote authentication") + .required(true) .index(3), ) .arg( clap::Arg::with_name("password") .help("Specifies the password for remote authentication") + .required(true) .index(4), ), ), @@ -207,9 +207,9 @@ impl Tunnel { fn process_openvpn_proxy_get() -> Result<()> { let tunnel_options = Self::get_tunnel_options()?; if let Some(proxy) = tunnel_options.openvpn.proxy { - if let OpenVpnProxySettings::Local(local_proxy) = proxy { + if let openvpn::ProxySettings::Local(local_proxy) = proxy { Self::print_local_proxy(&local_proxy) - } else if let OpenVpnProxySettings::Remote(remote_proxy) = proxy { + } else if let openvpn::ProxySettings::Remote(remote_proxy) = proxy { Self::print_remote_proxy(&remote_proxy) } else { unreachable!("unhandled proxy type"); @@ -220,14 +220,14 @@ impl Tunnel { Ok(()) } - fn print_local_proxy(proxy: &LocalOpenVpnProxySettings) { + fn print_local_proxy(proxy: &openvpn::LocalProxySettings) { println!("proxy: local"); println!(" local port: {}", proxy.port); println!(" peer IP: {}", proxy.peer.ip()); println!(" peer port: {}", proxy.peer.port()); } - fn print_remote_proxy(proxy: &RemoteOpenVpnProxySettings) { + fn print_remote_proxy(proxy: &openvpn::RemoteProxySettings) { println!("proxy: remote"); println!(" server IP: {}", proxy.address.ip()); println!(" server port: {}", proxy.address.port()); @@ -256,14 +256,14 @@ impl Tunnel { let remote_port = value_t!(args.value_of("remote-port"), u16).unwrap_or_else(|e| e.exit()); - let proxy = LocalOpenVpnProxySettings { + let proxy = openvpn::LocalProxySettings { port: local_port, peer: SocketAddr::new(remote_ip, remote_port), }; - let packed_proxy = OpenVpnProxySettings::Local(proxy); + let packed_proxy = openvpn::ProxySettings::Local(proxy); - if let Err(error) = OpenVpnProxySettingsValidation::validate(&packed_proxy) { + if let Err(error) = openvpn::ProxySettingsValidation::validate(&packed_proxy) { panic!(error); } @@ -278,21 +278,21 @@ impl Tunnel { let password = args.value_of("password"); let auth = match (username, password) { - (Some(username), Some(password)) => Some(OpenVpnProxyAuth { + (Some(username), Some(password)) => Some(openvpn::ProxyAuth { username: username.to_string(), password: password.to_string(), }), _ => None, }; - let proxy = RemoteOpenVpnProxySettings { + let proxy = openvpn::RemoteProxySettings { address: SocketAddr::new(remote_ip, remote_port), auth, }; - let packed_proxy = OpenVpnProxySettings::Remote(proxy); + let packed_proxy = openvpn::ProxySettings::Remote(proxy); - if let Err(error) = OpenVpnProxySettingsValidation::validate(&packed_proxy) { + if let Err(error) = openvpn::ProxySettingsValidation::validate(&packed_proxy) { panic!(error); } @@ -311,7 +311,7 @@ impl Tunnel { let tunnel_options = Self::get_tunnel_options()?; println!( "IPv6: {}", - if tunnel_options.enable_ipv6 { + if tunnel_options.generic.enable_ipv6 { "on" } else { "off" diff --git a/mullvad-daemon/src/lib.rs b/mullvad-daemon/src/lib.rs index 63dee4e536..eeb0f5755a 100644 --- a/mullvad-daemon/src/lib.rs +++ b/mullvad-daemon/src/lib.rs @@ -29,6 +29,7 @@ use log::{debug, error, info, warn}; use mullvad_rpc::{AccountsProxy, AppVersionProxy, HttpHandle}; use mullvad_types::{ account::{AccountData, AccountToken}, + endpoint::MullvadEndpoint, location::GeoIpLocation, relay_constraints::{ Constraint, OpenVpnConstraints, RelayConstraintsUpdate, RelaySettings, RelaySettingsUpdate, @@ -42,10 +43,10 @@ use mullvad_types::{ use std::{mem, path::PathBuf, sync::mpsc, thread, time::Duration}; use talpid_core::{ mpsc::IntoSender, - tunnel_state_machine::{self, TunnelCommand, TunnelParameters, TunnelParametersGenerator}, + tunnel_state_machine::{self, TunnelCommand, TunnelParametersGenerator}, }; use talpid_types::{ - net::{OpenVpnProxySettings, TransportProtocol}, + net::{openvpn, TransportProtocol, TunnelParameters}, tunnel::{BlockReason, TunnelStateTransition}, }; @@ -58,6 +59,9 @@ error_chain! { DaemonIsAlreadyRunning { description("Another instance of the daemon is already running") } + UnsupportedTunnel { + description("Unsupported tunnel") + } ManagementInterfaceError(msg: &'static str) { description("Error in the management interface") display("Management interface error: {}", msg) @@ -340,24 +344,20 @@ impl Daemon { .map(|account_token| { match self.settings.get_relay_settings() { RelaySettings::CustomTunnelEndpoint(custom_relay) => custom_relay - .to_tunnel_endpoint() + .to_tunnel_parameters(self.settings.get_tunnel_options().clone()) .chain_err(|| "Custom tunnel endpoint could not be resolved"), RelaySettings::Normal(constraints) => self .relay_selector .get_tunnel_endpoint(&constraints, retry_attempt) .chain_err(|| "No valid relay servers match the current settings") - .map(|(relay, endpoint)| { + .and_then(|(relay, endpoint)| { self.last_generated_relay = Some(relay); - endpoint + self.create_tunnel_parameters(endpoint, account_token) }), } - .map(|endpoint| { + .map(|tunnel_params| { tunnel_parameters_tx - .send(TunnelParameters { - endpoint, - options: self.settings.get_tunnel_options().clone(), - username: account_token, - }) + .send(tunnel_params) .map_err(|_| Error::from("Tunnel parameters receiver stopped listening")) }) }); @@ -366,6 +366,26 @@ impl Daemon { } } + fn create_tunnel_parameters( + &self, + endpoint: MullvadEndpoint, + account_token: String, + ) -> Result<TunnelParameters> { + let tunnel_options = self.settings.get_tunnel_options().clone(); + match endpoint { + MullvadEndpoint::OpenVpn(endpoint) => Ok(openvpn::TunnelParameters { + config: openvpn::ConnectionConfig::new(endpoint, account_token, "-".to_string()), + options: tunnel_options.openvpn, + generic_options: tunnel_options.generic, + } + .into()), + MullvadEndpoint::Wireguard { + peer: _, + gateway: _, + } => Err(ErrorKind::UnsupportedTunnel.into()), + } + } + fn schedule_reconnect(&mut self, delay: Duration) { let tunnel_command_tx = self.tx.clone(); let (tx, rx) = mpsc::channel(); @@ -639,7 +659,7 @@ impl Daemon { fn on_set_openvpn_proxy( &mut self, tx: oneshot::Sender<::std::result::Result<(), settings::Error>>, - proxy: Option<OpenVpnProxySettings>, + proxy: Option<openvpn::ProxySettings>, ) { let constraints_result = match proxy { Some(_) => self.apply_proxy_constraints(), diff --git a/mullvad-daemon/src/management_interface.rs b/mullvad-daemon/src/management_interface.rs index c68c8ff967..cea4d6a75d 100644 --- a/mullvad-daemon/src/management_interface.rs +++ b/mullvad-daemon/src/management_interface.rs @@ -30,7 +30,7 @@ use std::{ }; use talpid_core::mpsc::IntoSender; use talpid_ipc; -use talpid_types::{net::OpenVpnProxySettings, tunnel::TunnelStateTransition}; +use talpid_types::{net::openvpn, tunnel::TunnelStateTransition}; use uuid; /// FIXME(linus): This is here just because the futures crate has deprecated it and jsonrpc_core @@ -115,7 +115,7 @@ build_rpc_trait! { /// Sets proxy details for OpenVPN #[rpc(meta, name = "set_openvpn_proxy")] - fn set_openvpn_proxy(&self, Self::Metadata, Option<OpenVpnProxySettings>) -> BoxFuture<(), Error>; + fn set_openvpn_proxy(&self, Self::Metadata, Option<openvpn::ProxySettings>) -> BoxFuture<(), Error>; /// Set if IPv6 is enabled in the tunnel #[rpc(meta, name = "set_enable_ipv6")] @@ -194,7 +194,7 @@ pub enum ManagementCommand { /// Set proxy details for OpenVPN SetOpenVpnProxy( OneshotSender<Result<(), settings::Error>>, - Option<OpenVpnProxySettings>, + Option<openvpn::ProxySettings>, ), /// Set if IPv6 should be enabled in the tunnel SetEnableIpv6(OneshotSender<()>, bool), @@ -587,7 +587,7 @@ impl<T: From<ManagementCommand> + 'static + Send> ManagementInterfaceApi fn set_openvpn_proxy( &self, _: Self::Metadata, - proxy: Option<OpenVpnProxySettings>, + proxy: Option<openvpn::ProxySettings>, ) -> BoxFuture<(), Error> { log::debug!("set_openvpn_proxy({:?})", proxy); let (tx, rx) = sync::oneshot::channel(); diff --git a/mullvad-daemon/src/relays.rs b/mullvad-daemon/src/relays.rs index 0dba9dd9a3..11c0d49930 100644 --- a/mullvad-daemon/src/relays.rs +++ b/mullvad-daemon/src/relays.rs @@ -4,6 +4,7 @@ use futures::Future; use mullvad_rpc::{HttpHandle, RelayListProxy}; use mullvad_types::{ + endpoint::{MullvadEndpoint, TunnelEndpointData}, location::Location, relay_constraints::{ Constraint, LocationConstraint, Match, OpenVpnConstraints, RelayConstraints, @@ -14,12 +15,11 @@ use mullvad_types::{ use serde_json; -use talpid_types::net::{TransportProtocol, TunnelEndpoint, TunnelEndpointData}; +use talpid_types::net::TransportProtocol; use std::{ fs::File, io, - net::IpAddr, path::{Path, PathBuf}, sync::{mpsc, Arc, Mutex, MutexGuard}, thread, @@ -196,7 +196,7 @@ impl RelaySelector { &mut self, constraints: &RelayConstraints, retry_attempt: u32, - ) -> Result<(Relay, TunnelEndpoint)> { + ) -> Result<(Relay, MullvadEndpoint)> { let preferred_constraints = Self::preferred_constraints(constraints, retry_attempt); if let Some((relay, endpoint)) = self.get_tunnel_endpoint_internal(&preferred_constraints) { debug!( @@ -264,7 +264,7 @@ impl RelaySelector { fn get_tunnel_endpoint_internal( &mut self, constraints: &RelayConstraints, - ) -> Option<(Relay, TunnelEndpoint)> { + ) -> Option<(Relay, MullvadEndpoint)> { let matching_relays: Vec<Relay> = self .lock_parsed_relays() .relays() @@ -280,10 +280,8 @@ impl RelaySelector { ); self.get_random_tunnel(&selected_relay.tunnels) .map(|tunnel_parameters| { - let endpoint = TunnelEndpoint { - address: IpAddr::V4(selected_relay.ipv4_addr_in), - tunnel: tunnel_parameters, - }; + let endpoint = tunnel_parameters + .to_mullvad_endpoint(selected_relay.ipv4_addr_in.into()); (selected_relay.clone(), endpoint) }) }) diff --git a/mullvad-ipc-client/src/lib.rs b/mullvad-ipc-client/src/lib.rs index 99f9ff6815..d7eaf653ef 100644 --- a/mullvad-ipc-client/src/lib.rs +++ b/mullvad-ipc-client/src/lib.rs @@ -12,15 +12,12 @@ use mullvad_types::{ location::GeoIpLocation, relay_constraints::{RelaySettings, RelaySettingsUpdate}, relay_list::RelayList, - settings::Settings, + settings::{Settings, TunnelOptions}, version::AppVersionInfo, }; use serde::{Deserialize, Serialize}; use std::{path::Path, sync::mpsc, thread, time::Duration}; -use talpid_types::{ - net::{OpenVpnProxySettings, TunnelOptions}, - tunnel::TunnelStateTransition, -}; +use talpid_types::{net::openvpn, tunnel::TunnelStateTransition}; pub use jsonrpc_client_core::{Error as RpcError, ErrorKind as RpcErrorKind}; @@ -196,7 +193,7 @@ impl DaemonRpcClient { self.call("set_openvpn_mssfix", &[mssfix]) } - pub fn set_openvpn_proxy(&mut self, proxy: Option<OpenVpnProxySettings>) -> Result<()> { + pub fn set_openvpn_proxy(&mut self, proxy: Option<openvpn::ProxySettings>) -> Result<()> { self.call("set_openvpn_proxy", &[proxy]) } diff --git a/mullvad-types/Cargo.toml b/mullvad-types/Cargo.toml index 8239696b9b..c0202ed1b6 100644 --- a/mullvad-types/Cargo.toml +++ b/mullvad-types/Cargo.toml @@ -14,6 +14,7 @@ error-chain = "0.12" log = "0.4" regex = "1" lazy_static = "1.1.0" +ipnetwork = "0.13" talpid-types = { path = "../talpid-types" } mullvad-paths = { path = "../mullvad-paths" } diff --git a/mullvad-types/src/custom_tunnel.rs b/mullvad-types/src/custom_tunnel.rs index 475dfa2eaf..83211ba64a 100644 --- a/mullvad-types/src/custom_tunnel.rs +++ b/mullvad-types/src/custom_tunnel.rs @@ -1,40 +1,77 @@ +use crate::settings::TunnelOptions; use serde::{Deserialize, Serialize}; use std::{ fmt, - net::{IpAddr, ToSocketAddrs}, + net::{IpAddr, SocketAddr, ToSocketAddrs}, }; -use talpid_types::net::{TunnelEndpoint, TunnelEndpointData}; +use talpid_types::net::{openvpn, wireguard, TunnelParameters}; error_chain! { errors { InvalidHost(host: String) { display("Invalid host: {}", host) } + Unsupported { + description("Tunnel type not supported") + } } } #[derive(Debug, Clone, Eq, PartialEq, Serialize, Deserialize)] pub struct CustomTunnelEndpoint { - pub host: String, - pub tunnel: TunnelEndpointData, + host: String, + config: ConnectionConfig, } impl CustomTunnelEndpoint { - pub fn to_tunnel_endpoint(&self) -> Result<TunnelEndpoint> { - Ok(TunnelEndpoint { - address: resolve_to_ip(&self.host)?, - tunnel: self.tunnel.clone(), - }) + pub fn new(host: String, config: ConnectionConfig) -> Self { + Self { host, config } + } + + pub fn to_tunnel_parameters(&self, tunnel_options: TunnelOptions) -> Result<TunnelParameters> { + let ip = resolve_to_ip(&self.host)?; + let mut config = self.config.clone(); + config.set_ip(ip); + + let parameters = match config { + ConnectionConfig::OpenVpn(config) => openvpn::TunnelParameters { + config, + options: tunnel_options.openvpn.clone(), + generic_options: tunnel_options.generic.clone(), + } + .into(), + ConnectionConfig::Wireguard(connection) => wireguard::TunnelParameters { + connection, + options: tunnel_options.wireguard.clone(), + generic_options: tunnel_options.generic.clone(), + } + .into(), + }; + Ok(parameters) } } impl fmt::Display for CustomTunnelEndpoint { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, "{} over {}", self.host, self.tunnel) + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match &self.config { + ConnectionConfig::OpenVpn(config) => write!( + f, + "OpenVPN relay - {}:{} {}", + self.host, + config.endpoint.address.port(), + config.endpoint.protocol + ), + ConnectionConfig::Wireguard(connection) => write!( + f, + "WireGuard relay - {} with public key {}", + connection.peer.endpoint, connection.peer.public_key + ), + } } } + /// Does a DNS lookup if the host isn't an IP. /// Returns the first IPv4 address if one exists, otherwise the first IPv6 address. /// Rust only provides means to resolve a socket addr, not just a host, for some reason. So @@ -53,3 +90,25 @@ fn resolve_to_ip(host: &str) -> Result<IpAddr> { }) .ok_or_else(|| ErrorKind::InvalidHost(host.to_owned()).into()) } + +#[derive(Debug, Clone, Eq, PartialEq, Serialize, Deserialize)] +#[serde(rename = "connection_config")] +pub enum ConnectionConfig { + #[serde(rename = "openvpn")] + OpenVpn(openvpn::ConnectionConfig), + #[serde(rename = "wireguard")] + Wireguard(wireguard::ConnectionConfig), +} + +impl ConnectionConfig { + fn set_ip(&mut self, ip: IpAddr) { + match self { + ConnectionConfig::OpenVpn(config) => { + config.endpoint.address = SocketAddr::new(ip, config.endpoint.address.port()); + } + ConnectionConfig::Wireguard(config) => { + config.peer.endpoint = SocketAddr::new(ip, config.peer.endpoint.port()) + } + } + } +} diff --git a/mullvad-types/src/endpoint.rs b/mullvad-types/src/endpoint.rs new file mode 100644 index 0000000000..79cb6693b7 --- /dev/null +++ b/mullvad-types/src/endpoint.rs @@ -0,0 +1,111 @@ +use ipnetwork::IpNetwork; +use serde::{Deserialize, Serialize}; +use std::{ + fmt, + net::{IpAddr, SocketAddr}, +}; +use talpid_types::net::{wireguard, Endpoint, TransportProtocol}; + +use crate::relay_list::{OpenVpnEndpointData, WireguardEndpointData}; + +/// Contains server data needed to conenct to a single mullvad endpoint +#[derive(Debug, Clone, PartialEq, Eq, Hash, Deserialize, Serialize)] +pub enum MullvadEndpoint { + OpenVpn(Endpoint), + Wireguard { + peer: wireguard::PeerConfig, + gateway: IpAddr, + }, +} + +impl MullvadEndpoint { + /// Returns this tunnel endpoint as an `Endpoint`. + pub fn to_endpoint(&self) -> Endpoint { + match self { + MullvadEndpoint::OpenVpn(endpoint) => *endpoint, + MullvadEndpoint::Wireguard { peer, gateway: _ } => Endpoint::new( + peer.endpoint.ip(), + peer.endpoint.port(), + TransportProtocol::Udp, + ), + } + } +} +/// TunnelEndpointData contains data required to connect to a given tunnel endpoint. +/// Different endpoint types can require different types of data. +#[derive(Debug, Clone, PartialEq, Eq, Hash, Deserialize, Serialize)] +pub enum TunnelEndpointData { + /// Extra parameters for an OpenVPN tunnel endpoint. + #[serde(rename = "openvpn")] + OpenVpn(OpenVpnEndpointData), + /// Extra parameters for a Wireguard tunnel endpoint. + #[serde(rename = "wireguard")] + Wireguard(WireguardEndpointData), +} +impl From<OpenVpnEndpointData> for TunnelEndpointData { + fn from(endpoint_data: OpenVpnEndpointData) -> TunnelEndpointData { + TunnelEndpointData::OpenVpn(endpoint_data) + } +} + +impl From<WireguardEndpointData> for TunnelEndpointData { + fn from(endpoint_data: WireguardEndpointData) -> TunnelEndpointData { + TunnelEndpointData::Wireguard(endpoint_data) + } +} + +impl fmt::Display for TunnelEndpointData { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> { + match self { + TunnelEndpointData::OpenVpn(openvpn_data) => { + write!(f, "OpenVPN ")?; + openvpn_data.fmt(f) + } + TunnelEndpointData::Wireguard(wireguard_data) => { + write!(f, "Wireguard ")?; + wireguard_data.fmt(f) + } + } + } +} + +impl TunnelEndpointData { + pub fn to_mullvad_endpoint(self, host: IpAddr) -> MullvadEndpoint { + match self { + TunnelEndpointData::OpenVpn(metadata) => { + MullvadEndpoint::OpenVpn(Endpoint::new(host, metadata.port, metadata.protocol)) + } + TunnelEndpointData::Wireguard(metadata) => { + let peer_config = wireguard::PeerConfig { + public_key: metadata.peer_public_key, + endpoint: SocketAddr::new(host, metadata.port), + allowed_ips: all_of_the_internet(), + }; + MullvadEndpoint::Wireguard { + peer: peer_config, + gateway: metadata.gateway, + } + } + } + } + pub fn port(&self) -> u16 { + match self { + TunnelEndpointData::OpenVpn(metadata) => metadata.port, + TunnelEndpointData::Wireguard(metadata) => metadata.port, + } + } + + pub fn transport_protocol(&self) -> TransportProtocol { + match self { + TunnelEndpointData::OpenVpn(metadata) => metadata.protocol, + TunnelEndpointData::Wireguard(_) => TransportProtocol::Udp, + } + } +} + +fn all_of_the_internet() -> Vec<IpNetwork> { + vec![ + "0.0.0.0/0".parse().expect("Failed to parse ipv6 network"), + "::0/0".parse().expect("Failed to parse ipv6 network"), + ] +} diff --git a/mullvad-types/src/lib.rs b/mullvad-types/src/lib.rs index a972719460..11e6ac4005 100644 --- a/mullvad-types/src/lib.rs +++ b/mullvad-types/src/lib.rs @@ -11,6 +11,7 @@ extern crate error_chain; pub mod account; pub mod auth_failed; +pub mod endpoint; pub mod location; pub mod relay_constraints; pub mod relay_list; diff --git a/mullvad-types/src/relay_constraints.rs b/mullvad-types/src/relay_constraints.rs index 52f22a9229..41305115c2 100644 --- a/mullvad-types/src/relay_constraints.rs +++ b/mullvad-types/src/relay_constraints.rs @@ -1,10 +1,11 @@ use crate::{ location::{CityCode, CountryCode, Hostname}, + relay_list::{OpenVpnEndpointData, WireguardEndpointData}, CustomTunnelEndpoint, }; use serde::{Deserialize, Serialize}; use std::fmt; -use talpid_types::net::{OpenVpnEndpointData, TransportProtocol, WireguardEndpointData}; +use talpid_types::net::TransportProtocol; pub trait Match<T> { diff --git a/mullvad-types/src/relay_list.rs b/mullvad-types/src/relay_list.rs index bc5d66eb80..1e16dcb6ba 100644 --- a/mullvad-types/src/relay_list.rs +++ b/mullvad-types/src/relay_list.rs @@ -1,7 +1,10 @@ use crate::location::{CityCode, CountryCode, Location}; use serde::{Deserialize, Serialize}; -use std::net::Ipv4Addr; -use talpid_types::net::{OpenVpnEndpointData, WireguardEndpointData}; +use std::{ + fmt, + net::{IpAddr, Ipv4Addr}, +}; +use talpid_types::net::{wireguard, TransportProtocol}; #[derive(Debug, Clone, Deserialize, Serialize)] @@ -63,3 +66,45 @@ impl RelayTunnels { self.wireguard.clear(); } } + +#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash, Deserialize, Serialize)] +pub struct OpenVpnEndpointData { + pub port: u16, + pub protocol: TransportProtocol, +} + +impl fmt::Display for OpenVpnEndpointData { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> { + write!(f, "{} port {}", self.protocol, self.port) + } +} + +#[derive(Clone, Eq, PartialEq, Hash, Deserialize, Serialize)] +pub struct WireguardEndpointData { + /// Port to connect to + pub port: u16, + /// Peer's IP address + pub gateway: IpAddr, + /// The peer's public key + pub peer_public_key: wireguard::PublicKey, +} + +impl fmt::Debug for WireguardEndpointData { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> { + f.debug_struct(&"WireguardEndpointData") + .field("port", &self.port) + .field("gateway", &self.gateway) + .field("peer_public_key", &self.peer_public_key) + .finish() + } +} + +impl fmt::Display for WireguardEndpointData { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> { + write!( + f, + "gateway {} port {} peer_public_key {}", + self.gateway, self.port, self.peer_public_key, + ) + } +} diff --git a/mullvad-types/src/settings.rs b/mullvad-types/src/settings.rs index 70f5d6b35e..cfc445b3c9 100644 --- a/mullvad-types/src/settings.rs +++ b/mullvad-types/src/settings.rs @@ -5,7 +5,7 @@ use log::{debug, info}; use serde::{Deserialize, Serialize}; use serde_json; use std::{fs::File, io, path::PathBuf}; -use talpid_types::net::{OpenVpnProxySettings, OpenVpnProxySettingsValidation, TunnelOptions}; +use talpid_types::net::{openvpn, wireguard, GenericTunnelOptions}; error_chain! { errors { @@ -201,9 +201,9 @@ impl Settings { } } - pub fn set_openvpn_proxy(&mut self, proxy: Option<OpenVpnProxySettings>) -> Result<bool> { + pub fn set_openvpn_proxy(&mut self, proxy: Option<openvpn::ProxySettings>) -> Result<bool> { if let Some(ref settings) = proxy { - if let Err(validation_error) = OpenVpnProxySettingsValidation::validate(settings) { + if let Err(validation_error) = openvpn::ProxySettingsValidation::validate(settings) { bail!(ErrorKind::InvalidProxyData(validation_error)); } } @@ -217,8 +217,8 @@ impl Settings { } pub fn set_enable_ipv6(&mut self, enable_ipv6: bool) -> Result<bool> { - if self.tunnel_options.enable_ipv6 != enable_ipv6 { - self.tunnel_options.enable_ipv6 = enable_ipv6; + if self.tunnel_options.generic.enable_ipv6 != enable_ipv6 { + self.tunnel_options.generic.enable_ipv6 = enable_ipv6; self.save().map(|_| true) } else { Ok(false) @@ -229,3 +229,29 @@ impl Settings { &self.tunnel_options } } + +/// TunnelOptions holds configuration data that applies to all kinds of tunnels. +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[serde(default)] +pub struct TunnelOptions { + /// openvpn holds OpenVPN specific tunnel options. + pub openvpn: openvpn::TunnelOptions, + /// Contains wireguard tunnel options. + pub wireguard: wireguard::TunnelOptions, + /// Contains generic tunnel options that may apply to more than a single tunnel type. + pub generic: GenericTunnelOptions, +} + +impl Default for TunnelOptions { + fn default() -> Self { + TunnelOptions { + openvpn: openvpn::TunnelOptions::default(), + wireguard: wireguard::TunnelOptions { + mtu: None, + #[cfg(target_os = "linux")] + fwmark: 78_78_78, + }, + generic: GenericTunnelOptions { enable_ipv6: false }, + } + } +} |
