Przeglądaj źródła

p2pnet/hosts.rs: refactor filterring, debug logging added

aggstam 3 lat temu
rodzic
commit
fac5cf0c05
1 zmienionych plików z 79 dodań i 39 usunięć
  1. 79 39
      src/net/hosts.rs

+ 79 - 39
src/net/hosts.rs

@@ -1,9 +1,10 @@
 use async_std::sync::{Arc, Mutex};
 use async_std::sync::{Arc, Mutex};
 use std::net::IpAddr;
 use std::net::IpAddr;
 
 
-use fxhash::FxHashSet;
+use fxhash::{FxHashMap, FxHashSet};
 use ipnet::{Ipv4Net, Ipv6Net};
 use ipnet::{Ipv4Net, Ipv6Net};
 use iprange::IpRange;
 use iprange::IpRange;
+use log::debug;
 use url::Url;
 use url::Url;
 
 
 use super::constants::{IP4_PRIV_RANGES, IP6_PRIV_RANGES, LOCALNET};
 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.
     /// Add a new host to the host list, after filtering.
     pub async fn store(&self, input_addrs: Vec<Url>) {
     pub async fn store(&self, input_addrs: Vec<Url>) {
+        debug!(target: "net", "hosts::store() [Start]");
         let addrs = if !self.localnet {
         let addrs = if !self.localnet {
             let filtered = filter_localnet(input_addrs);
             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 {
         } else {
+            debug!(target: "net", "hosts::store() [Localnet mode, skipping filterring.]");
             input_addrs
             input_addrs
         };
         };
         let mut addrs_map = self.addrs.lock().await;
         let mut addrs_map = self.addrs.lock().await;
         for addr in addrs {
         for addr in addrs {
             addrs_map.insert(addr);
             addrs_map.insert(addr);
         }
         }
+        debug!(target: "net", "hosts::store() [End]");
     }
     }
 
 
     /// Add a new hosts external adders to the host list, after filtering and verifying
     /// Add a new hosts external adders to the host list, after filtering and verifying
     /// the address url resolves to the provided connection address.
     /// the address url resolves to the provided connection address.
     pub async fn store_ext(&self, connection_addr: Url, input_addrs: Vec<Url>) {
     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 addrs = if !self.localnet {
             let filtered = filter_localnet(input_addrs);
             let filtered = filter_localnet(input_addrs);
             let filtered = filter_invalid(&self.ipv4_range, &self.ipv6_range, filtered);
             let filtered = filter_invalid(&self.ipv4_range, &self.ipv6_range, filtered);
             filter_non_resolving(connection_addr, filtered)
             filter_non_resolving(connection_addr, filtered)
         } else {
         } else {
+            debug!(target: "net", "hosts::store_ext() [Localnet mode, skipping filterring.]");
             input_addrs
             input_addrs
         };
         };
         let mut addrs_map = self.addrs.lock().await;
         let mut addrs_map = self.addrs.lock().await;
         for addr in addrs {
         for addr in addrs {
             addrs_map.insert(addr);
             addrs_map.insert(addr);
         }
         }
+        debug!(target: "net", "hosts::store_ext() [End]");
     }
     }
 
 
     /// Return the list of hosts.
     /// Return the list of hosts.
@@ -83,18 +91,24 @@ impl Hosts {
 
 
 /// Auxiliary function to filter localnet hosts.
 /// Auxiliary function to filter localnet hosts.
 fn filter_localnet(input_addrs: Vec<Url>) -> Vec<Url> {
 fn filter_localnet(input_addrs: Vec<Url>) -> Vec<Url> {
+    debug!(target: "net", "hosts::filter_localnet() [Input addresses: {:?}]", input_addrs);
     let mut filtered = vec![];
     let mut filtered = vec![];
     for addr in &input_addrs {
     for addr in &input_addrs {
         match addr.host_str() {
         match addr.host_str() {
             Some(host_str) => {
             Some(host_str) => {
                 if LOCALNET.contains(&host_str) {
                 if LOCALNET.contains(&host_str) {
+                    debug!(target: "net", "hosts::filter_localnet() [Filtered LOCALNET host_str: {}]", host_str);
                     continue
                     continue
                 }
                 }
             }
             }
-            None => continue,
+            None => {
+                debug!(target: "net", "hosts::filter_localnet() [Filtered None host_str for addr: {}]", addr);
+                continue
+            }
         }
         }
         filtered.push(addr.clone());
         filtered.push(addr.clone());
     }
     }
+    debug!(target: "net", "hosts::filter_localnet() [Filtered addresses: {:?}]", filtered);
     filtered
     filtered
 }
 }
 
 
@@ -103,58 +117,80 @@ fn filter_invalid(
     ipv4_range: &IpRange<Ipv4Net>,
     ipv4_range: &IpRange<Ipv4Net>,
     ipv6_range: &IpRange<Ipv6Net>,
     ipv6_range: &IpRange<Ipv6Net>,
     input_addrs: Vec<Url>,
     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 {
     for addr in &input_addrs {
         // Discard domainless Urls
         // Discard domainless Urls
         let domain = match addr.domain() {
         let domain = match addr.domain() {
             Some(d) => d,
             Some(d) => d,
-            None => continue,
+            None => {
+                debug!(target: "net", "hosts::filter_invalid() [Filtered domainless url: {}]", addr);
+                continue
+            }
         };
         };
 
 
         // Validate onion domain
         // Validate onion domain
         if domain.ends_with(".onion") && is_valid_onion(domain) {
         if domain.ends_with(".onion") && is_valid_onion(domain) {
-            filtered.push(addr.clone());
+            filtered.insert(addr.clone(), vec![]);
             continue
             continue
         }
         }
 
 
         // Validate normal domain
         // 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
     filtered
 }
 }
 
 
 /// Auxiliary function to filter unresolvable hosts, based on provided connection addr (excluding onion).
 /// 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();
     let connection_domain = connection_addr.domain().unwrap();
     // Validate connection onion domain
     // Validate connection onion domain
     if connection_domain.ends_with(".onion") && !is_valid_onion(connection_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![]
         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
     // Filter input addresses
     let mut filtered = vec![];
     let mut filtered = vec![];
-    for addr in input_addrs {
+    for (addr, resolves) in &input_addrs {
         // Keep valid onion domains
         // Keep valid onion domains
         let addr_domain = addr.domain().unwrap();
         let addr_domain = addr.domain().unwrap();
         if addr_domain.ends_with(".onion") && addr_domain == connection_domain {
         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
         // 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) => {
                 IpAddr::V4(a) => {
-                    if !ipv4_range.contains(&a) {
-                        valid = false;
+                    if ipv4_range.contains(&a) {
+                        valid = true;
                         break
                         break
                     }
                     }
                 }
                 }
                 IpAddr::V6(a) => {
                 IpAddr::V6(a) => {
-                    if !ipv6_range.contains(&a) {
-                        valid = false;
+                    if ipv6_range.contains(&a) {
+                        valid = true;
                         break
                         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
     filtered
 }
 }