summaryrefslogtreecommitdiffhomepage
path: root/mullvad-daemon/src
diff options
context:
space:
mode:
authorErik Larkö <erik@mullvad.net>2017-10-26 09:38:10 +0200
committerErik Larkö <erik@mullvad.net>2017-11-02 09:20:09 +0100
commite543bd104d08e0838d177e10da45962ee25aa42c (patch)
tree6da3507544b30de22158131ff239df8c2a8e9157 /mullvad-daemon/src
parentd6eaa0a95d07fd1105ff37e71472edc6d3c07392 (diff)
downloadmullvadvpn-e543bd104d08e0838d177e10da45962ee25aa42c.tar.xz
mullvadvpn-e543bd104d08e0838d177e10da45962ee25aa42c.zip
Set the tunnel port and protocol over the API
Diffstat (limited to 'mullvad-daemon/src')
-rw-r--r--mullvad-daemon/src/main.rs68
-rw-r--r--mullvad-daemon/src/management_interface.rs36
-rw-r--r--mullvad-daemon/src/settings.rs66
3 files changed, 106 insertions, 64 deletions
diff --git a/mullvad-daemon/src/main.rs b/mullvad-daemon/src/main.rs
index ad2850b926..3a0b6854de 100644
--- a/mullvad-daemon/src/main.rs
+++ b/mullvad-daemon/src/main.rs
@@ -27,6 +27,7 @@ extern crate jsonrpc_pubsub;
extern crate jsonrpc_ws_server;
#[macro_use]
extern crate lazy_static;
+extern crate rand;
extern crate uuid;
extern crate mullvad_rpc;
@@ -48,9 +49,12 @@ use jsonrpc_core::futures::sync::oneshot::Sender as OneshotSender;
use management_interface::{BoxFuture, ManagementInterfaceServer, TunnelCommand};
use mullvad_rpc::{AccountsProxy, HttpHandle};
use mullvad_types::account::{AccountData, AccountToken};
+use mullvad_types::relay_constraints::{OpenVpnConstraints, RelayConstraintsUpdate,
+ TunnelConstraints};
use mullvad_types::relay_endpoint::RelayEndpoint;
use mullvad_types::states::{DaemonState, SecurityState, TargetState};
+use rand::Rng;
use std::io;
use std::net::Ipv4Addr;
use std::path::PathBuf;
@@ -314,7 +318,9 @@ impl Daemon {
GetAccountData(tx, account_token) => Ok(self.on_get_account_data(tx, account_token)),
SetAccount(tx, account_token) => self.on_set_account(tx, account_token),
GetAccount(tx) => Ok(self.on_get_account(tx)),
- SetCustomRelay(tx, relay_endpoint) => self.on_set_custom_relay(tx, relay_endpoint),
+ UpdateRelayConstraints(tx, constraints_update) => {
+ self.on_update_relay_constraints(tx, constraints_update)
+ }
Shutdown => self.handle_trigger_shutdown_event(),
}
}
@@ -370,22 +376,22 @@ impl Daemon {
Self::oneshot_send(tx, self.settings.get_account_token(), "current account")
}
- fn on_set_custom_relay(
+ fn on_update_relay_constraints(
&mut self,
tx: OneshotSender<()>,
- relay_endpoint: Option<RelayEndpoint>,
+ constraints: RelayConstraintsUpdate,
) -> Result<()> {
- let save_result = self.settings.set_custom_relay(relay_endpoint);
+ let save_result = self.settings.update_relay_constraints(constraints);
match save_result.chain_err(|| "Unable to save settings") {
- Ok(relays_changed) => {
- Self::oneshot_send(tx, (), "set_custom_relay response");
+ Ok(constraints_changed) => {
+ Self::oneshot_send(tx, (), "update_relay_constraints response");
let tunnel_needs_restart =
self.state == TunnelState::Connecting || self.state == TunnelState::Connected;
- if relays_changed && tunnel_needs_restart {
- info!("Initiating tunnel restart because a custom relay was selected");
+ if constraints_changed && tunnel_needs_restart {
+ info!("Initiating tunnel restart because the relay constraints changed");
self.kill_tunnel()?;
}
}
@@ -513,15 +519,37 @@ impl Daemon {
}
fn get_relay(&mut self) -> Result<Endpoint> {
- if let Some(relay_endpoint) = self.settings.get_custom_relay() {
- relay_endpoint
- .to_endpoint()
- .chain_err(|| "Invalid custom relay")
- } else {
- Ok(self.relay_iter.next().unwrap())
+ let relay_constraints = self.settings.get_relay_constraints();
+
+ let host = relay_constraints
+ .host
+ .unwrap_or_else(|| format!("{}", self.relay_iter.next().unwrap().address));
+
+ match relay_constraints.tunnel {
+ TunnelConstraints::OpenVpn(constraints) => self.get_openvpn_relay(host, constraints),
}
}
+ fn get_openvpn_relay(
+ &mut self,
+ host: String,
+ constraints: OpenVpnConstraints,
+ ) -> Result<Endpoint> {
+ let protocol = constraints.protocol;
+
+ let port = match constraints.port {
+ mullvad_types::relay_constraints::Port::Any => randomize_port(protocol),
+ mullvad_types::relay_constraints::Port::Port(port) => port,
+ };
+
+ RelayEndpoint {
+ host,
+ port,
+ protocol,
+ }.to_endpoint()
+ .chain_err(|| "Unable to construct a valid relay")
+ }
+
fn spawn_tunnel_monitor(&self, relay: Endpoint, account_token: &str) -> Result<TunnelMonitor> {
// Must wrap the channel in a Mutex because TunnelMonitor forces the closure to be Sync
let event_tx = Arc::new(Mutex::new(self.tx.clone()));
@@ -677,3 +705,15 @@ fn log_version() {
include_str!(concat!(env!("OUT_DIR"), "/git-commit-info.txt"))
)
}
+
+fn randomize_port(protocol: TransportProtocol) -> u16 {
+ let pool: Vec<u16> = if protocol == TransportProtocol::Udp {
+ vec![1194, 1195, 1196, 1197, 1300, 1301, 1302]
+ } else {
+ vec![80, 443]
+ };
+
+ *rand::thread_rng()
+ .choose(&pool)
+ .expect("no ports to randomize from")
+}
diff --git a/mullvad-daemon/src/management_interface.rs b/mullvad-daemon/src/management_interface.rs
index 43e55f4cb4..8674882613 100644
--- a/mullvad-daemon/src/management_interface.rs
+++ b/mullvad-daemon/src/management_interface.rs
@@ -10,7 +10,6 @@ use jsonrpc_ws_server;
use mullvad_rpc;
use mullvad_types::account::{AccountData, AccountToken};
use mullvad_types::location::{CountryCode, Location};
-use mullvad_types::relay_endpoint::RelayEndpoint;
use mullvad_types::states::{DaemonState, TargetState};
use serde;
@@ -21,6 +20,7 @@ use std::net::{IpAddr, Ipv4Addr};
use std::sync::{Arc, Mutex, RwLock};
use std::sync::atomic::{AtomicBool, Ordering};
+use mullvad_types::relay_constraints::RelayConstraintsUpdate;
use talpid_core::mpsc::IntoSender;
use talpid_ipc;
use uuid;
@@ -56,13 +56,12 @@ build_rpc_trait! {
#[rpc(meta, name = "get_account")]
fn get_account(&self, Self::Metadata) -> BoxFuture<Option<AccountToken>, Error>;
- /// Set which relay to connect to
- #[rpc(meta, name = "set_custom_relay")]
- fn set_custom_relay(&self, Self::Metadata, RelayEndpoint) -> BoxFuture<(), Error>;
-
- /// Unset the custom relay, reverting to the default relay listing
- #[rpc(meta, name = "remove_custom_relay")]
- fn remove_custom_relay(&self, Self::Metadata) -> BoxFuture<(), Error>;
+ /// Update constraints put on the type of tunnel connection to use
+ #[rpc(meta, name = "update_relay_constraints")]
+ fn update_relay_constraints(
+ &self,
+ Self::Metadata, RelayConstraintsUpdate
+ ) -> BoxFuture<(), Error>;
/// Set if the client should automatically establish a tunnel on start or not.
#[rpc(meta, name = "set_autoconnect")]
@@ -133,8 +132,8 @@ pub enum TunnelCommand {
SetAccount(OneshotSender<()>, Option<AccountToken>),
/// Request the current account token being used.
GetAccount(OneshotSender<Option<AccountToken>>),
- /// Set a custom relay instead of the default list of relays
- SetCustomRelay(OneshotSender<()>, Option<RelayEndpoint>),
+ /// Place constraints on the type of tunnel and relay
+ UpdateRelayConstraints(OneshotSender<()>, RelayConstraintsUpdate),
/// Makes the daemon exit the main loop and quit.
Shutdown,
}
@@ -382,30 +381,21 @@ impl<T: From<TunnelCommand> + 'static + Send> ManagementInterfaceApi for Managem
Box::new(future)
}
- fn set_custom_relay(
+ fn update_relay_constraints(
&self,
meta: Self::Metadata,
- custom_relay: RelayEndpoint,
+ constraints_update: RelayConstraintsUpdate,
) -> BoxFuture<(), Error> {
- trace!("set_custom_relay");
+ trace!("update_relay_constraints");
try_future!(self.check_auth(&meta));
let (tx, rx) = sync::oneshot::channel();
- let message = TunnelCommand::SetCustomRelay(tx, Some(custom_relay));
+ let message = TunnelCommand::UpdateRelayConstraints(tx, constraints_update);
let future = self.send_command_to_daemon(message)
.and_then(|_| rx.map_err(|_| Error::internal_error()));
Box::new(future)
}
- fn remove_custom_relay(&self, meta: Self::Metadata) -> BoxFuture<(), Error> {
- trace!("remove_custom_relay");
- try_future!(self.check_auth(&meta));
- let (tx, rx) = sync::oneshot::channel();
- let future = self.send_command_to_daemon(TunnelCommand::SetCustomRelay(tx, None))
- .and_then(|_| rx.map_err(|_| Error::internal_error()));
- Box::new(future)
- }
-
fn set_autoconnect(&self, meta: Self::Metadata, _autoconnect: bool) -> BoxFuture<(), Error> {
trace!("set_autoconnect");
try_future!(self.check_auth(&meta));
diff --git a/mullvad-daemon/src/settings.rs b/mullvad-daemon/src/settings.rs
index 1ba32eb178..f217d9a677 100644
--- a/mullvad-daemon/src/settings.rs
+++ b/mullvad-daemon/src/settings.rs
@@ -1,12 +1,14 @@
extern crate app_dirs;
-extern crate toml;
+extern crate serde_json;
use self::app_dirs::{AppDataType, AppInfo};
-use mullvad_types::relay_endpoint::RelayEndpoint;
+use talpid_types::net::TransportProtocol;
+use mullvad_types::relay_constraints::{OpenVpnConstraints, Port, RelayConstraints,
+ RelayConstraintsUpdate, TunnelConstraints};
use std::fs::File;
-use std::io::{self, Read, Write};
+use std::io;
use std::path::PathBuf;
error_chain! {
@@ -33,17 +35,30 @@ static APP_INFO: AppInfo = AppInfo {
author: "Mullvad",
};
-static SETTINGS_FILE: &str = "settings.toml";
+static SETTINGS_FILE: &str = "settings.json";
#[derive(Debug, Clone, Deserialize, Serialize)]
+#[serde(default)]
pub struct Settings {
account_token: Option<String>,
- custom_relay: Option<RelayEndpoint>,
+ relay_constraints: RelayConstraints,
+}
+
+impl Default for Settings {
+ fn default() -> Self {
+ DEFAULT_SETTINGS
+ }
}
const DEFAULT_SETTINGS: Settings = Settings {
account_token: None,
- custom_relay: None,
+ relay_constraints: RelayConstraints {
+ host: None,
+ tunnel: TunnelConstraints::OpenVpn(OpenVpnConstraints {
+ port: Port::Any,
+ protocol: TransportProtocol::Udp,
+ }),
+ },
};
impl Settings {
@@ -53,7 +68,7 @@ impl Settings {
match File::open(&settings_path) {
Ok(mut file) => {
info!("Loading settings from {}", settings_path.to_string_lossy());
- Self::read_settings(&mut file, settings_path)
+ Self::read_settings(&mut file)
}
Err(ref e) if e.kind() == io::ErrorKind::NotFound => {
info!(
@@ -68,13 +83,12 @@ impl Settings {
/// Serializes the settings and saves them to the file it was loaded from.
fn save(&self) -> Result<()> {
- let settings_path = Self::get_settings_path()?;
- let data = toml::to_string(self).chain_err(|| ErrorKind::ParseError)?;
+ let path = Self::get_settings_path()?;
- debug!("Writing settings to {}", settings_path.to_string_lossy());
- File::create(&settings_path)
- .and_then(|mut file| file.write_all(data.as_bytes()))
- .chain_err(|| ErrorKind::WriteError(settings_path))
+ debug!("Writing settings to {}", path.to_string_lossy());
+ let file = File::create(&path).chain_err(|| ErrorKind::WriteError(path.clone()))?;
+
+ serde_json::to_writer_pretty(file, self).chain_err(|| ErrorKind::WriteError(path))
}
fn get_settings_path() -> Result<PathBuf> {
@@ -83,11 +97,8 @@ impl Settings {
Ok(dir.join(SETTINGS_FILE))
}
- fn read_settings(file: &mut File, path: PathBuf) -> Result<Settings> {
- let mut data = Vec::new();
- file.read_to_end(&mut data)
- .chain_err(|| ErrorKind::ReadError(path))?;
- toml::from_slice(&data).chain_err(|| ErrorKind::ParseError)
+ fn read_settings(file: &mut File) -> Result<Settings> {
+ serde_json::from_reader(file).chain_err(|| ErrorKind::ParseError)
}
pub fn get_account_token(&self) -> Option<String> {
@@ -121,18 +132,19 @@ impl Settings {
}
}
- pub fn get_custom_relay(&self) -> Option<RelayEndpoint> {
- self.custom_relay.clone()
+ pub fn get_relay_constraints(&self) -> RelayConstraints {
+ self.relay_constraints.clone()
}
- pub fn set_custom_relay(&mut self, relay_endpoint: Option<RelayEndpoint>) -> Result<bool> {
- if self.custom_relay != relay_endpoint {
- match &relay_endpoint {
- &Some(ref data) => info!("Setting a custom relay: {}", data),
- &None => info!("Removing the custom relay"),
- }
+ pub fn update_relay_constraints(&mut self, update: RelayConstraintsUpdate) -> Result<bool> {
+ let new_constraints = self.relay_constraints.update(update);
- self.custom_relay = relay_endpoint;
+ if new_constraints {
+ debug!(
+ "changed relay constraints from {:?} to {:?}",
+ self.relay_constraints,
+ new_constraints
+ );
self.save().map(|_| true)
} else {