diff --git a/CHANGELOG.md b/CHANGELOG.md index d12b7d4..88b9c2b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -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 diff --git a/src/cloud.rs b/src/cloud.rs index cea9ecb..dc28838 100644 --- a/src/cloud.rs +++ b/src/cloud.rs @@ -227,6 +227,7 @@ pub struct GenericCloud GenericCloud 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 GenericCloud GenericCloud GenericCloud Result<(usize, SocketAddr), io::Error>; fn send(&mut self, data: &[u8], addr: SocketAddr) -> Result; fn address(&self) -> Result; + fn detect_nat() -> bool; } impl Socket for UdpSocket { @@ -42,6 +45,9 @@ impl Socket for UdpSocket { fn address(&self) -> Result { self.local_addr() } + fn detect_nat() -> bool { + get_internal_ip().is_private() + } } @@ -95,4 +101,7 @@ impl Socket for MockSocket { fn address(&self) -> Result { Ok(self.address) } + fn detect_nat() -> bool { + false + } } diff --git a/src/port_forwarding.rs b/src/port_forwarding.rs index 4accc47..a283ae1 100644 --- a/src/port_forwarding.rs +++ b/src/port_forwarding.rs @@ -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, diff --git a/src/util.rs b/src/util.rs index c861f0b..d32ec3d 100644 --- a/src/util.rs +++ b/src/util.rs @@ -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: Addr) -> Result, Error> {