diff options
| -rw-r--r-- | mullvad-daemon/src/main.rs | 35 | ||||
| -rw-r--r-- | talpid-core/src/tunnel/mod.rs | 90 | ||||
| -rw-r--r-- | talpid-types/src/net.rs | 54 |
3 files changed, 106 insertions, 73 deletions
diff --git a/mullvad-daemon/src/main.rs b/mullvad-daemon/src/main.rs index 5b17a67be4..d4de632817 100644 --- a/mullvad-daemon/src/main.rs +++ b/mullvad-daemon/src/main.rs @@ -55,6 +55,7 @@ use mullvad_types::relay_endpoint::RelayEndpoint; use mullvad_types::states::{DaemonState, SecurityState, TargetState}; use rand::Rng; +use std::env; use std::io; use std::net::Ipv4Addr; use std::path::PathBuf; @@ -65,7 +66,8 @@ use std::time::{Duration, Instant}; use talpid_core::firewall::{Firewall, FirewallProxy, SecurityPolicy}; use talpid_core::mpsc::IntoSender; use talpid_core::tunnel::{self, TunnelEvent, TunnelMetadata, TunnelMonitor}; -use talpid_types::net::{Endpoint, TransportProtocol, TunnelEndpoint}; +use talpid_types::net::{Endpoint, OpenVpnParameters, TransportProtocol, TunnelEndpoint, + TunnelParameters}; error_chain!{ errors { @@ -110,6 +112,8 @@ lazy_static! { const CRATE_NAME: &str = "mullvadd"; +const DATE_TIME_FORMAT_STR: &str = "%Y-%m-%d %H:%M:%S%.3f"; + /// All events that can happen in the daemon. Sent from various threads and exposed interfaces. pub enum DaemonEvent { @@ -185,6 +189,7 @@ struct Daemon { // Just for testing. A cyclic iterator iterating over the hardcoded relays, // picking a new one for each retry. relay_iter: std::iter::Cycle<std::iter::Cloned<std::slice::Iter<'static, Endpoint>>>, + resource_dir: PathBuf, } impl Daemon { @@ -193,6 +198,7 @@ impl Daemon { let management_interface_broadcaster = Self::start_management_interface(tx.clone())?; let state = TunnelState::NotRunning; let target_state = TargetState::Unsecured; + let resource_dir = get_resource_dir(); Ok(Daemon { state, tunnel_close_handle: None, @@ -212,6 +218,7 @@ impl Daemon { tunnel_metadata: None, tunnel_log: tunnel_log, relay_iter: RELAYS.iter().cloned().cycle(), + resource_dir, }) } @@ -560,7 +567,10 @@ impl Daemon { protocol, }.to_endpoint() .chain_err(|| "Unable to construct a valid relay")?; - Ok(TunnelEndpoint::OpenVpn(endpoint)) + Ok(TunnelEndpoint { + address: endpoint.address.ip(), + tunnel: TunnelParameters::OpenVpn(OpenVpnParameters { port, protocol }), + }) } fn spawn_tunnel_monitor( @@ -580,6 +590,7 @@ impl Daemon { tunnel_endpoint, account_token, self.tunnel_log.as_ref().map(PathBuf::as_path), + &self.resource_dir, on_tunnel_event, ).chain_err(|| ErrorKind::TunnelError("Unable to start tunnel monitor")) } @@ -693,8 +704,8 @@ fn init_logger(log_level: log::LogLevelFilter, log_file: Option<&PathBuf>) -> Re let mut config = fern::Dispatch::new() .format(|out, message, record| { out.finish(format_args!( - "{}[{}][{}] {}", - chrono::Local::now().format("[%Y-%m-%d %H:%M:%S%.3f]"), + "[{}][{}][{}] {}", + chrono::Local::now().format(DATE_TIME_FORMAT_STR), record.target(), record.level(), message @@ -734,3 +745,19 @@ fn randomize_port(protocol: TransportProtocol) -> u16 { .choose(&pool) .expect("no ports to randomize from") } + +fn get_resource_dir() -> PathBuf { + match env::current_exe() { + Ok(mut path) => { + path.pop(); + path + } + Err(e) => { + error!( + "Failed finding the install directory. Using working directory: {}", + e + ); + PathBuf::from(".") + } + } +} diff --git a/talpid-core/src/tunnel/mod.rs b/talpid-core/src/tunnel/mod.rs index af0002c61d..f5c3618352 100644 --- a/talpid-core/src/tunnel/mod.rs +++ b/talpid-core/src/tunnel/mod.rs @@ -5,14 +5,13 @@ use openvpn_plugin::types::OpenVpnPluginEvent; use process::openvpn::OpenVpnCommand; use std::collections::HashMap; -use std::env; use std::ffi::{OsStr, OsString}; use std::fs; use std::io::{self, Write}; use std::net::Ipv4Addr; use std::path::{Path, PathBuf}; -use talpid_types::net::{Endpoint, TunnelEndpoint}; +use talpid_types::net::{Endpoint, TunnelEndpoint, TunnelParameters}; /// A module for all OpenVPN related tunnel management. pub mod openvpn; @@ -39,8 +38,8 @@ mod errors { description("Running on an unsupported operating system") } /// This type of VPN tunnel is not supported. - UnsupportedTunnelTechnology { - description("This tunnel technology is not supported") + UnsupportedTunnelProtocol { + description("This tunnel protocol is not supported") } } } @@ -112,23 +111,29 @@ impl TunnelMonitor { /// Creates a new `TunnelMonitor` that connects to the given remote and notifies `on_event` /// on tunnel state changes. pub fn new<L>( - remote: TunnelEndpoint, + tunnel_endpoint: TunnelEndpoint, account_token: &str, log: Option<&Path>, + resource_dir: &Path, on_event: L, ) -> Result<Self> where L: Fn(TunnelEvent) + Send + Sync + 'static, { - let remote = match remote { - TunnelEndpoint::OpenVpn(endpoint) => endpoint, - _ => bail!(ErrorKind::UnsupportedTunnelTechnology), - }; + match tunnel_endpoint.tunnel { + TunnelParameters::OpenVpn(_) => (), + TunnelParameters::Wireguard(_) => bail!(ErrorKind::UnsupportedTunnelProtocol), + } let user_pass_file = Self::create_user_pass_file(account_token) .chain_err(|| ErrorKind::CredentialsWriteError)?; - let cmd = Self::create_openvpn_cmd(remote, user_pass_file.as_ref(), log); - let user_pass_file_path = user_pass_file.to_path_buf(); + let cmd = Self::create_openvpn_cmd( + tunnel_endpoint.to_endpoint(), + user_pass_file.as_ref(), + log, + resource_dir, + ); + let user_pass_file_path = user_pass_file.to_path_buf(); let on_openvpn_event = move |event, env| { if event == OpenVpnPluginEvent::Up { // The user-pass file has been read. Try to delete it early. @@ -140,8 +145,11 @@ impl TunnelMonitor { } }; - let monitor = openvpn::OpenVpnMonitor::new(cmd, on_openvpn_event, Self::get_plugin_path()?) - .chain_err(|| ErrorKind::TunnelMonitoringError)?; + let monitor = openvpn::OpenVpnMonitor::new( + cmd, + on_openvpn_event, + Self::get_plugin_path(resource_dir)?, + ).chain_err(|| ErrorKind::TunnelMonitoringError)?; Ok(TunnelMonitor { monitor, _user_pass_file: user_pass_file, @@ -152,28 +160,25 @@ impl TunnelMonitor { remote: Endpoint, user_pass_file: &Path, log: Option<&Path>, + resource_dir: &Path, ) -> OpenVpnCommand { - let mut cmd = OpenVpnCommand::new(Self::get_openvpn_bin()); - if let Some(config) = Self::get_config_path() { + let mut cmd = OpenVpnCommand::new(Self::get_openvpn_bin(resource_dir)); + if let Some(config) = Self::get_config_path(resource_dir) { cmd.config(config); } cmd.remote(remote) .user_pass(user_pass_file) - .ca(Self::get_ca_path()) - .crl(Self::get_crl_path()); + .ca(resource_dir.join("ca.crt")) + .crl(resource_dir.join("crl.pem")); if let Some(log) = log { cmd.log(log); } cmd } - fn get_openvpn_bin() -> OsString { + fn get_openvpn_bin(resource_dir: &Path) -> OsString { let bin = OsStr::new("openvpn"); - let bundled_path = Self::get_install_dir() - .unwrap_or(PathBuf::from(".")) - .join("openvpn-binaries") - .join(bin); - + let bundled_path = resource_dir.join("openvpn-binaries").join(bin); if bundled_path.exists() { bundled_path.into_os_string() } else { @@ -182,24 +187,9 @@ impl TunnelMonitor { } } - fn get_ca_path() -> PathBuf { - Self::get_install_dir() - .unwrap_or(PathBuf::from(".")) - .join("ca.crt") - } - - fn get_crl_path() -> PathBuf { - Self::get_install_dir() - .unwrap_or(PathBuf::from(".")) - .join("crl.pem") - } - - fn get_plugin_path() -> Result<PathBuf> { + fn get_plugin_path(resource_dir: &Path) -> Result<PathBuf> { let lib_ext = Self::get_library_extension().chain_err(|| ErrorKind::PluginNotFound)?; - - let path = Self::get_install_dir() - .unwrap_or(PathBuf::from(".")) - .join(format!("libtalpid_openvpn_plugin.{}", lib_ext)); + let path = resource_dir.join(format!("libtalpid_openvpn_plugin.{}", lib_ext)); if path.exists() { debug!("Using OpenVPN plugin at {}", path.to_string_lossy()); @@ -221,11 +211,8 @@ impl TunnelMonitor { } } - fn get_config_path() -> Option<PathBuf> { - let path = Self::get_install_dir() - .unwrap_or(PathBuf::from(".")) - .join("openvpn.conf"); - + fn get_config_path(resource_dir: &Path) -> Option<PathBuf> { + let path = resource_dir.join("openvpn.conf"); if path.exists() { Some(path) } else { @@ -233,19 +220,6 @@ impl TunnelMonitor { } } - fn get_install_dir() -> Option<PathBuf> { - match env::current_exe() { - Ok(mut path) => { - path.pop(); - Some(path) - } - Err(e) => { - error!("Failed finding the directory of the executable: {}", e); - None - } - } - } - fn create_user_pass_file(account_token: &str) -> io::Result<mktemp::TempFile> { let temp_file = mktemp::TempFile::new(); debug!( diff --git a/talpid-types/src/net.rs b/talpid-types/src/net.rs index a293592f18..9d84be0ea2 100644 --- a/talpid-types/src/net.rs +++ b/talpid-types/src/net.rs @@ -3,28 +3,60 @@ use std::fmt; use std::net::{IpAddr, SocketAddr}; use std::str::FromStr; -/// Represents one tunnel endpoint. Tunnel technology plus address. +/// Represents one tunnel endpoint. Address, plus extra parameters specific to tunnel protocol. #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] -pub enum TunnelEndpoint { - /// An OpenVPN tunnel endpoint. - OpenVpn(Endpoint), - /// A Wireguard tunnel endpoint. - Wireguard(SocketAddr), +pub struct TunnelEndpoint { + pub address: IpAddr, + pub tunnel: TunnelParameters, } impl TunnelEndpoint { /// Returns this tunnel endpoint as an `Endpoint`. pub fn to_endpoint(&self) -> Endpoint { + Endpoint::new( + self.address, + self.tunnel.port(), + self.tunnel.transport_protocol(), + ) + } +} + +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Deserialize, Serialize)] +pub enum TunnelParameters { + /// Extra parameters for an OpenVPN tunnel endpoint. + OpenVpn(OpenVpnParameters), + /// Extra parameters for a Wireguard tunnel endpoint. + Wireguard(WireguardParameters), +} + +impl TunnelParameters { + pub fn port(&self) -> u16 { match *self { - TunnelEndpoint::OpenVpn(endpoint) => endpoint, - TunnelEndpoint::Wireguard(address) => Endpoint { - address, - protocol: TransportProtocol::Udp, - }, + TunnelParameters::OpenVpn(metadata) => metadata.port, + TunnelParameters::Wireguard(metadata) => metadata.port, } } + + pub fn transport_protocol(&self) -> TransportProtocol { + match *self { + TunnelParameters::OpenVpn(metadata) => metadata.protocol, + TunnelParameters::Wireguard(_) => TransportProtocol::Udp, + } + } +} + +#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash, Deserialize, Serialize)] +pub struct OpenVpnParameters { + pub port: u16, + pub protocol: TransportProtocol, } +#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash, Deserialize, Serialize)] +pub struct WireguardParameters { + pub port: u16, +} + + /// Represents a network layer IP address together with the transport layer protocol and port. #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] pub struct Endpoint { |
