Reducing published peer timeout to 5 min on NAT

This commit is contained in:
Dennis Schwerdel 2019-12-04 10:34:08 +01:00
parent ee8542307f
commit 9cd7e53880
5 changed files with 40 additions and 21 deletions

View File

@ -4,6 +4,8 @@ This project follows [semantic versioning](http://semver.org).
### Unreleased
- [added] Exchange peer timeout and adapt keepalive accordingly
- [added] Reducing published peer timeout to 5 min when NAT is detected
- [changed] Rust version 1.41.0
- [changed] Updated dependencies

View File

@ -227,6 +227,7 @@ pub struct GenericCloud<D: Device, P: Protocol, T: Table, S: Socket, TS: TimeSou
device: D,
crypto: Crypto,
next_peerlist: Time,
peer_timeout_publish: u16,
update_freq: u16,
buffer_out: [u8; 64 * 1024],
next_housekeep: Time,
@ -255,15 +256,22 @@ impl<D: Device, P: Protocol, T: Table, S: Socket, TS: TimeSource> GenericCloud<D
Err(err) => fail!("Failed to open ipv6 address ::{}: {}", config.port, err)
};
let now = TS::now();
let peer_timeout_publish = if S::detect_nat() {
info!("Private IP detected, setting published peer timeout to 300s");
300
} else {
config.peer_timeout as u16
};
let mut res = GenericCloud {
magic: config.get_magic(),
node_id: random(),
peers: PeerList::new(config.peer_timeout as Duration),
peers: PeerList::new(config.peer_timeout),
addresses,
learning,
broadcast,
reconnect_peers: Vec::new(),
own_addresses: Vec::new(),
peer_timeout_publish,
table,
socket4,
socket6,
@ -414,7 +422,7 @@ impl<D: Device, P: Protocol, T: Table, S: Socket, TS: TimeSource> GenericCloud<D
// Send a message to each resolved address
for a in resolve(&addr)? {
// Ignore error this time
let mut msg = Message::Init(0, node_id, subnets.clone(), self.config.peer_timeout as u16);
let mut msg = Message::Init(0, node_id, subnets.clone(), self.peer_timeout_publish);
self.send_msg(a, &mut msg).ok();
}
Ok(())
@ -435,7 +443,7 @@ impl<D: Device, P: Protocol, T: Table, S: Socket, TS: TimeSource> GenericCloud<D
debug!("Connecting to {:?}", addr);
let subnets = self.addresses.clone();
let node_id = self.node_id;
let mut msg = Message::Init(0, node_id, subnets.clone(), self.config.peer_timeout as u16);
let mut msg = Message::Init(0, node_id, subnets.clone(), self.peer_timeout_publish);
self.send_msg(addr, &mut msg)
}
@ -725,7 +733,7 @@ impl<D: Device, P: Protocol, T: Table, S: Socket, TS: TimeSource> GenericCloud<D
let own_node_id = self.node_id;
self.send_msg(
peer,
&mut Message::Init(stage + 1, own_node_id, own_addrs, self.config.peer_timeout as u16)
&mut Message::Init(stage + 1, own_node_id, own_addrs, self.peer_timeout_publish)
)?;
}
// Send peers in any case

View File

@ -5,6 +5,8 @@ use std::{
os::unix::io::{AsRawFd, RawFd}
};
use super::util::get_internal_ip;
use net2::UdpBuilder;
@ -14,6 +16,7 @@ pub trait Socket: AsRawFd + Sized {
fn receive(&mut self, buffer: &mut [u8]) -> Result<(usize, SocketAddr), io::Error>;
fn send(&mut self, data: &[u8], addr: SocketAddr) -> Result<usize, io::Error>;
fn address(&self) -> Result<SocketAddr, io::Error>;
fn detect_nat() -> bool;
}
impl Socket for UdpSocket {
@ -42,6 +45,9 @@ impl Socket for UdpSocket {
fn address(&self) -> Result<SocketAddr, io::Error> {
self.local_addr()
}
fn detect_nat() -> bool {
get_internal_ip().is_private()
}
}
@ -95,4 +101,7 @@ impl Socket for MockSocket {
fn address(&self) -> Result<SocketAddr, io::Error> {
Ok(self.address)
}
fn detect_nat() -> bool {
false
}
}

View File

@ -2,16 +2,13 @@
// Copyright (C) 2015-2019 Dennis Schwerdel
// This software is licensed under GPL-3 or newer (see LICENSE.md)
use std::{
io,
net::{SocketAddr, SocketAddrV4, UdpSocket}
};
use std::{io, net::SocketAddrV4};
use igd::*;
use super::util::{SystemTimeSource, Time, TimeSource};
use super::util::{get_internal_ip, SystemTimeSource, Time, TimeSource};
const LEASE_TIME: u32 = 300;
const LEASE_TIME: u32 = 1800;
const DESCRIPTION: &str = "VpnCloud";
@ -40,16 +37,7 @@ impl PortForwarding {
}
};
info!("Port-forwarding: found router at {}", gateway.addr);
// Get the internal address (this trick gets the address by opening a UDP connection which
// does not really open anything but returns the correct address)
let dummy_sock = UdpSocket::bind("0.0.0.0:0").expect("Failed to bind");
dummy_sock.connect(gateway.addr).expect("Failed to connect");
let internal_addr;
if let SocketAddr::V4(addr) = dummy_sock.local_addr().expect("Failed to get local address") {
internal_addr = SocketAddrV4::new(*addr.ip(), port);
} else {
unreachable!()
}
let internal_addr = SocketAddrV4::new(get_internal_ip(), port);
// Query the external address
let external_ip = match gateway.get_external_ip() {
Ok(ip) => ip,

View File

@ -4,7 +4,7 @@
use std::{
fmt,
net::{SocketAddr, ToSocketAddrs},
net::{Ipv4Addr, SocketAddr, ToSocketAddrs, UdpSocket},
sync::atomic::{AtomicIsize, Ordering}
};
@ -115,6 +115,18 @@ macro_rules! try_fail {
} );
}
pub fn get_internal_ip() -> Ipv4Addr {
// Get the internal address (this trick gets the address by opening a UDP connection which
// does not really open anything but returns the correct address)
let dummy_sock = UdpSocket::bind("0.0.0.0:0").expect("Failed to bind");
dummy_sock.connect("8.8.8.8:53").expect("Failed to connect");
if let SocketAddr::V4(addr) = dummy_sock.local_addr().expect("Failed to get local address") {
*addr.ip()
} else {
unreachable!()
}
}
#[allow(unknown_lints, clippy::needless_pass_by_value)]
pub fn resolve<Addr: ToSocketAddrs + fmt::Debug>(addr: Addr) -> Result<Vec<SocketAddr>, Error> {