This commit is contained in:
John Smith 2022-08-27 12:54:09 -04:00
parent 39ddb6534a
commit 4e8c1d5b4a
4 changed files with 94 additions and 37 deletions

View File

@ -45,6 +45,7 @@ pub const PUBLIC_ADDRESS_CHANGE_DETECTION_COUNT: usize = 3;
pub const PUBLIC_ADDRESS_CHECK_CACHE_SIZE: usize = 8; pub const PUBLIC_ADDRESS_CHECK_CACHE_SIZE: usize = 8;
pub const PUBLIC_ADDRESS_CHECK_TASK_INTERVAL_SECS: u32 = 60; pub const PUBLIC_ADDRESS_CHECK_TASK_INTERVAL_SECS: u32 = 60;
pub const PUBLIC_ADDRESS_INCONSISTENCY_TIMEOUT_US: u64 = 300_000_000u64; // 5 minutes pub const PUBLIC_ADDRESS_INCONSISTENCY_TIMEOUT_US: u64 = 300_000_000u64; // 5 minutes
pub const PUBLIC_ADDRESS_INCONSISTENCY_PUNISHMENT_TIMEOUT_US: u64 = 3600_000_000u64; // 60 minutes
pub const BOOT_MAGIC: &[u8; 4] = b"BOOT"; pub const BOOT_MAGIC: &[u8; 4] = b"BOOT";
pub const BOOTSTRAP_TXT_VERSION: u8 = 0; pub const BOOTSTRAP_TXT_VERSION: u8 = 0;
@ -1702,6 +1703,9 @@ impl NetworkManager {
let network_class = net.get_network_class().unwrap_or(NetworkClass::Invalid); let network_class = net.get_network_class().unwrap_or(NetworkClass::Invalid);
// Determine if our external address has likely changed // Determine if our external address has likely changed
let mut bad_public_address_detection_punishment: Option<
Box<dyn FnOnce() + Send + 'static>,
> = None;
let needs_public_address_detection = let needs_public_address_detection =
if matches!(network_class, NetworkClass::InboundCapable) { if matches!(network_class, NetworkClass::InboundCapable) {
// Get the dial info filter for this connection so we can check if we have any public dialinfo that may have changed // Get the dial info filter for this connection so we can check if we have any public dialinfo that may have changed
@ -1721,7 +1725,6 @@ impl NetworkManager {
// then we zap the network class and re-detect it // then we zap the network class and re-detect it
let inner = &mut *self.inner.lock(); let inner = &mut *self.inner.lock();
let mut inconsistencies = Vec::new(); let mut inconsistencies = Vec::new();
let mut inconsistent = false;
// Iteration goes from most recent to least recent node/address pair // Iteration goes from most recent to least recent node/address pair
let pacc = inner let pacc = inner
.public_address_check_cache .public_address_check_cache
@ -1737,24 +1740,41 @@ impl NetworkManager {
if !current_addresses.contains(a) && !pait.contains_key(reporting_ip_block) { if !current_addresses.contains(a) && !pait.contains_key(reporting_ip_block) {
// Record the origin of the inconsistency // Record the origin of the inconsistency
inconsistencies.push(*reporting_ip_block); inconsistencies.push(*reporting_ip_block);
// If we have enough inconsistencies to consider changing our public dial info,
// add them to our denylist (throttling) and go ahead and check for new
// public dialinfo
if inconsistencies.len() >= PUBLIC_ADDRESS_CHANGE_DETECTION_COUNT {
let exp_ts =
intf::get_timestamp() + PUBLIC_ADDRESS_INCONSISTENCY_TIMEOUT_US;
for i in inconsistencies {
pait.insert(i, exp_ts);
}
inconsistent = true;
break;
}
} }
} }
// If we have enough inconsistencies to consider changing our public dial info,
// add them to our denylist (throttling) and go ahead and check for new
// public dialinfo
let inconsistent = if inconsistencies.len() >= PUBLIC_ADDRESS_CHANGE_DETECTION_COUNT
{
let exp_ts = intf::get_timestamp() + PUBLIC_ADDRESS_INCONSISTENCY_TIMEOUT_US;
for i in &inconsistencies {
pait.insert(*i, exp_ts);
}
// Run this routine if the inconsistent nodes turn out to be lying
let this = self.clone();
bad_public_address_detection_punishment = Some(Box::new(move || {
let mut inner = this.inner.lock();
let pait = inner
.public_address_inconsistencies_table
.entry(key)
.or_insert_with(|| HashMap::new());
let exp_ts = intf::get_timestamp()
+ PUBLIC_ADDRESS_INCONSISTENCY_PUNISHMENT_TIMEOUT_US;
for i in inconsistencies {
pait.insert(i, exp_ts);
}
}));
true
} else {
false
};
// // debug code // // debug code
// if changed { // if inconsistent {
// trace!("public_address_check_cache: {:#?}\ncurrent_addresses: {:#?}\ninconsistencies: {}", inner // trace!("public_address_check_cache: {:#?}\ncurrent_addresses: {:#?}\ninconsistencies: {}", inner
// .public_address_check_cache, current_addresses, inconsistencies); // .public_address_check_cache, current_addresses, inconsistencies);
// } // }
@ -1799,9 +1819,8 @@ impl NetworkManager {
let mut inner = self.inner.lock(); let mut inner = self.inner.lock();
inner.public_address_check_cache.clear(); inner.public_address_check_cache.clear();
// Reset the network class and dial info so we can re-detect it // Re-detect the public dialinfo
routing_table.clear_dial_info_details(RoutingDomain::PublicInternet); net.set_needs_public_dial_info_check(bad_public_address_detection_punishment);
net.reset_network_class();
} else { } else {
let inner = self.inner.lock(); let inner = self.inner.lock();
warn!("Public address may have changed. Restarting the server may be required."); warn!("Public address may have changed. Restarting the server may be required.");

View File

@ -48,6 +48,10 @@ struct NetworkInner {
enable_ipv4: bool, enable_ipv4: bool,
enable_ipv6_global: bool, enable_ipv6_global: bool,
enable_ipv6_local: bool, enable_ipv6_local: bool,
// public dial info check
needs_public_dial_info_check: bool,
doing_public_dial_info_check: bool,
public_dial_info_check_punishment: Option<Box<dyn FnOnce() + Send + 'static>>,
// udp // udp
bound_first_udp: BTreeMap<u16, Option<(socket2::Socket, socket2::Socket)>>, bound_first_udp: BTreeMap<u16, Option<(socket2::Socket, socket2::Socket)>>,
inbound_udp_protocol_handlers: BTreeMap<SocketAddr, RawUdpProtocolHandler>, inbound_udp_protocol_handlers: BTreeMap<SocketAddr, RawUdpProtocolHandler>,
@ -89,6 +93,9 @@ impl Network {
NetworkInner { NetworkInner {
network_started: false, network_started: false,
network_needs_restart: false, network_needs_restart: false,
needs_public_dial_info_check: false,
doing_public_dial_info_check: false,
public_dial_info_check_punishment: None,
protocol_config: None, protocol_config: None,
static_public_dialinfo: ProtocolTypeSet::empty(), static_public_dialinfo: ProtocolTypeSet::empty(),
network_class: None, network_class: None,
@ -770,17 +777,30 @@ impl Network {
} }
////////////////////////////////////////// //////////////////////////////////////////
pub fn set_needs_public_dial_info_check(
&self,
punishment: Option<Box<dyn FnOnce() + Send + 'static>>,
) {
let mut inner = self.inner.lock();
inner.needs_public_dial_info_check = true;
inner.public_dial_info_check_punishment = punishment;
}
fn needs_public_dial_info_check(&self) -> bool {
let inner = self.inner.lock();
inner.needs_public_dial_info_check
}
pub fn doing_public_dial_info_check(&self) -> bool {
let inner = self.inner.lock();
inner.doing_public_dial_info_check
}
pub fn get_network_class(&self) -> Option<NetworkClass> { pub fn get_network_class(&self) -> Option<NetworkClass> {
let inner = self.inner.lock(); let inner = self.inner.lock();
inner.network_class inner.network_class
} }
#[instrument(level = "debug", skip_all)]
pub fn reset_network_class(&self) {
let mut inner = self.inner.lock();
inner.network_class = None;
}
////////////////////////////////////////// //////////////////////////////////////////
#[instrument(level = "trace", skip(self), err)] #[instrument(level = "trace", skip(self), err)]
@ -842,7 +862,8 @@ impl Network {
// If we need to figure out our network class, tick the task for it // If we need to figure out our network class, tick the task for it
if detect_address_changes { if detect_address_changes {
let network_class = self.get_network_class().unwrap_or(NetworkClass::Invalid); let network_class = self.get_network_class().unwrap_or(NetworkClass::Invalid);
if network_class == NetworkClass::Invalid { let needs_public_dial_info_check = self.needs_public_dial_info_check();
if network_class == NetworkClass::Invalid || needs_public_dial_info_check {
let routing_table = self.routing_table(); let routing_table = self.routing_table();
let rth = routing_table.get_routing_table_health(); let rth = routing_table.get_routing_table_health();

View File

@ -605,16 +605,13 @@ impl Network {
} }
#[instrument(level = "trace", skip(self), err)] #[instrument(level = "trace", skip(self), err)]
pub async fn update_network_class_task_routine( pub async fn do_public_dial_info_check(
self, &self,
stop_token: StopToken, stop_token: StopToken,
_l: u64, _l: u64,
_t: u64, _t: u64,
) -> EyreResult<()> { ) -> EyreResult<()> {
// Ensure we aren't trying to update this without clearing it first // Figure out if we can optimize TCP/WS checking since they are often on the same port
let old_network_class = self.inner.lock().network_class;
assert_eq!(old_network_class, None);
let protocol_config = self.inner.lock().protocol_config.unwrap_or_default(); let protocol_config = self.inner.lock().protocol_config.unwrap_or_default();
let tcp_same_port = if protocol_config.inbound.contains(ProtocolType::TCP) let tcp_same_port = if protocol_config.inbound.contains(ProtocolType::TCP)
&& protocol_config.inbound.contains(ProtocolType::WS) && protocol_config.inbound.contains(ProtocolType::WS)
@ -823,6 +820,26 @@ impl Network {
network_manager.send_node_info_updates(true).await; network_manager.send_node_info_updates(true).await;
} }
if !changed {}
Ok(()) Ok(())
} }
#[instrument(level = "trace", skip(self), err)]
pub async fn update_network_class_task_routine(
self,
stop_token: StopToken,
l: u64,
t: u64,
) -> EyreResult<()> {
// Note that we are doing the public dial info check
self.inner.lock().doing_public_dial_info_check = true;
// Do the public dial info check
let out = self.do_public_dial_info_check(stop_token, l, t);
// Done with public dial info check
self.inner.lock().doing_public_dial_info_check = false;
out
}
} }

View File

@ -291,6 +291,11 @@ impl Network {
} }
////////////////////////////////////////// //////////////////////////////////////////
pub fn set_needs_public_dial_info_check(&self) {
//
}
pub fn get_network_class(&self) -> Option<NetworkClass> { pub fn get_network_class(&self) -> Option<NetworkClass> {
// xxx eventually detect tor browser? // xxx eventually detect tor browser?
return if self.inner.lock().network_started { return if self.inner.lock().network_started {
@ -300,11 +305,6 @@ impl Network {
}; };
} }
pub fn reset_network_class(&self) {
//let mut inner = self.inner.lock();
//inner.network_class = None;
}
pub fn get_protocol_config(&self) -> Option<ProtocolConfig> { pub fn get_protocol_config(&self) -> Option<ProtocolConfig> {
self.inner.lock().protocol_config.clone() self.inner.lock().protocol_config.clone()
} }