summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorLinus Färnstrand <linus@mullvad.net>2018-11-13 06:16:48 +0100
committerLinus Färnstrand <linus@mullvad.net>2018-11-13 13:34:09 +0100
commitf048c66ab3672b32098158f97a56ac6a0717c976 (patch)
treea6aee9db2e37a9a723ca1f2140e8bedf96ba0c16
parente59ac7a68a5cdda11d82b4a69ad33fddd3b3d294 (diff)
downloadmullvadvpn-f048c66ab3672b32098158f97a56ac6a0717c976.tar.xz
mullvadvpn-f048c66ab3672b32098158f97a56ac6a0717c976.zip
Add block_on_disconnected setting, for never unblocking the firewall
-rw-r--r--mullvad-daemon/src/lib.rs27
-rw-r--r--mullvad-daemon/src/management_interface.rs22
-rw-r--r--mullvad-ipc-client/src/lib.rs4
-rw-r--r--mullvad-types/src/settings.rs17
-rw-r--r--talpid-core/src/tunnel_state_machine/blocked_state.rs4
-rw-r--r--talpid-core/src/tunnel_state_machine/connected_state.rs4
-rw-r--r--talpid-core/src/tunnel_state_machine/connecting_state.rs4
-rw-r--r--talpid-core/src/tunnel_state_machine/disconnected_state.rs41
-rw-r--r--talpid-core/src/tunnel_state_machine/disconnecting_state.rs12
-rw-r--r--talpid-core/src/tunnel_state_machine/mod.rs10
10 files changed, 137 insertions, 8 deletions
diff --git a/mullvad-daemon/src/lib.rs b/mullvad-daemon/src/lib.rs
index f420afdff2..b5ef9dd21e 100644
--- a/mullvad-daemon/src/lib.rs
+++ b/mullvad-daemon/src/lib.rs
@@ -220,6 +220,7 @@ impl Daemon {
let tunnel_parameters_generator = MullvadTunnelParametersGenerator { tx: tx.clone() };
let tunnel_command_tx = tunnel_state_machine::spawn(
settings.get_allow_lan(),
+ settings.get_block_when_disconnected(),
tunnel_parameters_generator,
log_dir,
resource_dir,
@@ -423,6 +424,9 @@ impl Daemon {
SetAccount(tx, account_token) => self.on_set_account(tx, account_token),
UpdateRelaySettings(tx, update) => self.on_update_relay_settings(tx, update),
SetAllowLan(tx, allow_lan) => self.on_set_allow_lan(tx, allow_lan),
+ SetBlockWhenDisconnected(tx, block_when_disconnected) => {
+ self.on_set_block_when_disconnected(tx, block_when_disconnected)
+ }
SetAutoConnect(tx, auto_connect) => self.on_set_auto_connect(tx, auto_connect),
SetOpenVpnMssfix(tx, mssfix_arg) => self.on_set_openvpn_mssfix(tx, mssfix_arg),
SetOpenVpnProxy(tx, proxy) => self.on_set_openvpn_proxy(tx, proxy),
@@ -601,6 +605,29 @@ impl Daemon {
}
}
+ fn on_set_block_when_disconnected(
+ &mut self,
+ tx: oneshot::Sender<()>,
+ block_when_disconnected: bool,
+ ) {
+ let save_result = self
+ .settings
+ .set_block_when_disconnected(block_when_disconnected);
+ match save_result.chain_err(|| "Unable to save settings") {
+ Ok(settings_changed) => {
+ Self::oneshot_send(tx, (), "set_block_when_disconnected response");
+ if settings_changed {
+ self.management_interface_broadcaster
+ .notify_settings(&self.settings);
+ self.send_tunnel_command(TunnelCommand::BlockWhenDisconnected(
+ block_when_disconnected,
+ ));
+ }
+ }
+ Err(e) => error!("{}", e.display_chain()),
+ }
+ }
+
fn on_set_auto_connect(&mut self, tx: oneshot::Sender<()>, auto_connect: bool) {
let save_result = self.settings.set_auto_connect(auto_connect);
match save_result.chain_err(|| "Unable to save settings") {
diff --git a/mullvad-daemon/src/management_interface.rs b/mullvad-daemon/src/management_interface.rs
index d306e4c33f..f9eb8ffa63 100644
--- a/mullvad-daemon/src/management_interface.rs
+++ b/mullvad-daemon/src/management_interface.rs
@@ -65,6 +65,10 @@ build_rpc_trait! {
#[rpc(meta, name = "set_allow_lan")]
fn set_allow_lan(&self, Self::Metadata, bool) -> BoxFuture<(), Error>;
+ /// Set if the client should allow network communication when in the disconnected state.
+ #[rpc(meta, name = "set_block_when_disconnected")]
+ fn set_block_when_disconnected(&self, Self::Metadata, bool) -> BoxFuture<(), Error>;
+
/// Set if the daemon should automatically establish a tunnel on start or not.
#[rpc(meta, name = "set_auto_connect")]
fn set_auto_connect(&self, Self::Metadata, bool) -> BoxFuture<(), Error>;
@@ -176,6 +180,8 @@ pub enum ManagementCommand {
UpdateRelaySettings(OneshotSender<()>, RelaySettingsUpdate),
/// Set the allow LAN setting.
SetAllowLan(OneshotSender<()>, bool),
+ /// Set the block_when_disconnected setting.
+ SetBlockWhenDisconnected(OneshotSender<()>, bool),
/// Set the auto-connect setting.
SetAutoConnect(OneshotSender<()>, bool),
/// Set the mssfix argument for OpenVPN
@@ -455,6 +461,22 @@ impl<T: From<ManagementCommand> + 'static + Send> ManagementInterfaceApi
Box::new(future)
}
+ fn set_block_when_disconnected(
+ &self,
+ _: Self::Metadata,
+ block_when_disconnected: bool,
+ ) -> BoxFuture<(), Error> {
+ log::debug!("set_block_when_disconnected({})", block_when_disconnected);
+ let (tx, rx) = sync::oneshot::channel();
+ let future = self
+ .send_command_to_daemon(ManagementCommand::SetBlockWhenDisconnected(
+ tx,
+ block_when_disconnected,
+ ))
+ .and_then(|_| rx.map_err(|_| Error::internal_error()));
+ Box::new(future)
+ }
+
fn set_auto_connect(&self, _: Self::Metadata, auto_connect: bool) -> BoxFuture<(), Error> {
log::debug!("set_auto_connect({})", auto_connect);
let (tx, rx) = sync::oneshot::channel();
diff --git a/mullvad-ipc-client/src/lib.rs b/mullvad-ipc-client/src/lib.rs
index c38f6d4fc1..7f2c6a17c1 100644
--- a/mullvad-ipc-client/src/lib.rs
+++ b/mullvad-ipc-client/src/lib.rs
@@ -143,6 +143,10 @@ impl DaemonRpcClient {
self.call("set_allow_lan", &[allow_lan])
}
+ pub fn set_block_when_disconnected(&mut self, block_when_disconnected: bool) -> Result<()> {
+ self.call("set_block_when_disconnected", &[block_when_disconnected])
+ }
+
pub fn get_allow_lan(&mut self) -> Result<bool> {
self.call("get_allow_lan", &NO_ARGS)
}
diff --git a/mullvad-types/src/settings.rs b/mullvad-types/src/settings.rs
index 15e336dae4..a6a1b95e2c 100644
--- a/mullvad-types/src/settings.rs
+++ b/mullvad-types/src/settings.rs
@@ -44,6 +44,9 @@ pub struct Settings {
relay_settings: RelaySettings,
/// If the daemon should allow communication with private (LAN) networks.
allow_lan: bool,
+ /// Extra level of kill switch. When this setting is on, the disconnected state will block
+ /// the firewall to not allow any traffic in or out.
+ block_when_disconnected: bool,
/// If the daemon should connect the VPN tunnel directly on start or not.
auto_connect: bool,
/// Options that should be applied to tunnels of a specific type regardless of where the relays
@@ -60,6 +63,7 @@ impl Default for Settings {
tunnel: Constraint::Any,
}),
allow_lan: false,
+ block_when_disconnected: false,
auto_connect: false,
tunnel_options: TunnelOptions::default(),
}
@@ -165,6 +169,19 @@ impl Settings {
}
}
+ pub fn get_block_when_disconnected(&self) -> bool {
+ self.block_when_disconnected
+ }
+
+ pub fn set_block_when_disconnected(&mut self, block_when_disconnected: bool) -> Result<bool> {
+ if block_when_disconnected != self.block_when_disconnected {
+ self.block_when_disconnected = block_when_disconnected;
+ self.save().map(|_| true)
+ } else {
+ Ok(false)
+ }
+ }
+
pub fn get_auto_connect(&self) -> bool {
self.auto_connect
}
diff --git a/talpid-core/src/tunnel_state_machine/blocked_state.rs b/talpid-core/src/tunnel_state_machine/blocked_state.rs
index 3e63551110..14b72a20f8 100644
--- a/talpid-core/src/tunnel_state_machine/blocked_state.rs
+++ b/talpid-core/src/tunnel_state_machine/blocked_state.rs
@@ -58,6 +58,10 @@ impl TunnelState for BlockedState {
Self::set_security_policy(shared_values);
SameState(self)
}
+ Ok(TunnelCommand::BlockWhenDisconnected(block_when_disconnected)) => {
+ shared_values.block_when_disconnected = block_when_disconnected;
+ SameState(self)
+ }
Ok(TunnelCommand::IsOffline(is_offline)) => {
shared_values.is_offline = is_offline;
if !is_offline && self.block_reason == BlockReason::IsOffline {
diff --git a/talpid-core/src/tunnel_state_machine/connected_state.rs b/talpid-core/src/tunnel_state_machine/connected_state.rs
index 577f435260..fa6735f145 100644
--- a/talpid-core/src/tunnel_state_machine/connected_state.rs
+++ b/talpid-core/src/tunnel_state_machine/connected_state.rs
@@ -94,6 +94,10 @@ impl ConnectedState {
}
}
}
+ Ok(TunnelCommand::BlockWhenDisconnected(block_when_disconnected)) => {
+ shared_values.block_when_disconnected = block_when_disconnected;
+ SameState(self)
+ }
Ok(TunnelCommand::IsOffline(is_offline)) => {
shared_values.is_offline = is_offline;
if is_offline {
diff --git a/talpid-core/src/tunnel_state_machine/connecting_state.rs b/talpid-core/src/tunnel_state_machine/connecting_state.rs
index df0a00744e..e4d81dd51e 100644
--- a/talpid-core/src/tunnel_state_machine/connecting_state.rs
+++ b/talpid-core/src/tunnel_state_machine/connecting_state.rs
@@ -211,6 +211,10 @@ impl ConnectingState {
}
}
}
+ Ok(TunnelCommand::BlockWhenDisconnected(block_when_disconnected)) => {
+ shared_values.block_when_disconnected = block_when_disconnected;
+ SameState(self)
+ }
Ok(TunnelCommand::IsOffline(is_offline)) => {
shared_values.is_offline = is_offline;
if is_offline {
diff --git a/talpid-core/src/tunnel_state_machine/disconnected_state.rs b/talpid-core/src/tunnel_state_machine/disconnected_state.rs
index 60444e9cc7..643395931f 100644
--- a/talpid-core/src/tunnel_state_machine/disconnected_state.rs
+++ b/talpid-core/src/tunnel_state_machine/disconnected_state.rs
@@ -1,7 +1,8 @@
use super::{
- BlockedState, ConnectingState, Error, EventConsequence, SharedTunnelStateValues, TunnelCommand,
- TunnelState, TunnelStateTransition, TunnelStateWrapper,
+ BlockedState, ConnectingState, EventConsequence, ResultExt, SharedTunnelStateValues,
+ TunnelCommand, TunnelState, TunnelStateTransition, TunnelStateWrapper,
};
+use crate::security::SecurityPolicy;
use error_chain::ChainedError;
use futures::sync::mpsc;
use futures::Stream;
@@ -10,10 +11,23 @@ use futures::Stream;
pub struct DisconnectedState;
impl DisconnectedState {
- fn reset_security_policy(shared_values: &mut SharedTunnelStateValues) {
- if let Err(error) = shared_values.security.reset_policy() {
- let chained_error = Error::with_chain(error, "Failed to reset security policy");
- log::error!("{}", chained_error.display_chain());
+ fn set_security_policy(shared_values: &mut SharedTunnelStateValues) {
+ let result = if shared_values.block_when_disconnected {
+ let policy = SecurityPolicy::Blocked {
+ allow_lan: shared_values.allow_lan,
+ };
+ shared_values
+ .security
+ .apply_policy(policy)
+ .chain_err(|| "Failed to apply blocking security policy for disconnected state")
+ } else {
+ shared_values
+ .security
+ .reset_policy()
+ .chain_err(|| "Failed to reset security policy")
+ };
+ if let Err(error) = result {
+ log::error!("{}", error.display_chain());
}
}
}
@@ -25,8 +39,7 @@ impl TunnelState for DisconnectedState {
shared_values: &mut SharedTunnelStateValues,
_: Self::Bootstrap,
) -> (TunnelStateWrapper, TunnelStateTransition) {
- Self::reset_security_policy(shared_values);
-
+ Self::set_security_policy(shared_values);
(
TunnelStateWrapper::from(DisconnectedState),
TunnelStateTransition::Disconnected,
@@ -42,7 +55,19 @@ impl TunnelState for DisconnectedState {
match try_handle_event!(self, commands.poll()) {
Ok(TunnelCommand::AllowLan(allow_lan)) => {
+ let changed = shared_values.allow_lan != allow_lan;
shared_values.allow_lan = allow_lan;
+ if changed {
+ Self::set_security_policy(shared_values);
+ }
+ SameState(self)
+ }
+ Ok(TunnelCommand::BlockWhenDisconnected(block_when_disconnected)) => {
+ let changed = shared_values.block_when_disconnected != block_when_disconnected;
+ shared_values.block_when_disconnected = block_when_disconnected;
+ if changed {
+ Self::set_security_policy(shared_values);
+ }
SameState(self)
}
Ok(TunnelCommand::IsOffline(is_offline)) => {
diff --git a/talpid-core/src/tunnel_state_machine/disconnecting_state.rs b/talpid-core/src/tunnel_state_machine/disconnecting_state.rs
index 7ebb637d2d..928880f274 100644
--- a/talpid-core/src/tunnel_state_machine/disconnecting_state.rs
+++ b/talpid-core/src/tunnel_state_machine/disconnecting_state.rs
@@ -33,6 +33,10 @@ impl DisconnectingState {
shared_values.allow_lan = allow_lan;
AfterDisconnect::Nothing
}
+ Ok(TunnelCommand::BlockWhenDisconnected(block_when_disconnected)) => {
+ shared_values.block_when_disconnected = block_when_disconnected;
+ AfterDisconnect::Nothing
+ }
Ok(TunnelCommand::IsOffline(is_offline)) => {
shared_values.is_offline = is_offline;
AfterDisconnect::Nothing
@@ -46,6 +50,10 @@ impl DisconnectingState {
shared_values.allow_lan = allow_lan;
AfterDisconnect::Block(reason)
}
+ Ok(TunnelCommand::BlockWhenDisconnected(block_when_disconnected)) => {
+ shared_values.block_when_disconnected = block_when_disconnected;
+ AfterDisconnect::Block(reason)
+ }
Ok(TunnelCommand::IsOffline(is_offline)) => {
shared_values.is_offline = is_offline;
if !is_offline && reason == BlockReason::IsOffline {
@@ -64,6 +72,10 @@ impl DisconnectingState {
shared_values.allow_lan = allow_lan;
AfterDisconnect::Reconnect(retry_attempt)
}
+ Ok(TunnelCommand::BlockWhenDisconnected(block_when_disconnected)) => {
+ shared_values.block_when_disconnected = block_when_disconnected;
+ AfterDisconnect::Reconnect(retry_attempt)
+ }
Ok(TunnelCommand::IsOffline(is_offline)) => {
shared_values.is_offline = is_offline;
if is_offline {
diff --git a/talpid-core/src/tunnel_state_machine/mod.rs b/talpid-core/src/tunnel_state_machine/mod.rs
index e44ec91234..d952e458f2 100644
--- a/talpid-core/src/tunnel_state_machine/mod.rs
+++ b/talpid-core/src/tunnel_state_machine/mod.rs
@@ -43,6 +43,7 @@ error_chain! {
/// Spawn the tunnel state machine thread, returning a channel for sending tunnel commands.
pub fn spawn<P, T>(
allow_lan: bool,
+ block_when_disconnected: bool,
tunnel_parameters_generator: impl TunnelParametersGenerator,
log_dir: Option<PathBuf>,
resource_dir: PathBuf,
@@ -62,6 +63,7 @@ where
thread::spawn(move || {
match create_event_loop(
allow_lan,
+ block_when_disconnected,
is_offline,
tunnel_parameters_generator,
log_dir,
@@ -97,6 +99,7 @@ where
fn create_event_loop<T>(
allow_lan: bool,
+ block_when_disconnected: bool,
is_offline: bool,
tunnel_parameters_generator: impl TunnelParametersGenerator,
log_dir: Option<PathBuf>,
@@ -111,6 +114,7 @@ where
let reactor = Core::new().chain_err(|| ErrorKind::ReactorError)?;
let state_machine = TunnelStateMachine::new(
allow_lan,
+ block_when_disconnected,
is_offline,
tunnel_parameters_generator,
log_dir,
@@ -132,6 +136,8 @@ where
pub enum TunnelCommand {
/// Enable or disable LAN access in the firewall.
AllowLan(bool),
+ /// Enable or disable the block_when_disconnected feature.
+ BlockWhenDisconnected(bool),
/// Notify the state machine of the connectivity of the device.
IsOffline(bool),
/// Open tunnel connection.
@@ -168,6 +174,7 @@ struct TunnelStateMachine {
impl TunnelStateMachine {
fn new(
allow_lan: bool,
+ block_when_disconnected: bool,
is_offline: bool,
tunnel_parameters_generator: impl TunnelParametersGenerator,
log_dir: Option<PathBuf>,
@@ -180,6 +187,7 @@ impl TunnelStateMachine {
let mut shared_values = SharedTunnelStateValues {
security,
allow_lan,
+ block_when_disconnected,
is_offline,
tunnel_parameters_generator: Box::new(tunnel_parameters_generator),
log_dir,
@@ -258,6 +266,8 @@ struct SharedTunnelStateValues {
security: NetworkSecurity,
/// Should LAN access be allowed outside the tunnel.
allow_lan: bool,
+ /// Should network access be allowed when in the disconnected state.
+ block_when_disconnected: bool,
/// True when the computer is known to be offline.
is_offline: bool,
/// The generator of new `TunnelParameter`s