Browse Source

timers: use kernel-esque max handshake counter for giving up on retries

jm/master
Jake McGinty 8 years ago
parent
commit
e94421cc51
  1. 2
      src/consts.rs
  2. 25
      src/interface/peer_server.rs
  3. 15
      src/peer.rs

2
src/consts.rs

@ -16,6 +16,8 @@ lazy_static! {
pub static ref TIMER_RESOLUTION : Duration = Duration::from_millis(100);
pub static ref COOKIE_REFRESH_TIME : Duration = Duration::new(120, 0);
pub static ref MAX_HANDSHAKE_ATTEMPTS : u64 = REKEY_ATTEMPT_TIME.as_secs() / REKEY_TIMEOUT.as_secs() - 1;
}
// transport ratcheting message limits, in seconds

25
src/interface/peer_server.rs

@ -1,5 +1,5 @@
use consts::{REKEY_TIMEOUT, REKEY_ATTEMPT_TIME, KEEPALIVE_TIMEOUT, STALE_SESSION_TIMEOUT,
MAX_CONTENT_SIZE, WIPE_AFTER_TIME};
use consts::{REKEY_TIMEOUT, KEEPALIVE_TIMEOUT, STALE_SESSION_TIMEOUT,
MAX_CONTENT_SIZE, WIPE_AFTER_TIME, MAX_HANDSHAKE_ATTEMPTS};
use cookie;
use interface::{SharedPeer, SharedState, State, UtunPacket};
use message::{Message, Initiation, Response, CookieReply, Transport};
@ -265,6 +265,7 @@ impl PeerServer {
let needs_handshake = {
let mut peer = peer_ref.borrow_mut();
let needs_handshake = peer.needs_new_handshake(true);
peer.queue_egress(packet);
if peer.ready_for_transport() {
@ -276,7 +277,8 @@ impl PeerServer {
self.send_to_peer(peer.handle_outgoing_transport(packet.payload())?)?;
}
}
peer.needs_new_handshake(true)
needs_handshake
};
if needs_handshake {
@ -290,8 +292,13 @@ impl PeerServer {
let shared_state = self.shared_state.clone();
let mut state = shared_state.borrow_mut();
let mut peer = peer_ref.borrow_mut();
let private_key = &state.interface_info.private_key.ok_or_else(|| err_msg("no private key!"))?;
let new_index = self.unused_index(&mut state);
if peer.timers.handshake_initialized.elapsed() < *REKEY_TIMEOUT {
bail!("skipping handshake init because of REKEY_TIMEOUT");
}
let private_key = &state.interface_info.private_key.ok_or_else(|| err_msg("no private key!"))?;
let new_index = self.unused_index(&mut state);
let (endpoint, init_packet, dead_index) = peer.initiate_new_session(private_key, new_index)?;
let _ = state.index_map.insert(new_index, peer_ref.clone());
@ -323,11 +330,11 @@ impl PeerServer {
let wait = *REKEY_TIMEOUT - peer.timers.handshake_initialized.elapsed();
self.timer.send_after(wait, Rekey(peer_ref.clone(), our_index));
bail!("too soon since last init sent, waiting {:?} ({})", wait, our_index);
} else if peer.timers.egress_queued.elapsed() > *REKEY_ATTEMPT_TIME {
peer.sessions.next = None;
bail!("REKEY_ATTEMPT_TIME exceeded, destroying session ({})", our_index);
} else if peer.timers.handshake_attempts >= *MAX_HANDSHAKE_ATTEMPTS {
bail!("REKEY_ATTEMPT_TIME exceeded, giving up.");
}
debug!("sending hanshake init (rekey re-attempt)");
peer.timers.handshake_attempts += 1;
debug!("sending hanshake init (rekey attempt #{})", peer.timers.handshake_attempts);
},
Some((_, SessionType::Current)) => {
let since_last_send = peer.timers.data_sent.elapsed();

15
src/peer.rs

@ -2,7 +2,7 @@ use anti_replay::AntiReplay;
use byteorder::{ByteOrder, LittleEndian};
use consts::{TRANSPORT_OVERHEAD, TRANSPORT_HEADER_SIZE, REKEY_AFTER_MESSAGES, REKEY_AFTER_TIME,
REKEY_AFTER_TIME_RECV, REJECT_AFTER_TIME, REJECT_AFTER_MESSAGES, PADDING_MULTIPLE,
MAX_QUEUED_PACKETS};
MAX_QUEUED_PACKETS, MAX_HANDSHAKE_ATTEMPTS};
use cookie;
use failure::{Error, err_msg};
use interface::UtunPacket;
@ -57,6 +57,7 @@ pub struct Timers {
pub handshake_completed : Timestamp,
pub handshake_initialized : Timestamp,
pub persistent_timer : Option<TimerHandle>,
pub handshake_attempts : u64,
pub keepalive_sent : bool
}
@ -172,7 +173,7 @@ impl Peer {
pub fn queue_egress(&mut self, packet: UtunPacket) {
if self.outgoing_queue.len() < MAX_QUEUED_PACKETS {
self.outgoing_queue.push_back(packet);
self.timers.egress_queued = Timestamp::now();
self.timers.handshake_attempts = 0;
} else {
debug!("dropping pending egress packet because the queue is full");
}
@ -180,7 +181,8 @@ impl Peer {
pub fn needs_new_handshake(&self, sending: bool) -> bool {
if self.sessions.next.is_some() {
return false;
trace!("needs new handshake: {} attempts", self.timers.handshake_attempts);
return self.timers.handshake_attempts >= *MAX_HANDSHAKE_ATTEMPTS;
}
if self.sessions.current.is_none() {
debug!("needs new handshake: no current session");
@ -204,7 +206,12 @@ impl Peer {
}
pub fn ready_for_transport(&self) -> bool {
self.sessions.current.is_some()
if let Some(ref current) = self.sessions.current {
current.birthday.elapsed() < *REJECT_AFTER_TIME &&
current.noise.sending_nonce().unwrap() < REJECT_AFTER_MESSAGES
} else {
false
}
}
pub fn get_mapped_indices(&self) -> Vec<u32> {

Loading…
Cancel
Save