aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJake McGinty <me@jake.su>2018-02-15 04:39:01 +0000
committerJake McGinty <me@jake.su>2018-02-15 04:39:01 +0000
commitadda3a848b149211b1ed8417ec21472b0ad60f68 (patch)
tree520eecd324cb508c17e2f06a17383497fb6d93fe
parentuse x25519-dalek for a significant performance boost (diff)
downloadwireguard-rs-adda3a848b149211b1ed8417ec21472b0ad60f68.tar.xz
wireguard-rs-adda3a848b149211b1ed8417ec21472b0ad60f68.zip
proper passive keepalives
-rw-r--r--Cargo.lock2
-rw-r--r--Cargo.toml2
-rw-r--r--src/consts.rs21
-rw-r--r--src/interface/peer_server.rs42
-rw-r--r--src/protocol/peer.rs11
-rw-r--r--src/timer.rs4
6 files changed, 50 insertions, 32 deletions
diff --git a/Cargo.lock b/Cargo.lock
index cfcb30a..68d67a1 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -1179,7 +1179,7 @@ dependencies = [
"failure 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
"futures 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)",
"hex 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "lazy_static 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)",
+ "lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
"nix 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
diff --git a/Cargo.toml b/Cargo.toml
index e41c495..6f4fa82 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -33,7 +33,7 @@ daemonize = "0.2"
env_logger = "^0.4"
failure = "^0.1"
futures = "^0.1"
-lazy_static = "^0.2"
+lazy_static = "^1"
log = "^0.3"
hex = "^0.3"
rand = "^0.4"
diff --git a/src/consts.rs b/src/consts.rs
index 1989832..27f53dd 100644
--- a/src/consts.rs
+++ b/src/consts.rs
@@ -1,23 +1,22 @@
#![allow(dead_code)]
use std::u64;
+use std::time::Duration;
-// transport ratcheting time limits, in seconds
-pub const REKEY_ATTEMPT_TIME: u64 = 90;
-pub const REKEY_AFTER_TIME: u64 = 120;
-pub const REJECT_AFTER_TIME: u64 = 180;
+lazy_static! {
+ pub static ref REKEY_ATTEMPT_TIME: Duration = Duration::new(90, 0);
+ pub static ref REKEY_AFTER_TIME: Duration = Duration::new(121, 0);
+ pub static ref REJECT_AFTER_TIME: Duration = Duration::new(180, 0);
+ pub static ref REKEY_TIMEOUT: Duration = Duration::new(5, 0);
+ pub static ref KEEPALIVE_TIMEOUT: Duration = Duration::new(10, 0);
+ pub static ref RECEIVE_REKEY_TIMEOUT: Duration = *REKEY_AFTER_TIME - *KEEPALIVE_TIMEOUT - *REKEY_TIMEOUT;
+ pub static ref TIMER_TICK_DURATION: Duration = Duration::from_millis(100);
+}
// transport ratcheting message limits, in seconds
pub const REKEY_AFTER_MESSAGES: u64 = u64::MAX - (1 << 16) - 1;
pub const REJECT_AFTER_MESSAGES: u64 = u64::MAX - (1 << 4) - 1;
-// how often to attempt rekeying
-pub const REKEY_TIMEOUT: u64 = 5;
-
-// keepalive packet timer, in seconds
-pub const KEEPALIVE_TIMEOUT: u64 = 10;
-
-pub const RECEIVE_REKEY_TIMEOUT: u64 = REKEY_AFTER_TIME - KEEPALIVE_TIMEOUT - REKEY_TIMEOUT;
pub const TRANSPORT_HEADER_SIZE: usize = 16;
pub const AEAD_TAG_SIZE: usize = 16;
diff --git a/src/interface/peer_server.rs b/src/interface/peer_server.rs
index 4149059..588e45c 100644
--- a/src/interface/peer_server.rs
+++ b/src/interface/peer_server.rs
@@ -1,12 +1,12 @@
use super::{SharedState, UtunPacket, trace_packet};
-use consts::{REKEY_TIMEOUT, REKEY_AFTER_TIME, KEEPALIVE_TIMEOUT, MAX_CONTENT_SIZE};
+use consts::{REKEY_TIMEOUT, REKEY_AFTER_TIME, KEEPALIVE_TIMEOUT, MAX_CONTENT_SIZE, TIMER_TICK_DURATION};
use protocol::{Peer, SessionType};
use noise::Noise;
use timer::{Timer, TimerMessage};
use std::io;
use std::net::{IpAddr, Ipv6Addr, SocketAddr};
-use std::time::{Duration, Instant};
+use std::time::Instant;
use byteorder::{ByteOrder, LittleEndian};
use failure::{Error, err_msg};
@@ -153,11 +153,11 @@ impl PeerServer {
// Start the timers for this new session
self.timer.spawn_delayed(&self.handle,
- REKEY_AFTER_TIME,
+ *REKEY_AFTER_TIME,
TimerMessage::Rekey(peer_ref.clone(), our_index));
self.timer.spawn_delayed(&self.handle,
- KEEPALIVE_TIMEOUT,
+ *KEEPALIVE_TIMEOUT,
TimerMessage::KeepAlive(peer_ref.clone(), our_index));
},
3 => {
@@ -202,7 +202,7 @@ impl PeerServer {
let now = Instant::now();
if let Some(last_init) = peer.last_rekey_init {
- if now.duration_since(last_init) < Duration::from_secs(REKEY_TIMEOUT) {
+ if now.duration_since(last_init) < *REKEY_TIMEOUT {
debug!("too soon since last rekey attempt");
}
}
@@ -218,19 +218,27 @@ impl PeerServer {
},
TimerMessage::KeepAlive(peer_ref, our_index) => {
let mut peer = peer_ref.borrow_mut();
- match peer.find_session(our_index) {
- Some((_, SessionType::Current)) => {
- self.send_to_peer(peer.handle_outgoing_transport(&[])?);
- debug!("sent keepalive packet ({})", our_index);
-
- self.timer.spawn_delayed(&self.handle,
- KEEPALIVE_TIMEOUT,
- TimerMessage::KeepAlive(peer_ref.clone(), our_index));
- }
- _ => {
- debug!("keepalive timer received for non-current session, ignoring.");
+ {
+ let (session, session_type) = peer.find_session(our_index).ok_or_else(|| err_msg("missing session for timer"))?;
+ ensure!(session_type == SessionType::Current, "expired session for timer");
+
+ if let Some(last_sent) = session.last_sent {
+ let last_sent_packet = Instant::now().duration_since(last_sent);
+ if last_sent_packet < *KEEPALIVE_TIMEOUT {
+ self.timer.spawn_delayed(&self.handle,
+ *KEEPALIVE_TIMEOUT - last_sent_packet + *TIMER_TICK_DURATION,
+ TimerMessage::KeepAlive(peer_ref.clone(), our_index));
+ bail!("passive keepalive tick (waiting {:?})", *KEEPALIVE_TIMEOUT - last_sent_packet);
+ }
}
}
+
+ self.send_to_peer(peer.handle_outgoing_transport(&[])?);
+ debug!("sent keepalive packet ({})", our_index);
+
+ self.timer.spawn_delayed(&self.handle,
+ *KEEPALIVE_TIMEOUT,
+ TimerMessage::KeepAlive(peer_ref.clone(), our_index));
}
}
Ok(())
@@ -271,7 +279,7 @@ impl Future for PeerServer {
loop {
match self.timer.poll() {
Ok(Async::Ready(Some(message))) => {
- let _ = self.handle_timer(message).map_err(|e| warn!("TIMER ERR: {:?}", e));
+ let _ = self.handle_timer(message).map_err(|e| debug!("TIMER: {}", e));
},
Ok(Async::NotReady) => break,
Ok(Async::Ready(None)) | Err(_) => return Err(()),
diff --git a/src/protocol/peer.rs b/src/protocol/peer.rs
index dc1d666..bfa3173 100644
--- a/src/protocol/peer.rs
+++ b/src/protocol/peer.rs
@@ -40,6 +40,8 @@ pub struct Session {
pub our_index: u32,
pub their_index: u32,
pub anti_replay: AntiReplay,
+ pub last_sent: Option<Instant>,
+ pub last_received: Option<Instant>,
}
impl Session {
@@ -50,6 +52,8 @@ impl Session {
our_index: rand::thread_rng().gen::<u32>(),
their_index,
anti_replay: AntiReplay::default(),
+ last_sent: None,
+ last_received: None,
}
}
@@ -59,6 +63,8 @@ impl Session {
our_index: self.our_index,
their_index: self.their_index,
anti_replay: self.anti_replay,
+ last_sent: self.last_sent,
+ last_received: self.last_received,
}
}
}
@@ -70,6 +76,8 @@ impl From<snow::Session> for Session {
our_index: rand::thread_rng().gen::<u32>(),
their_index: 0,
anti_replay: AntiReplay::default(),
+ last_sent: None,
+ last_received: None,
}
}
}
@@ -232,6 +240,8 @@ impl Peer {
let len = session.noise.read_message(&packet[16..], &mut raw_packet).map_err(SyncFailure::new)?;
raw_packet.truncate(len);
+ session.last_received = Some(Instant::now());
+
session_type
};
@@ -266,6 +276,7 @@ impl Peer {
let len = session.noise.write_message(packet, &mut out_packet[16..])
.map_err(SyncFailure::new)?;
self.tx_bytes += len as u64;
+ session.last_sent = Some(Instant::now());
out_packet.truncate(TRANSPORT_HEADER_SIZE + len);
Ok((endpoint, out_packet))
}
diff --git a/src/timer.rs b/src/timer.rs
index 75e3fbf..16e5a5d 100644
--- a/src/timer.rs
+++ b/src/timer.rs
@@ -23,8 +23,8 @@ impl Timer {
Self { timer, tx, rx }
}
- pub fn spawn_delayed(&mut self, handle: &Handle, delay_secs: u64, message: TimerMessage) {
- let timer = self.timer.sleep(Duration::from_secs(delay_secs));
+ pub fn spawn_delayed(&mut self, handle: &Handle, delay: Duration, message: TimerMessage) {
+ let timer = self.timer.sleep(delay);
let future = timer.and_then({
let tx = self.tx.clone();
move |_| {