Просмотр исходного кода

p2pnet: patch validate hosts ips before storing: added missing ranges

aggstam 3 лет назад
Родитель
Сommit
366c917021
3 измененных файлов с 44 добавлено и 5 удалено
  1. 17 0
      Cargo.lock
  2. 4 0
      Cargo.toml
  3. 23 5
      src/net/hosts.rs

+ 17 - 0
Cargo.lock

@@ -1210,6 +1210,8 @@ dependencies = [
  "incrementalmerkletree",
  "indexmap",
  "indicatif",
+ "ipnet",
+ "iprange",
  "itertools",
  "lazy-init",
  "lazy_static",
@@ -2331,6 +2333,21 @@ dependencies = [
  "cfg-if 1.0.0",
 ]
 
+[[package]]
+name = "ipnet"
+version = "2.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "879d54834c8c76457ef4293a689b2a8c59b076067ad77b15efafbb05f92a592b"
+
+[[package]]
+name = "iprange"
+version = "0.6.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "37209be0ad225457e63814401415e748e2453a5297f9b637338f5fb8afa4ec00"
+dependencies = [
+ "ipnet",
+]
+
 [[package]]
 name = "ircd"
 version = "0.4.0"

+ 4 - 0
Cargo.toml

@@ -58,6 +58,8 @@ smol = {version = "1.2.5", optional = true}
 
 # Networking
 futures-rustls = {version = "0.22.2", features = ["dangerous_configuration"], optional = true}
+iprange = {version = "0.6.7", optional = true}
+ipnet = {version = "2.5.0", optional = true}
 socket2 = {version = "0.4.7", optional = true}
 
 # TLS cert utilities
@@ -212,6 +214,8 @@ net = [
     "fast-socks5",
     "futures-rustls",
     "hex",
+    "iprange",
+    "ipnet",
     "structopt",
     "structopt-toml",
     "rand",

+ 23 - 5
src/net/hosts.rs

@@ -2,6 +2,8 @@ use async_std::sync::{Arc, Mutex};
 use std::net::IpAddr;
 
 use fxhash::FxHashSet;
+use ipnet::{Ipv4Net, Ipv6Net};
+use iprange::IpRange;
 use url::Url;
 
 use super::constants::{IP4_PRIV_RANGES, IP6_PRIV_RANGES, LOCALNET};
@@ -13,19 +15,31 @@ pub type HostsPtr = Arc<Hosts>;
 pub struct Hosts {
     addrs: Mutex<FxHashSet<Url>>,
     localnet: bool,
+    ipv4_range: IpRange<Ipv4Net>,
+    ipv6_range: IpRange<Ipv6Net>,
 }
 
 impl Hosts {
     /// Create a new host list.
     pub fn new(localnet: bool) -> Arc<Self> {
-        Arc::new(Self { addrs: Mutex::new(FxHashSet::default()), localnet })
+        // Initialize ipv4_range and ipv6_range if needed
+        let mut ipv4_range: IpRange<Ipv4Net> =
+            IP4_PRIV_RANGES.iter().map(|s| s.parse().unwrap()).collect();
+        let mut ipv6_range: IpRange<Ipv6Net> =
+            IP6_PRIV_RANGES.iter().map(|s| s.parse().unwrap()).collect();
+
+        // These will make the trie potentially smaller
+        ipv4_range.simplify();
+        ipv6_range.simplify();
+
+        Arc::new(Self { addrs: Mutex::new(FxHashSet::default()), localnet, ipv4_range, ipv6_range })
     }
 
     /// Add a new host to the host list, after filtering.
     pub async fn store(&self, input_addrs: Vec<Url>) {
         let addrs = if !self.localnet {
             let filtered = filter_localnet(input_addrs);
-            filter_invalid(filtered)
+            filter_invalid(&self.ipv4_range, &self.ipv6_range, filtered)
         } else {
             input_addrs
         };
@@ -70,7 +84,11 @@ fn filter_localnet(input_addrs: Vec<Url>) -> Vec<Url> {
 }
 
 /// Auxiliary function to filter invalid(unresolvable) hosts.
-fn filter_invalid(input_addrs: Vec<Url>) -> Vec<Url> {
+fn filter_invalid(
+    ipv4_range: &IpRange<Ipv4Net>,
+    ipv6_range: &IpRange<Ipv6Net>,
+    input_addrs: Vec<Url>,
+) -> Vec<Url> {
     let mut filtered = vec![];
     for addr in &input_addrs {
         // Discard domainless Urls
@@ -96,13 +114,13 @@ fn filter_invalid(input_addrs: Vec<Url>) -> Vec<Url> {
             for i in socket_addrs {
                 match i.ip() {
                     IpAddr::V4(a) => {
-                        if IP4_PRIV_RANGES.contains(&a.to_string().as_str()) {
+                        if ipv4_range.contains(&a) {
                             valid = false;
                             break
                         }
                     }
                     IpAddr::V6(a) => {
-                        if IP6_PRIV_RANGES.contains(&a.to_string().as_str()) {
+                        if ipv6_range.contains(&a) {
                             valid = false;
                             break
                         }