diff options
| author | Janito Vaqueiro Ferreira Filho <janito@mullvad.net> | 2018-09-06 08:57:14 -0300 |
|---|---|---|
| committer | Janito Vaqueiro Ferreira Filho <janito@mullvad.net> | 2018-09-06 08:57:14 -0300 |
| commit | d051e71ae289a92be1743a6b844d290cbfae4fd9 (patch) | |
| tree | 1f5c410b06b846fa588b8536b77d4872c2b13c7f /talpid-core | |
| parent | c448ca931fddacce052a392614d2d906033ca933 (diff) | |
| parent | 1c9d41c964c3844aa2cf5aaa557b6d549f93f298 (diff) | |
| download | mullvadvpn-d051e71ae289a92be1743a6b844d290cbfae4fd9.tar.xz mullvadvpn-d051e71ae289a92be1743a6b844d290cbfae4fd9.zip | |
Merge branch 'check-ipv6-enabled'
Diffstat (limited to 'talpid-core')
| -rw-r--r-- | talpid-core/Cargo.toml | 1 | ||||
| -rw-r--r-- | talpid-core/src/lib.rs | 2 | ||||
| -rw-r--r-- | talpid-core/src/tunnel/mod.rs | 52 | ||||
| -rw-r--r-- | talpid-core/src/tunnel_state_machine/connecting_state.rs | 34 |
4 files changed, 78 insertions, 11 deletions
diff --git a/talpid-core/Cargo.toml b/talpid-core/Cargo.toml index 23df76dfd8..1041d184a3 100644 --- a/talpid-core/Cargo.toml +++ b/talpid-core/Cargo.toml @@ -43,6 +43,7 @@ tokio-core = "0.1" [target.'cfg(windows)'.dependencies] widestring = "0.3" +winreg = "0.5" [dev-dependencies] tempfile = "3.0" diff --git a/talpid-core/src/lib.rs b/talpid-core/src/lib.rs index 55df5e135f..ecc530aec3 100644 --- a/talpid-core/src/lib.rs +++ b/talpid-core/src/lib.rs @@ -34,6 +34,8 @@ extern crate tokio_core; extern crate uuid; #[cfg(target_os = "linux")] extern crate which; +#[cfg(windows)] +extern crate winreg; extern crate openvpn_plugin; extern crate talpid_ipc; diff --git a/talpid-core/src/tunnel/mod.rs b/talpid-core/src/tunnel/mod.rs index ce49ea7b0d..59f032b286 100644 --- a/talpid-core/src/tunnel/mod.rs +++ b/talpid-core/src/tunnel/mod.rs @@ -60,6 +60,10 @@ error_chain!{ CredentialsWriteError { description("Error while writing credentials to temporary file") } + /// Tunnel can't have IPv6 enabled because the system has disabled IPv6 support. + EnableIpv6Error { + description("Can't enable IPv6 on tunnel interface because IPv6 is disabled") + } /// Running on an operating system which is not supported yet. UnsupportedPlatform { description("Running on an unsupported operating system") @@ -150,10 +154,9 @@ impl TunnelMonitor { where L: Fn(TunnelEvent) + Send + Sync + 'static, { - match tunnel_endpoint.tunnel { - TunnelEndpointData::OpenVpn(_) => (), - TunnelEndpointData::Wireguard(_) => bail!(ErrorKind::UnsupportedTunnelProtocol), - } + Self::ensure_endpoint_is_openvpn(&tunnel_endpoint)?; + Self::ensure_ipv6_can_be_used_if_enabled(tunnel_options)?; + let user_pass_file = Self::create_user_pass_file(username).chain_err(|| ErrorKind::CredentialsWriteError)?; let cmd = Self::create_openvpn_cmd( @@ -188,6 +191,21 @@ impl TunnelMonitor { }) } + fn ensure_endpoint_is_openvpn(endpoint: &TunnelEndpoint) -> Result<()> { + match endpoint.tunnel { + TunnelEndpointData::OpenVpn(_) => Ok(()), + TunnelEndpointData::Wireguard(_) => bail!(ErrorKind::UnsupportedTunnelProtocol), + } + } + + fn ensure_ipv6_can_be_used_if_enabled(tunnel_options: &TunnelOptions) -> Result<()> { + if tunnel_options.enable_ipv6 && !is_ipv6_enabled_in_os() { + bail!(ErrorKind::EnableIpv6Error); + } else { + Ok(()) + } + } + fn create_openvpn_cmd( remote: Endpoint, tunnel_alias: Option<OsString>, @@ -297,3 +315,29 @@ impl CloseHandle { self.0.close() } } + +fn is_ipv6_enabled_in_os() -> bool { + #[cfg(windows)] + { + use winreg::enums::*; + use winreg::RegKey; + + const IPV6_DISABLED: u8 = 0xFF; + + RegKey::predef(HKEY_LOCAL_MACHINE) + .open_subkey(r#"SYSTEM\CurrentControlSet\Services\Tcpip6\Parameters"#) + .and_then(|ipv6_config| ipv6_config.get_value("DisabledComponents")) + .map(|ipv6_disabled_bits: u32| (ipv6_disabled_bits & 0xFF) == IPV6_DISABLED as u32) + .unwrap_or(false) + } + #[cfg(target_os = "linux")] + { + fs::read_to_string("/proc/sys/net/ipv6/conf/all/disable_ipv6") + .map(|disable_ipv6| disable_ipv6.trim() == "0") + .unwrap_or(false) + } + #[cfg(target_os = "macos")] + { + true + } +} diff --git a/talpid-core/src/tunnel_state_machine/connecting_state.rs b/talpid-core/src/tunnel_state_machine/connecting_state.rs index 80fd94f364..6c31a08c69 100644 --- a/talpid-core/src/tunnel_state_machine/connecting_state.rs +++ b/talpid-core/src/tunnel_state_machine/connecting_state.rs @@ -14,12 +14,12 @@ use talpid_types::tunnel::BlockReason; use super::{ AfterDisconnect, BlockedState, ConnectedState, ConnectedStateBootstrap, DisconnectingState, - EventConsequence, Result, ResultExt, SharedTunnelStateValues, TunnelCommand, TunnelParameters, - TunnelState, TunnelStateTransition, TunnelStateWrapper, + EventConsequence, SharedTunnelStateValues, TunnelCommand, TunnelParameters, TunnelState, + TunnelStateTransition, TunnelStateWrapper, }; use logging; use security::SecurityPolicy; -use tunnel::{CloseHandle, TunnelEvent, TunnelMetadata, TunnelMonitor}; +use tunnel::{self, CloseHandle, TunnelEvent, TunnelMetadata, TunnelMonitor}; const MIN_TUNNEL_ALIVE_TIME: Duration = Duration::from_millis(1000); @@ -31,6 +31,18 @@ const TUNNEL_INTERFACE_ALIAS: Option<&str> = Some("Mullvad"); #[cfg(not(windows))] const TUNNEL_INTERFACE_ALIAS: Option<&str> = None; +error_chain! { + errors { + RotateLogError { + description("Failed to rotate tunnel log file") + } + } + + links { + TunnelMonitorError(tunnel::Error, tunnel::ErrorKind); + } +} + /// The tunnel has been started, but it is not established/functional. pub struct ConnectingState { tunnel_events: mpsc::UnboundedReceiver<TunnelEvent>, @@ -101,7 +113,7 @@ impl ConnectingState { }; let log_file = Self::prepare_tunnel_log_file(¶meters)?; - TunnelMonitor::new( + Ok(TunnelMonitor::new( parameters.endpoint, ¶meters.options, TUNNEL_INTERFACE_ALIAS.to_owned().map(OsString::from), @@ -109,7 +121,7 @@ impl ConnectingState { log_file.as_ref().map(PathBuf::as_path), ¶meters.resource_dir, on_tunnel_event, - ).chain_err(|| "Unable to start tunnel monitor") + )?) } fn prepare_tunnel_log_file(parameters: &TunnelParameters) -> Result<Option<PathBuf>> { @@ -119,7 +131,7 @@ impl ConnectingState { TunnelEndpointData::Wireguard(_) => WIREGUARD_LOG_FILENAME, }; let tunnel_log = log_dir.join(filename); - logging::rotate_log(&tunnel_log).chain_err(|| "Unable to rotate tunnel log")?; + logging::rotate_log(&tunnel_log).chain_err(|| ErrorKind::RotateLogError)?; Ok(Some(tunnel_log)) } else { Ok(None) @@ -291,9 +303,17 @@ impl TunnelState for ConnectingState { TunnelStateTransition::Connecting, ), Err(error) => { + let block_reason = match *error.kind() { + ErrorKind::TunnelMonitorError(tunnel::ErrorKind::EnableIpv6Error) => { + BlockReason::Ipv6Unavailable + } + _ => BlockReason::StartTunnelError, + }; + let chained_error = error.chain_err(|| "Failed to start tunnel"); error!("{}", chained_error.display_chain()); - BlockedState::enter(shared_values, (BlockReason::StartTunnelError, allow_lan)) + + BlockedState::enter(shared_values, (block_reason, allow_lan)) } } } |
