mirror of https://github.com/dswd/vpncloud.git
Some fixes
This commit is contained in:
parent
fc18245fda
commit
cbc73d0c0e
|
@ -5,6 +5,12 @@ This project follows [semantic versioning](http://semver.org).
|
|||
### UNRELEASED
|
||||
|
||||
- [changed] Changed documentation
|
||||
- [changed] Updated dependencies
|
||||
- [changed] Retrying connections for 120 secs
|
||||
- [fixed] Fixed corner case with lost init message
|
||||
- [fixed] Do not reconnect to timed out pending connections
|
||||
- [fixed] Most specific claims beat less specific claims
|
||||
- [fixed] Count all invalid protocol traffic
|
||||
|
||||
### v2.0.0 (2020-10-30)
|
||||
|
||||
|
|
34
src/cloud.rs
34
src/cloud.rs
|
@ -55,12 +55,12 @@ struct PeerData {
|
|||
|
||||
#[derive(Clone)]
|
||||
pub struct ReconnectEntry {
|
||||
address: String,
|
||||
address: Option<(String, Time)>,
|
||||
resolved: Vec<SocketAddr>,
|
||||
next_resolve: Time,
|
||||
tries: u16,
|
||||
timeout: u16,
|
||||
next: Time
|
||||
next: Time,
|
||||
final_timeout: Option<Time>
|
||||
}
|
||||
|
||||
|
||||
|
@ -250,12 +250,12 @@ impl<D: Device, P: Protocol, S: Socket, TS: TimeSource> GenericCloud<D, P, S, TS
|
|||
}
|
||||
};
|
||||
self.reconnect_peers.push(ReconnectEntry {
|
||||
address: add,
|
||||
address: Some((add, now)),
|
||||
tries: 0,
|
||||
timeout: 1,
|
||||
resolved,
|
||||
next_resolve: now,
|
||||
next: now
|
||||
next: now,
|
||||
final_timeout: None
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -398,11 +398,13 @@ impl<D: Device, P: Protocol, S: Socket, TS: TimeSource> GenericCloud<D, P, S, TS
|
|||
}
|
||||
}
|
||||
// Resolve entries anew
|
||||
if entry.next_resolve <= now {
|
||||
if let Ok(addrs) = resolve(&entry.address as &str) {
|
||||
entry.resolved = addrs;
|
||||
if let Some((ref address, ref mut next_resolve)) = entry.address {
|
||||
if *next_resolve <= now {
|
||||
if let Ok(addrs) = resolve(address as &str) {
|
||||
entry.resolved = addrs;
|
||||
}
|
||||
*next_resolve = now + RESOLVE_INTERVAL;
|
||||
}
|
||||
entry.next_resolve = now + RESOLVE_INTERVAL;
|
||||
}
|
||||
// Ignore if next attempt is already in the future
|
||||
if entry.next > now {
|
||||
|
@ -421,6 +423,7 @@ impl<D: Device, P: Protocol, S: Socket, TS: TimeSource> GenericCloud<D, P, S, TS
|
|||
// Schedule next connection attempt
|
||||
entry.next = now + Time::from(entry.timeout);
|
||||
}
|
||||
self.reconnect_peers.retain(|e| e.final_timeout.unwrap_or(now) >= now);
|
||||
if self.next_stats_out < now {
|
||||
// Write out the statistics
|
||||
self.write_out_stats().map_err(|err| Error::FileIo("Failed to write stats file", err))?;
|
||||
|
@ -697,7 +700,10 @@ impl<D: Device, P: Protocol, S: Socket, TS: TimeSource> GenericCloud<D, P, S, TS
|
|||
}
|
||||
MESSAGE_TYPE_KEEPALIVE => self.update_peer_info(src, None)?,
|
||||
MESSAGE_TYPE_CLOSE => self.remove_peer(src),
|
||||
_ => return Err(Error::Message("Unknown message type"))
|
||||
_ => {
|
||||
self.traffic.count_invalid_protocol(data.len());
|
||||
return Err(Error::Message("Unknown message type"))
|
||||
}
|
||||
}
|
||||
}
|
||||
MessageResult::Initialized(info) => self.add_new_peer(src, info)?,
|
||||
|
@ -733,13 +739,17 @@ impl<D: Device, P: Protocol, S: Socket, TS: TimeSource> GenericCloud<D, P, S, TS
|
|||
self.pending_inits.insert(src, init);
|
||||
Ok(res)
|
||||
}
|
||||
Err(err) => return Err(err)
|
||||
Err(err) => {
|
||||
self.traffic.count_invalid_protocol(data.len());
|
||||
return Err(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if let Some(peer) = self.peers.get_mut(&src) {
|
||||
peer.crypto.handle_message(data)
|
||||
} else {
|
||||
info!("Ignoring non-init message from unknown peer {}", addr_nice(src));
|
||||
self.traffic.count_invalid_protocol(data.len());
|
||||
return Ok(())
|
||||
};
|
||||
match msg_result {
|
||||
|
|
|
@ -79,6 +79,8 @@ pub const STAGE_PENG: u8 = 3;
|
|||
pub const WAITING_TO_CLOSE: u8 = 4;
|
||||
pub const CLOSING: u8 = 5;
|
||||
|
||||
pub const MAX_FAILED_RETRIES: usize = 120;
|
||||
|
||||
pub const SALTED_NODE_ID_HASH_LEN: usize = 20;
|
||||
pub type SaltedNodeIdHash = [u8; SALTED_NODE_ID_HASH_LEN];
|
||||
|
||||
|
@ -447,7 +449,7 @@ impl<P: Payload> InitState<P> {
|
|||
Ok(())
|
||||
} else if self.next_stage == CLOSING {
|
||||
Ok(())
|
||||
} else if self.failed_retries < 5 {
|
||||
} else if self.failed_retries < MAX_FAILED_RETRIES {
|
||||
self.failed_retries += 1;
|
||||
self.repeat_last_message(out);
|
||||
Ok(())
|
||||
|
@ -632,8 +634,9 @@ impl<P: Payload> InitState<P> {
|
|||
}
|
||||
|
||||
// decrypt the payload
|
||||
let peer_payload =
|
||||
self.decrypt(&mut encrypted_payload).map_err(|_| Error::CryptoInitFatal("Failed to decrypt payload"))?;
|
||||
let peer_payload = self
|
||||
.decrypt(&mut encrypted_payload)
|
||||
.map_err(|_| Error::CryptoInitFatal("Failed to decrypt payload"))?;
|
||||
|
||||
// create and send stage 3 reply
|
||||
self.send_message(STAGE_PENG, None, out);
|
||||
|
@ -644,8 +647,9 @@ impl<P: Payload> InitState<P> {
|
|||
}
|
||||
InitMsg::Peng { mut encrypted_payload, .. } => {
|
||||
// decrypt the payload
|
||||
let peer_payload =
|
||||
self.decrypt(&mut encrypted_payload).map_err(|_| Error::CryptoInitFatal("Failed to decrypt payload"))?;
|
||||
let peer_payload = self
|
||||
.decrypt(&mut encrypted_payload)
|
||||
.map_err(|_| Error::CryptoInitFatal("Failed to decrypt payload"))?;
|
||||
|
||||
self.next_stage = CLOSING; // force resend when receiving any message
|
||||
Ok(InitResult::Success { peer_payload, is_initiator: false })
|
||||
|
@ -921,10 +925,7 @@ mod tests {
|
|||
|
||||
// Fail if no match
|
||||
test_algorithm_negotiation(
|
||||
Algorithms {
|
||||
algorithm_speeds: smallvec![(&AES_128_GCM, 600.0)],
|
||||
allow_unencrypted: true
|
||||
},
|
||||
Algorithms { algorithm_speeds: smallvec![(&AES_128_GCM, 600.0)], allow_unencrypted: true },
|
||||
Algorithms {
|
||||
algorithm_speeds: smallvec![(&AES_256_GCM, 500.0), (&CHACHA20_POLY1305, 400.0)],
|
||||
allow_unencrypted: false
|
||||
|
|
22
src/table.rs
22
src/table.rs
|
@ -88,15 +88,21 @@ impl<TS: TimeSource> ClaimTable<TS> {
|
|||
if let Some(entry) = self.cache.get(&addr) {
|
||||
return Some(entry.peer)
|
||||
}
|
||||
let mut found = None;
|
||||
let mut prefix_len = -1;
|
||||
for entry in &self.claims {
|
||||
if entry.claim.matches(addr) {
|
||||
self.cache.insert(addr, CacheValue {
|
||||
peer: entry.peer,
|
||||
timeout: min(TS::now() + self.cache_timeout as Time, entry.timeout)
|
||||
});
|
||||
return Some(entry.peer)
|
||||
if entry.claim.prefix_len as isize > prefix_len && entry.claim.matches(addr) {
|
||||
found = Some(entry);
|
||||
prefix_len = entry.claim.prefix_len as isize;
|
||||
}
|
||||
}
|
||||
if let Some(entry) = found {
|
||||
self.cache.insert(addr, CacheValue {
|
||||
peer: entry.peer,
|
||||
timeout: min(TS::now() + self.cache_timeout as Time, entry.timeout)
|
||||
});
|
||||
return Some(entry.peer)
|
||||
}
|
||||
None
|
||||
}
|
||||
|
||||
|
@ -149,9 +155,9 @@ mod bench {
|
|||
use super::*;
|
||||
use crate::util::MockTimeSource;
|
||||
|
||||
use test::Bencher;
|
||||
use std::str::FromStr;
|
||||
use smallvec::smallvec;
|
||||
use std::str::FromStr;
|
||||
use test::Bencher;
|
||||
|
||||
#[bench]
|
||||
fn lookup_warm(b: &mut Bencher) {
|
||||
|
|
Loading…
Reference in New Issue