mirror of
https://github.com/darkrenaissance/darkfi.git
synced 2026-04-28 03:00:18 -04:00
p2pnet/hosts.rs: refactor filterring, debug logging added
This commit is contained in:
118
src/net/hosts.rs
118
src/net/hosts.rs
@@ -1,9 +1,10 @@
|
||||
use async_std::sync::{Arc, Mutex};
|
||||
use std::net::IpAddr;
|
||||
|
||||
use fxhash::FxHashSet;
|
||||
use fxhash::{FxHashMap, FxHashSet};
|
||||
use ipnet::{Ipv4Net, Ipv6Net};
|
||||
use iprange::IpRange;
|
||||
use log::debug;
|
||||
use url::Url;
|
||||
|
||||
use super::constants::{IP4_PRIV_RANGES, IP6_PRIV_RANGES, LOCALNET};
|
||||
@@ -37,32 +38,39 @@ impl Hosts {
|
||||
|
||||
/// Add a new host to the host list, after filtering.
|
||||
pub async fn store(&self, input_addrs: Vec<Url>) {
|
||||
debug!(target: "net", "hosts::store() [Start]");
|
||||
let addrs = if !self.localnet {
|
||||
let filtered = filter_localnet(input_addrs);
|
||||
filter_invalid(&self.ipv4_range, &self.ipv6_range, filtered)
|
||||
let filtered = filter_invalid(&self.ipv4_range, &self.ipv6_range, filtered);
|
||||
filtered.into_iter().map(|(k, _)| k).collect()
|
||||
} else {
|
||||
debug!(target: "net", "hosts::store() [Localnet mode, skipping filterring.]");
|
||||
input_addrs
|
||||
};
|
||||
let mut addrs_map = self.addrs.lock().await;
|
||||
for addr in addrs {
|
||||
addrs_map.insert(addr);
|
||||
}
|
||||
debug!(target: "net", "hosts::store() [End]");
|
||||
}
|
||||
|
||||
/// Add a new hosts external adders to the host list, after filtering and verifying
|
||||
/// the address url resolves to the provided connection address.
|
||||
pub async fn store_ext(&self, connection_addr: Url, input_addrs: Vec<Url>) {
|
||||
debug!(target: "net", "hosts::store_ext() [Start]");
|
||||
let addrs = if !self.localnet {
|
||||
let filtered = filter_localnet(input_addrs);
|
||||
let filtered = filter_invalid(&self.ipv4_range, &self.ipv6_range, filtered);
|
||||
filter_non_resolving(connection_addr, filtered)
|
||||
} else {
|
||||
debug!(target: "net", "hosts::store_ext() [Localnet mode, skipping filterring.]");
|
||||
input_addrs
|
||||
};
|
||||
let mut addrs_map = self.addrs.lock().await;
|
||||
for addr in addrs {
|
||||
addrs_map.insert(addr);
|
||||
}
|
||||
debug!(target: "net", "hosts::store_ext() [End]");
|
||||
}
|
||||
|
||||
/// Return the list of hosts.
|
||||
@@ -83,18 +91,24 @@ impl Hosts {
|
||||
|
||||
/// Auxiliary function to filter localnet hosts.
|
||||
fn filter_localnet(input_addrs: Vec<Url>) -> Vec<Url> {
|
||||
debug!(target: "net", "hosts::filter_localnet() [Input addresses: {:?}]", input_addrs);
|
||||
let mut filtered = vec![];
|
||||
for addr in &input_addrs {
|
||||
match addr.host_str() {
|
||||
Some(host_str) => {
|
||||
if LOCALNET.contains(&host_str) {
|
||||
debug!(target: "net", "hosts::filter_localnet() [Filtered LOCALNET host_str: {}]", host_str);
|
||||
continue
|
||||
}
|
||||
}
|
||||
None => continue,
|
||||
None => {
|
||||
debug!(target: "net", "hosts::filter_localnet() [Filtered None host_str for addr: {}]", addr);
|
||||
continue
|
||||
}
|
||||
}
|
||||
filtered.push(addr.clone());
|
||||
}
|
||||
debug!(target: "net", "hosts::filter_localnet() [Filtered addresses: {:?}]", filtered);
|
||||
filtered
|
||||
}
|
||||
|
||||
@@ -103,58 +117,80 @@ fn filter_invalid(
|
||||
ipv4_range: &IpRange<Ipv4Net>,
|
||||
ipv6_range: &IpRange<Ipv6Net>,
|
||||
input_addrs: Vec<Url>,
|
||||
) -> Vec<Url> {
|
||||
let mut filtered = vec![];
|
||||
) -> FxHashMap<Url, Vec<IpAddr>> {
|
||||
debug!(target: "net", "hosts::filter_invalid() [Input addresses: {:?}]", input_addrs);
|
||||
let mut filtered = FxHashMap::default();
|
||||
for addr in &input_addrs {
|
||||
// Discard domainless Urls
|
||||
let domain = match addr.domain() {
|
||||
Some(d) => d,
|
||||
None => continue,
|
||||
None => {
|
||||
debug!(target: "net", "hosts::filter_invalid() [Filtered domainless url: {}]", addr);
|
||||
continue
|
||||
}
|
||||
};
|
||||
|
||||
// Validate onion domain
|
||||
if domain.ends_with(".onion") && is_valid_onion(domain) {
|
||||
filtered.push(addr.clone());
|
||||
filtered.insert(addr.clone(), vec![]);
|
||||
continue
|
||||
}
|
||||
|
||||
// Validate normal domain
|
||||
if let Ok(socket_addrs) = addr.socket_addrs(|| None) {
|
||||
// Check if domain resolved to anything
|
||||
if socket_addrs.is_empty() {
|
||||
continue
|
||||
}
|
||||
// Checking resolved IP validity
|
||||
let mut valid = true;
|
||||
for i in socket_addrs {
|
||||
match i.ip() {
|
||||
IpAddr::V4(a) => {
|
||||
if ipv4_range.contains(&a) {
|
||||
valid = false;
|
||||
break
|
||||
match addr.socket_addrs(|| None) {
|
||||
Ok(socket_addrs) => {
|
||||
// Check if domain resolved to anything
|
||||
if socket_addrs.is_empty() {
|
||||
debug!(target: "net", "hosts::filter_invalid() [Filtered unresolvable url: {}]", addr);
|
||||
continue
|
||||
}
|
||||
// Checking resolved IP validity
|
||||
let mut resolves = vec![];
|
||||
for i in socket_addrs {
|
||||
let ip = i.ip();
|
||||
match ip {
|
||||
IpAddr::V4(a) => {
|
||||
if ipv4_range.contains(&a) {
|
||||
debug!(target: "net", "hosts::filter_invalid() [Filtered invalid ip: {}]", a);
|
||||
continue
|
||||
}
|
||||
resolves.push(ip);
|
||||
}
|
||||
}
|
||||
IpAddr::V6(a) => {
|
||||
if ipv6_range.contains(&a) {
|
||||
valid = false;
|
||||
break
|
||||
IpAddr::V6(a) => {
|
||||
if ipv6_range.contains(&a) {
|
||||
debug!(target: "net", "hosts::filter_invalid() [Filtered invalid ip: {}]", a);
|
||||
continue
|
||||
}
|
||||
resolves.push(ip);
|
||||
}
|
||||
}
|
||||
}
|
||||
if resolves.is_empty() {
|
||||
debug!(target: "net", "hosts::filter_invalid() [Filtered unresolvable url: {}]", addr);
|
||||
continue
|
||||
}
|
||||
filtered.insert(addr.clone(), resolves);
|
||||
}
|
||||
if valid {
|
||||
filtered.push(addr.clone());
|
||||
Err(err) => {
|
||||
debug!(target: "net", "hosts::filter_invalid() [Filtered Err(socket_addrs) for url {}: {}]", addr, err)
|
||||
}
|
||||
}
|
||||
}
|
||||
debug!(target: "net", "hosts::filter_invalid() [Filtered addresses: {:?}]", filtered);
|
||||
filtered
|
||||
}
|
||||
|
||||
/// Auxiliary function to filter unresolvable hosts, based on provided connection addr (excluding onion).
|
||||
fn filter_non_resolving(connection_addr: Url, input_addrs: Vec<Url>) -> Vec<Url> {
|
||||
fn filter_non_resolving(
|
||||
connection_addr: Url,
|
||||
input_addrs: FxHashMap<Url, Vec<IpAddr>>,
|
||||
) -> Vec<Url> {
|
||||
debug!(target: "net", "hosts::filter_non_resolving() [Input addresses: {:?}]", input_addrs);
|
||||
debug!(target: "net", "hosts::filter_non_resolving() [Connection address: {}]", connection_addr);
|
||||
let connection_domain = connection_addr.domain().unwrap();
|
||||
// Validate connection onion domain
|
||||
if connection_domain.ends_with(".onion") && !is_valid_onion(connection_domain) {
|
||||
debug!(target: "net", "hosts::filter_non_resolving() [Tor connection detected, skipping filterring.]");
|
||||
return vec![]
|
||||
}
|
||||
|
||||
@@ -171,10 +207,12 @@ fn filter_non_resolving(connection_addr: Url, input_addrs: Vec<Url>) -> Vec<Url>
|
||||
}
|
||||
}
|
||||
}
|
||||
debug!(target: "net", "hosts::filter_non_resolving() [ipv4_range: {:?}]", ipv4_range);
|
||||
debug!(target: "net", "hosts::filter_non_resolving() [ipv6_range: {:?}]", ipv6_range);
|
||||
|
||||
// Filter input addresses
|
||||
let mut filtered = vec![];
|
||||
for addr in input_addrs {
|
||||
for (addr, resolves) in &input_addrs {
|
||||
// Keep valid onion domains
|
||||
let addr_domain = addr.domain().unwrap();
|
||||
if addr_domain.ends_with(".onion") && addr_domain == connection_domain {
|
||||
@@ -183,28 +221,30 @@ fn filter_non_resolving(connection_addr: Url, input_addrs: Vec<Url>) -> Vec<Url>
|
||||
}
|
||||
|
||||
// Checking IP validity
|
||||
let mut valid = true;
|
||||
let socket_addrs = addr.socket_addrs(|| None).unwrap();
|
||||
for i in socket_addrs {
|
||||
match i.ip() {
|
||||
let mut valid = false;
|
||||
for ip in resolves {
|
||||
match ip {
|
||||
IpAddr::V4(a) => {
|
||||
if !ipv4_range.contains(&a) {
|
||||
valid = false;
|
||||
if ipv4_range.contains(&a) {
|
||||
valid = true;
|
||||
break
|
||||
}
|
||||
}
|
||||
IpAddr::V6(a) => {
|
||||
if !ipv6_range.contains(&a) {
|
||||
valid = false;
|
||||
if ipv6_range.contains(&a) {
|
||||
valid = true;
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if valid {
|
||||
filtered.push(addr.clone());
|
||||
if !valid {
|
||||
debug!(target: "net", "hosts::filter_non_resolving() [Filtered unresolvable url: {}]", addr);
|
||||
continue
|
||||
}
|
||||
filtered.push(addr.clone());
|
||||
}
|
||||
debug!(target: "net", "hosts::filter_non_resolving() [Filtered addresses: {:?}]", filtered);
|
||||
filtered
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user