summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--mullvad-daemon/src/main.rs35
-rw-r--r--talpid-core/src/tunnel/mod.rs90
-rw-r--r--talpid-types/src/net.rs54
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 {