From 991c6435c1018066f28bc673713cf93176f67a9d Mon Sep 17 00:00:00 2001 From: Jake McGinty Date: Thu, 11 Nov 2021 18:34:31 +0900 Subject: [PATCH] client: wait after updating interface before attempting NAT traversal otherwise, the server-reported IP itself won't have time to check if a handshake succeeds or not. --- client/src/main.rs | 11 +++++++---- client/src/nat.rs | 6 +++++- server/src/initialize.rs | 2 +- shared/src/types.rs | 15 +++++++++++++-- 4 files changed, 26 insertions(+), 8 deletions(-) diff --git a/client/src/main.rs b/client/src/main.rs index 13455b8..bacd30d 100644 --- a/client/src/main.rs +++ b/client/src/main.rs @@ -18,7 +18,7 @@ use std::{ net::SocketAddr, path::{Path, PathBuf}, thread, - time::Duration, + time::{Duration, Instant}, }; use structopt::{clap::AppSettings, StructOpt}; use wireguard_control::{Device, DeviceUpdate, InterfaceName, PeerConfigBuilder, PeerInfo}; @@ -546,6 +546,7 @@ fn fetch( } else { log::info!("{}", "peers are already up to date.".green()); } + let interface_updated_time = Instant::now(); store.set_cidrs(cidrs); store.update_peers(&peers)?; @@ -559,7 +560,6 @@ fn fetch( candidates.len(), if candidates.len() == 1 { "" } else { "es" } ); - log::debug!("candidates: {:?}", candidates); match Api::new(&config.server).http_form::<_, ()>("PUT", "/user/candidates", &candidates) { Err(ureq::Error::Status(404, _)) => { log::warn!("your network is using an old version of innernet-server that doesn't support NAT traversal candidate reporting.") @@ -567,10 +567,13 @@ fn fetch( Err(e) => return Err(e.into()), _ => {}, } - - log::debug!("viable ICE candidates: {:?}", candidates); + log::debug!("reported candidates: {:?}", candidates); let mut nat_traverse = NatTraverse::new(interface, network.backend, &modifications)?; + + if !nat_traverse.is_finished() { + thread::sleep(nat::STEP_INTERVAL - interface_updated_time.elapsed()); + } loop { if nat_traverse.is_finished() { break; diff --git a/client/src/nat.rs b/client/src/nat.rs index 351c924..41b7b2d 100644 --- a/client/src/nat.rs +++ b/client/src/nat.rs @@ -12,7 +12,7 @@ use shared::{ }; use wireguard_control::{Backend, Device, DeviceUpdate, InterfaceName, Key, PeerConfigBuilder}; -const STEP_INTERVAL: Duration = Duration::from_secs(5); +pub const STEP_INTERVAL: Duration = Duration::from_secs(5); pub struct NatTraverse<'a> { interface: &'a InterfaceName, @@ -26,6 +26,7 @@ impl<'a> NatTraverse<'a> { backend: Backend, diffs: &[PeerDiff], ) -> Result { + // Filter out removed peers from diffs list. let mut remaining: Vec<_> = diffs.iter().filter_map(|diff| diff.new).cloned().collect(); for peer in &mut remaining { @@ -97,6 +98,9 @@ impl<'a> NatTraverse<'a> { // Set all peers' endpoints to their next available candidate. let candidate_updates = self.remaining.iter_mut().filter_map(|peer| { let endpoint = peer.candidates.pop(); + if let Some(endpoint) = &endpoint { + log::debug!("trying endpoint {} for peer {}", endpoint, peer.name); + } set_endpoint(&peer.public_key, endpoint.as_ref()) }); diff --git a/server/src/initialize.rs b/server/src/initialize.rs index 236a2c3..acb5991 100644 --- a/server/src/initialize.rs +++ b/server/src/initialize.rs @@ -5,7 +5,7 @@ use dialoguer::{theme::ColorfulTheme, Input}; use indoc::printdoc; use publicip::Preference; use rusqlite::{params, Connection}; -use shared::{CidrContents, Endpoint, PERSISTENT_KEEPALIVE_INTERVAL_SECS, PeerContents, prompts}; +use shared::{prompts, CidrContents, Endpoint, PeerContents, PERSISTENT_KEEPALIVE_INTERVAL_SECS}; use wireguard_control::KeyPair; fn create_database>( diff --git a/shared/src/types.rs b/shared/src/types.rs index f23766d..0bbcfa0 100644 --- a/shared/src/types.rs +++ b/shared/src/types.rs @@ -3,7 +3,16 @@ use ipnetwork::IpNetwork; use lazy_static::lazy_static; use regex::Regex; use serde::{Deserialize, Serialize}; -use std::{fmt::{self, Display, Formatter}, io, net::{IpAddr, SocketAddr, ToSocketAddrs}, ops::{Deref, DerefMut}, path::Path, str::FromStr, time::{Duration, SystemTime}, vec}; +use std::{ + fmt::{self, Display, Formatter}, + io, + net::{IpAddr, SocketAddr, ToSocketAddrs}, + ops::{Deref, DerefMut}, + path::Path, + str::FromStr, + time::{Duration, SystemTime}, + vec, +}; use structopt::StructOpt; use url::Host; use wireguard_control::{ @@ -25,7 +34,9 @@ impl FromStr for Interface { if !Hostname::is_valid(name) { Err(InvalidInterfaceName::InvalidChars) } else { - Ok(Self { name: name.parse()? }) + Ok(Self { + name: name.parse()?, + }) } } }