summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorEmīls Piņķis <emils@mullvad.net>2019-01-14 13:29:16 +0000
committerEmīls Piņķis <emils@mullvad.net>2019-01-30 13:41:31 +0000
commit7a99bd987ee258ee54a8cb28ab4f580ac03ffe86 (patch)
tree0d7fa957b2b321c89a33bbb2382f16e5068e4333
parent4e2b2ff81704fdab21b269948c3ebf2a9f65b07c (diff)
downloadmullvadvpn-7a99bd987ee258ee54a8cb28ab4f580ac03ffe86.tar.xz
mullvadvpn-7a99bd987ee258ee54a8cb28ab4f580ac03ffe86.zip
Refactor mullvad types
-rw-r--r--mullvad-cli/src/cmds/relay.rs39
-rw-r--r--mullvad-cli/src/cmds/tunnel.rs32
-rw-r--r--mullvad-daemon/src/lib.rs44
-rw-r--r--mullvad-daemon/src/management_interface.rs8
-rw-r--r--mullvad-daemon/src/relays.rs14
-rw-r--r--mullvad-ipc-client/src/lib.rs9
-rw-r--r--mullvad-types/Cargo.toml1
-rw-r--r--mullvad-types/src/custom_tunnel.rs81
-rw-r--r--mullvad-types/src/endpoint.rs111
-rw-r--r--mullvad-types/src/lib.rs1
-rw-r--r--mullvad-types/src/relay_constraints.rs3
-rw-r--r--mullvad-types/src/relay_list.rs49
-rw-r--r--mullvad-types/src/settings.rs36
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 },
+ }
+ }
+}