summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorDavid Lönnhager <david.l@mullvad.net>2020-01-22 17:32:07 +0100
committerDavid Lönnhager <david.l@mullvad.net>2020-01-23 11:18:02 +0100
commit351da9a07ae6b1b4dcfb12d3fbfe66a7c238fc97 (patch)
tree478d0883f95fee0e491e003c0b78885eb5439117
parent9d26c4531c7c9f1b4ccb4beebc3910020e143b4d (diff)
downloadmullvadvpn-351da9a07ae6b1b4dcfb12d3fbfe66a7c238fc97.tar.xz
mullvadvpn-351da9a07ae6b1b4dcfb12d3fbfe66a7c238fc97.zip
Fix suspend issue for WireGuard key rotation
-rw-r--r--mullvad-daemon/src/wireguard.rs124
1 files changed, 60 insertions, 64 deletions
diff --git a/mullvad-daemon/src/wireguard.rs b/mullvad-daemon/src/wireguard.rs
index 4e29f410b9..38e9cfb908 100644
--- a/mullvad-daemon/src/wireguard.rs
+++ b/mullvad-daemon/src/wireguard.rs
@@ -8,7 +8,7 @@ use futures::{
use jsonrpc_client_core::Error as JsonRpcError;
use mullvad_types::account::AccountToken;
pub use mullvad_types::wireguard::*;
-use std::{cmp, time::Duration};
+use std::time::Duration;
pub use talpid_types::net::wireguard::{
ConnectionConfig, PrivateKey, TunnelConfig, TunnelParameters,
};
@@ -26,8 +26,9 @@ const TOO_MANY_KEYS_ERROR_CODE: i64 = -703;
const DEFAULT_AUTOMATIC_KEY_ROTATION: u32 = 7 * 24 * 60;
/// How long to wait before reattempting to rotate keys on failure (secs)
const AUTOMATIC_ROTATION_RETRY_DELAY: u64 = 5;
-/// Minimum interval used by automatic rotation (secs)
-const MINIMUM_ROTATION_INTERVAL: u64 = 5;
+/// How often to check whether the key has expired (in seconds).
+/// A short interval is used in case the computer is ever suspended.
+const KEY_CHECK_INTERVAL: u64 = 60;
#[derive(err_derive::Error, Debug)]
@@ -283,31 +284,31 @@ impl KeyManager {
_ => Error::RpcError(err),
}
}
- fn create_key_expiration_timer(
- public_key: PublicKey,
- rotation_interval_secs: u64,
- ) -> impl Future<Item = (), Error = Error> + Send {
- let last_update = public_key.created.clone();
- let key_age = Duration::from_secs(
- (Utc::now().signed_duration_since(last_update)).num_seconds() as u64,
- );
- let interval_duration = Duration::from_secs(rotation_interval_secs);
- let remaining_time = interval_duration
- .checked_sub(key_age)
- .unwrap_or(Duration::from_secs(0));
- let key_expiry = cmp::max(
- Duration::from_secs(MINIMUM_ROTATION_INTERVAL),
- remaining_time,
- );
-
- log::info!("Next key rotation (time left): {:?}", key_expiry);
+ fn create_rotation_check(
+ key: PublicKey,
+ rotation_interval_secs: u64,
+ ) -> Box<dyn Future<Item = (), Error = Error> + Send> {
+ Box::new(
+ tokio_timer::wheel()
+ .build()
+ .sleep(Duration::from_secs(KEY_CHECK_INTERVAL))
+ .map_err(|e| Error::RotationScheduleError(e))
+ .and_then(move |_| {
+ let key_age = Duration::from_secs(
+ (Utc::now().signed_duration_since(key.created)).num_seconds() as u64,
+ );
+ let remaining_time = Duration::from_secs(rotation_interval_secs)
+ .checked_sub(key_age)
+ .unwrap_or(Duration::from_secs(0));
- tokio_timer::wheel()
- .max_timeout(Duration::new(std::u64::MAX, 0))
- .build()
- .sleep(key_expiry)
- .map_err(|e| Error::RotationScheduleError(e))
+ if remaining_time == Duration::from_secs(0) {
+ Box::new(futures::future::ok(()))
+ } else {
+ Self::create_rotation_check(key, rotation_interval_secs)
+ }
+ }),
+ )
}
fn next_automatic_rotation(
@@ -316,50 +317,45 @@ impl KeyManager {
public_key: PublicKey,
rotation_interval_secs: u64,
account_token: AccountToken,
- ) -> impl Future<Item = PublicKey, Error = Error> + Send {
+ ) -> Box<dyn Future<Item = PublicKey, Error = Error> + Send> {
let expiration_timer =
- Self::create_key_expiration_timer(public_key.clone(), rotation_interval_secs);
-
-
+ Self::create_rotation_check(public_key.clone(), rotation_interval_secs);
let account_token_copy = account_token.clone();
- expiration_timer
- .and_then(move |_| {
- log::info!("Replacing WireGuard key");
+ Box::new(
+ expiration_timer
+ .and_then(move |_| {
+ log::info!("Replacing WireGuard key");
- let private_key = PrivateKey::new_from_random()
- .map_err(Error::GenerationError)
- .into_future();
- private_key.and_then(move |private_key| {
- Self::replace_key_rpc(
- http_handle.clone(),
- account_token.clone(),
- public_key.clone(),
- private_key,
- )
- .map_err(Self::map_rpc_error)
+ let private_key = PrivateKey::new_from_random()
+ .map_err(Error::GenerationError)
+ .into_future();
+ private_key.and_then(move |private_key| {
+ Self::replace_key_rpc(http_handle, account_token, public_key, private_key)
+ .map_err(Self::map_rpc_error)
+ })
})
- })
- .then(move |rpc_result| {
- match rpc_result {
- Ok(data) => {
- // Update account data
- let _ = daemon_tx.unbounded_send(InternalDaemonEvent::WgKeyEvent((
- account_token_copy,
- Ok(data.clone()),
- )));
- Ok(data.get_public_key())
+ .then(move |rpc_result| {
+ match rpc_result {
+ Ok(data) => {
+ // Update account data
+ let _ = daemon_tx.unbounded_send(InternalDaemonEvent::WgKeyEvent((
+ account_token_copy,
+ Ok(data.clone()),
+ )));
+ Ok(data.get_public_key())
+ }
+ Err(Error::TooManyKeys) => {
+ let _ = daemon_tx.unbounded_send(InternalDaemonEvent::WgKeyEvent((
+ account_token_copy,
+ Err(Error::TooManyKeys),
+ )));
+ Err(Error::TooManyKeys)
+ }
+ Err(unknown_err) => Err(unknown_err),
}
- Err(Error::TooManyKeys) => {
- let _ = daemon_tx.unbounded_send(InternalDaemonEvent::WgKeyEvent((
- account_token_copy,
- Err(Error::TooManyKeys),
- )));
- Err(Error::TooManyKeys)
- }
- Err(unknown_err) => Err(unknown_err),
- }
- })
+ }),
+ )
}
fn create_automatic_rotation(