Explorar el Código

net: change transport_mixing into a list of transports to be mixed allowing control of the specific transports we want to be mixed

oars hace 1 año
padre
commit
9743cc1d41
Se han modificado 5 ficheros con 149 adiciones y 60 borrados
  1. 0 6
      bin/app/src/plugin/mod.rs
  2. 13 21
      src/net/connector.rs
  3. 102 20
      src/net/hosts.rs
  4. 5 5
      src/net/session/outbound_session.rs
  5. 29 8
      src/net/settings.rs

+ 0 - 6
bin/app/src/plugin/mod.rs

@@ -241,10 +241,6 @@ impl PluginSettings {
             "net.outbound_peer_discovery_cooloff_time",
             "net.outbound_peer_discovery_cooloff_time",
             PropertyValue::Uint32(p2p_settings.outbound_peer_discovery_cooloff_time as u32),
             PropertyValue::Uint32(p2p_settings.outbound_peer_discovery_cooloff_time as u32),
         );
         );
-        self.add_setting(
-            "net.transport_mixing",
-            PropertyValue::Bool(p2p_settings.transport_mixing),
-        );
         self.add_setting("net.localnet", PropertyValue::Bool(p2p_settings.localnet));
         self.add_setting("net.localnet", PropertyValue::Bool(p2p_settings.localnet));
         self.add_setting(
         self.add_setting(
             "net.greylist_refinery_interval",
             "net.greylist_refinery_interval",
@@ -298,8 +294,6 @@ impl PluginSettings {
             .unwrap()
             .unwrap()
             .get_property_u32("value")
             .get_property_u32("value")
             .unwrap() as u64;
             .unwrap() as u64;
-        p2p_settings.transport_mixing =
-            self.get_setting("net.transport_mixing").unwrap().get_property_bool("value").unwrap();
         p2p_settings.localnet =
         p2p_settings.localnet =
             self.get_setting("net.localnet").unwrap().get_property_bool("value").unwrap();
             self.get_setting("net.localnet").unwrap().get_property_bool("value").unwrap();
         p2p_settings.greylist_refinery_interval = self
         p2p_settings.greylist_refinery_interval = self

+ 13 - 21
src/net/connector.rs

@@ -64,7 +64,7 @@ impl Connector {
 
 
         let settings = self.settings.read().await;
         let settings = self.settings.read().await;
         let transports = settings.allowed_transports.clone();
         let transports = settings.allowed_transports.clone();
-        let transport_mixing = settings.transport_mixing;
+        let mixed_transports = settings.mixed_transports.clone();
         let datastore = settings.p2p_datastore.clone();
         let datastore = settings.p2p_datastore.clone();
         let outbound_connect_timeout = settings.outbound_connect_timeout;
         let outbound_connect_timeout = settings.outbound_connect_timeout;
         let i2p_socks5_proxy = settings.i2p_socks5_proxy.clone();
         let i2p_socks5_proxy = settings.i2p_socks5_proxy.clone();
@@ -74,41 +74,33 @@ impl Connector {
         let mut endpoint = url.clone();
         let mut endpoint = url.clone();
         let scheme = endpoint.scheme();
         let scheme = endpoint.scheme();
 
 
-        if !transports.contains(&scheme.to_string()) && transport_mixing {
-            if transports.contains(&"tor".to_string()) && scheme == "tcp" {
-                endpoint.set_scheme("tor")?;
-            } else if transports.contains(&"tor+tls".to_string()) && scheme == "tcp+tls" {
-                endpoint.set_scheme("tor+tls")?;
-            } else if transports.contains(&"nym".to_string()) && scheme == "tcp" {
-                endpoint.set_scheme("nym")?;
-            } else if transports.contains(&"nym+tls".to_string()) && scheme == "tcp+tls" {
-                endpoint.set_scheme("nym+tls")?;
-            } else if transports.contains(&"socks5".to_string()) &&
-                (scheme == "tcp" || scheme == "tor")
-            {
+        if mixed_transports.contains(&scheme.to_string()) {
+            if transports.contains(&"socks5".to_string()) && (scheme == "tcp" || scheme == "tor") {
+                endpoint = tor_socks5_proxy;
                 endpoint.set_path(&format!(
                 endpoint.set_path(&format!(
                     "{}:{}",
                     "{}:{}",
                     endpoint.host().unwrap(),
                     endpoint.host().unwrap(),
                     endpoint.port().unwrap()
                     endpoint.port().unwrap()
                 ));
                 ));
-                endpoint.set_host(tor_socks5_proxy.host_str())?;
-                endpoint.set_port(tor_socks5_proxy.port())?;
-                endpoint.set_username(tor_socks5_proxy.username())?;
-                endpoint.set_password(tor_socks5_proxy.password())?;
                 endpoint.set_scheme("socks5")?;
                 endpoint.set_scheme("socks5")?;
             } else if transports.contains(&"socks5+tls".to_string()) &&
             } else if transports.contains(&"socks5+tls".to_string()) &&
                 (scheme == "tcp+tls" || scheme == "tor+tls")
                 (scheme == "tcp+tls" || scheme == "tor+tls")
             {
             {
+                endpoint = tor_socks5_proxy;
                 endpoint.set_path(&format!(
                 endpoint.set_path(&format!(
                     "{}:{}",
                     "{}:{}",
                     endpoint.host().unwrap(),
                     endpoint.host().unwrap(),
                     endpoint.port().unwrap()
                     endpoint.port().unwrap()
                 ));
                 ));
-                endpoint.set_host(tor_socks5_proxy.host_str())?;
-                endpoint.set_port(tor_socks5_proxy.port())?;
-                endpoint.set_username(tor_socks5_proxy.username())?;
-                endpoint.set_password(tor_socks5_proxy.password())?;
                 endpoint.set_scheme("socks5+tls")?;
                 endpoint.set_scheme("socks5+tls")?;
+            } else if transports.contains(&"tor".to_string()) && scheme == "tcp" {
+                endpoint.set_scheme("tor")?;
+            } else if transports.contains(&"tor+tls".to_string()) && scheme == "tcp+tls" {
+                endpoint.set_scheme("tor+tls")?;
+            } else if transports.contains(&"nym".to_string()) && scheme == "tcp" {
+                endpoint.set_scheme("nym")?;
+            } else if transports.contains(&"nym+tls".to_string()) && scheme == "tcp+tls" {
+                endpoint.set_scheme("nym+tls")?;
             }
             }
         }
         }
 
 

+ 102 - 20
src/net/hosts.rs

@@ -419,8 +419,8 @@ impl HostContainer {
         &self,
         &self,
         color: HostColor,
         color: HostColor,
         transports: &[String],
         transports: &[String],
-        transport_mixing: bool,
-        tor_socks5_proxy: Url,
+        mixed_transports: &[String],
+        tor_socks5_proxy: Url
     ) -> Vec<(Url, u64)> {
     ) -> Vec<(Url, u64)> {
         trace!(target: "net::hosts::fetch_addrs()", "[START] {color:?}");
         trace!(target: "net::hosts::fetch_addrs()", "[START] {color:?}");
         let mut hosts = vec![];
         let mut hosts = vec![];
@@ -431,7 +431,9 @@ impl HostContainer {
         // However, **do not** mix tor:// and tcp+tls://, nor tor+tls:// and tcp://.
         // However, **do not** mix tor:// and tcp+tls://, nor tor+tls:// and tcp://.
         macro_rules! mix_transport {
         macro_rules! mix_transport {
             ($a:expr, $b:expr) => {
             ($a:expr, $b:expr) => {
-                if transports.contains(&$a.to_string()) && transport_mixing {
+                if transports.contains(&$a.to_string()) &&
+                    mixed_transports.contains(&$b.to_string())
+                {
                     let mut a_to_b = self.fetch_with_schemes(index, &[$b.to_string()], None);
                     let mut a_to_b = self.fetch_with_schemes(index, &[$b.to_string()], None);
                     for (addr, last_seen) in a_to_b.iter_mut() {
                     for (addr, last_seen) in a_to_b.iter_mut() {
                         addr.set_scheme($a).unwrap();
                         addr.set_scheme($a).unwrap();
@@ -443,20 +445,19 @@ impl HostContainer {
 
 
         macro_rules! mix_socks5_transport {
         macro_rules! mix_socks5_transport {
             ($a:expr, $b:expr) => {
             ($a:expr, $b:expr) => {
-                if transports.contains(&$a.to_string()) && transport_mixing {
+                if transports.contains(&$a.to_string()) &&
+                    mixed_transports.contains(&$b.to_string())
+                {
                     let mut a_to_b = self.fetch_with_schemes(index, &[$b.to_string()], None);
                     let mut a_to_b = self.fetch_with_schemes(index, &[$b.to_string()], None);
                     for (addr, last_seen) in a_to_b.iter_mut() {
                     for (addr, last_seen) in a_to_b.iter_mut() {
-                        addr.set_path(&format!(
+                        let mut endpoint = tor_socks5_proxy.clone();
+                        endpoint.set_path(&format!(
                             "{}:{}",
                             "{}:{}",
                             addr.host().unwrap(),
                             addr.host().unwrap(),
                             addr.port().unwrap()
                             addr.port().unwrap()
                         ));
                         ));
-                        addr.set_host(tor_socks5_proxy.host_str()).unwrap();
-                        addr.set_port(tor_socks5_proxy.port()).unwrap();
-                        addr.set_username(tor_socks5_proxy.username()).unwrap();
-                        addr.set_password(tor_socks5_proxy.password()).unwrap();
-                        addr.set_scheme($a).unwrap();
-                        hosts.push((addr.clone(), last_seen.clone()));
+                        endpoint.set_scheme($a).unwrap();
+                        hosts.push((endpoint, last_seen.clone()));
                     }
                     }
                 }
                 }
             };
             };
@@ -471,8 +472,13 @@ impl HostContainer {
         mix_socks5_transport!("socks5", "tor");
         mix_socks5_transport!("socks5", "tor");
         mix_socks5_transport!("socks5+tls", "tor+tls");
         mix_socks5_transport!("socks5+tls", "tor+tls");
 
 
+        // Filter out a transport from requested transport if we set it to be mixed as
+        // we don't want to connect directly to that host
+        let transports: Vec<String> =
+            transports.iter().filter(|tp| !mixed_transports.contains(tp)).cloned().collect();
+
         // And now the actual requested transports
         // And now the actual requested transports
-        for (addr, last_seen) in self.fetch_with_schemes(index, transports, None) {
+        for (addr, last_seen) in self.fetch_with_schemes(index, &transports, None) {
             hosts.push((addr, last_seen));
             hosts.push((addr, last_seen));
         }
         }
 
 
@@ -1238,7 +1244,13 @@ impl Hosts {
     /// stored in the blacklist without a port, and if so, it will return
     /// stored in the blacklist without a port, and if so, it will return
     /// true.
     /// true.
     pub(in crate::net) fn block_all_ports(&self, url: &Url) -> bool {
     pub(in crate::net) fn block_all_ports(&self, url: &Url) -> bool {
-        let host = url.host().unwrap();
+        let host = url.host();
+        if host.is_none() {
+            // the url is a unix socket or an invalid address so it won't be in hostlist
+            return false
+        }
+
+        let host = host.unwrap();
         self.container.hostlists[HostColor::Black as usize]
         self.container.hostlists[HostColor::Black as usize]
             .read()
             .read()
             .unwrap()
             .unwrap()
@@ -1385,13 +1397,8 @@ impl Hosts {
                 let day = 86400;
                 let day = 86400;
                 self.container.refresh(HostColor::Dark, day);
                 self.container.refresh(HostColor::Dark, day);
 
 
-                // If transport mixing is disabled or Socks5 transport is not allowed we will not connect to this host
-                if !settings.transport_mixing ||
-                    !settings
-                        .allowed_transports
-                        .iter()
-                        .any(|t| t == "socks5" || t == "socks5+tls")
-                {
+                // If the scheme is not found in mixed_transports we can not connect to this host
+                if !settings.mixed_transports.contains(&addr_.scheme().to_string()) {
                     continue;
                     continue;
                 }
                 }
             }
             }
@@ -1904,4 +1911,79 @@ mod tests {
         assert!(Hosts::is_i2p_host("node.dark.fi.i2p"));
         assert!(Hosts::is_i2p_host("node.dark.fi.i2p"));
         assert!(!Hosts::is_i2p_host("node.dark.fi"));
         assert!(!Hosts::is_i2p_host("node.dark.fi"));
     }
     }
+    fn test_transport_tor_mixed_with_tcp_fetch() {
+        let host_container = HostContainer::new();
+        host_container.store_or_update(
+            HostColor::Grey,
+            Url::parse("tcp://dark.fi:28880").unwrap(),
+            0,
+        );
+
+        let fetched_hosts = host_container.fetch(
+            HostColor::Grey,
+            &["tor+tls".to_string(), "tcp".to_string(), "tor".to_string()],
+            &["tcp".to_string()],
+            Url::parse("socks5://127.0.0.1:9050").unwrap(),
+        );
+
+        // test tcp endpoint is changed to tor and tcp will not be used to
+        // connect to any host directly
+        assert_eq!(fetched_hosts.len(), 1);
+        assert_eq!(fetched_hosts[0].0.to_string(), "tor://dark.fi:28880/");
+    }
+
+    #[test]
+    fn test_transport_socks5_mixed_with_tor_fetch() {
+        let host_container = HostContainer::new();
+        let addr = "eweiibe6tdjsdprb4px6rqrzzcsi22m4koia44kc5pcjr7nec2rlxyad.onion:23330";
+        host_container.store_or_update(
+            HostColor::Grey,
+            Url::parse(&format!("tor://{}", addr)).unwrap(),
+            0,
+        );
+        let socks5_proxy_url = Url::parse("socks5://127.0.0.1:9050").unwrap();
+
+        let fetched_hosts = host_container.fetch(
+            HostColor::Grey,
+            &["socks5".to_string(), "socks5+tls".to_string(), "tor".to_string()],
+            &["tor".to_string()],
+            socks5_proxy_url.clone(),
+        );
+
+        // test tor endpoint is changed to socks5 and tor will not be used to
+        // connect to any host directly
+        assert_eq!(fetched_hosts.len(), 1);
+        let mixed_url = fetched_hosts[0].0.clone();
+        assert_eq!(mixed_url.scheme(), socks5_proxy_url.scheme());
+        assert_eq!(mixed_url.host(), socks5_proxy_url.host());
+        assert_eq!(mixed_url.port(), socks5_proxy_url.port());
+        assert_eq!(mixed_url.path_segments().unwrap().next(), Some(addr));
+    }
+
+    #[test]
+    fn test_transport_tor_and_socks5_mixed_with_tcp_fetch() {
+        let host_container = HostContainer::new();
+        host_container.store_or_update(
+            HostColor::Grey,
+            Url::parse("tcp://dark.fi:28880").unwrap(),
+            0,
+        );
+
+        let fetched_hosts = host_container.fetch(
+            HostColor::Grey,
+            &[
+                "tor".to_string(),
+                "tor+tls".to_string(),
+                "socks5".to_string(),
+                "socks5+tls".to_string(),
+            ],
+            &["tcp".to_string()],
+            Url::parse("socks5://127.0.0.1:9050").unwrap(),
+        );
+
+        // test the tcp endpoint is changed to two endpoints socks5 and tor.
+        assert_eq!(fetched_hosts.len(), 2);
+        let endpoints: Vec<_> = fetched_hosts.iter().map(|item| item.0.scheme()).collect();
+        assert!(endpoints.iter().all(|&scheme| scheme == "tor" || scheme == "socks5"));
+    }
 }
 }

+ 5 - 5
src/net/session/outbound_session.rs

@@ -216,7 +216,7 @@ impl Slot {
         let gold_count = settings.gold_connect_count;
         let gold_count = settings.gold_connect_count;
 
 
         let transports = settings.allowed_transports.clone();
         let transports = settings.allowed_transports.clone();
-        let transport_mixing = settings.transport_mixing;
+        let mixed_transports = settings.mixed_transports.clone();
         let preference_strict = settings.slot_preference_strict;
         let preference_strict = settings.slot_preference_strict;
         let tor_socks5_proxy = settings.tor_socks5_proxy.clone();
         let tor_socks5_proxy = settings.tor_socks5_proxy.clone();
 
 
@@ -230,13 +230,13 @@ impl Slot {
         // If we only have grey entries, select from the greylist. Otherwise,
         // If we only have grey entries, select from the greylist. Otherwise,
         // use the preference defined in settings.
         // use the preference defined in settings.
         let addrs = if grey_only && !preference_strict {
         let addrs = if grey_only && !preference_strict {
-            container.fetch(HostColor::Grey, &transports, transport_mixing, tor_socks5_proxy)
+            container.fetch(HostColor::Grey, &transports, &mixed_transports, tor_socks5_proxy)
         } else if slot < gold_count {
         } else if slot < gold_count {
-            container.fetch(HostColor::Gold, &transports, transport_mixing, tor_socks5_proxy)
+            container.fetch(HostColor::Gold, &transports, &mixed_transports, tor_socks5_proxy)
         } else if slot < white_count {
         } else if slot < white_count {
-            container.fetch(HostColor::White, &transports, transport_mixing, tor_socks5_proxy)
+            container.fetch(HostColor::White, &transports, &mixed_transports, tor_socks5_proxy)
         } else {
         } else {
-            container.fetch(HostColor::Grey, &transports, transport_mixing, tor_socks5_proxy)
+            container.fetch(HostColor::Grey, &transports, &mixed_transports, tor_socks5_proxy)
         };
         };
 
 
         hosts.check_addrs(addrs).await
         hosts.check_addrs(addrs).await

+ 29 - 8
src/net/settings.rs

@@ -52,7 +52,7 @@ pub struct Settings {
     pub external_addrs: Vec<Url>,
     pub external_addrs: Vec<Url>,
     /// Peer nodes to manually connect to
     /// Peer nodes to manually connect to
     pub peers: Vec<Url>,
     pub peers: Vec<Url>,
-    /// Seed nodes to connect to for peer discovery and/or adversising our
+    /// Seed nodes to connect to for peer discovery and/or advertising our
     /// own external addresses
     /// own external addresses
     pub seeds: Vec<Url>,
     pub seeds: Vec<Url>,
     /// Magic bytes should be unique per P2P network.
     /// Magic bytes should be unique per P2P network.
@@ -62,8 +62,18 @@ pub struct Settings {
     pub app_version: semver::Version,
     pub app_version: semver::Version,
     /// Whitelisted network transports for outbound connections
     /// Whitelisted network transports for outbound connections
     pub allowed_transports: Vec<String>,
     pub allowed_transports: Vec<String>,
-    /// Allow transport mixing (e.g. Tor would be allowed to connect to `tcp://`)
-    pub transport_mixing: bool,
+    /// Transports allowed to be mixed (tcp, tcp+tls, tor, tor+tls)
+    /// When transport is added to this list the corresponding transport
+    /// in allowed_transports is used to connect to the node.
+    /// Supported mixing scenarios include
+    /// allowed_transport | mixed_transport
+    ///        tor        |     tcp
+    ///       tor+tls     |    tcp+tls
+    ///       socks5      |      tor
+    ///       socks5      |      tcp
+    ///      socks5+tls   |    tor+tls
+    ///      socks5+tls   |    tcp+tls
+    pub mixed_transports: Vec<String>,
     /// Tor socks5 proxy to connect to when socks5 or socks5+tls are added to allowed transports
     /// Tor socks5 proxy to connect to when socks5 or socks5+tls are added to allowed transports
     /// and transport mixing is enabled
     /// and transport mixing is enabled
     pub tor_socks5_proxy: Url,
     pub tor_socks5_proxy: Url,
@@ -128,7 +138,7 @@ impl Default for Settings {
             seeds: vec![],
             seeds: vec![],
             app_version,
             app_version,
             allowed_transports: vec!["tcp+tls".to_string()],
             allowed_transports: vec!["tcp+tls".to_string()],
-            transport_mixing: false,
+            mixed_transports: vec![],
             tor_socks5_proxy: Url::parse("socks5://127.0.0.1:9050").unwrap(),
             tor_socks5_proxy: Url::parse("socks5://127.0.0.1:9050").unwrap(),
             i2p_socks5_proxy: Url::parse("socks5://127.0.0.1:4447").unwrap(),
             i2p_socks5_proxy: Url::parse("socks5://127.0.0.1:4447").unwrap(),
             outbound_connections: 8,
             outbound_connections: 8,
@@ -228,9 +238,20 @@ pub struct SettingsOpt {
     #[structopt(long = "transports")]
     #[structopt(long = "transports")]
     pub allowed_transports: Option<Vec<String>>,
     pub allowed_transports: Option<Vec<String>>,
 
 
-    /// Allow transport mixing (e.g. Tor would be allowed to connect to `tcp://`)
-    #[structopt(long)]
-    pub transport_mixing: Option<bool>,
+    /// Transports allowed to be mixed (tcp, tcp+tls, tor, tor+tls)
+    /// When transport is added to this list the corresponding transport
+    /// in allowed_transports is used to connect to the node.
+    /// Supported mixing scenarios include
+    /// allowed_transport | mixed_transport
+    ///        tor        |     tcp
+    ///       tor+tls     |    tcp+tls
+    ///       socks5      |      tor
+    ///       socks5      |      tcp
+    ///      socks5+tls   |    tor+tls
+    ///      socks5+tls   |    tcp+tls
+    #[serde(default)]
+    #[structopt(long = "mixed-transports")]
+    pub mixed_transports: Option<Vec<String>>,
 
 
     /// Tor socks5 proxy to connect to when socks5 or socks5+tls are added to allowed transports
     /// Tor socks5 proxy to connect to when socks5 or socks5+tls are added to allowed transports
     /// and transport mixing is enabled
     /// and transport mixing is enabled
@@ -316,7 +337,7 @@ impl From<SettingsOpt> for Settings {
             seeds: opt.seeds,
             seeds: opt.seeds,
             app_version: def.app_version,
             app_version: def.app_version,
             allowed_transports: opt.allowed_transports.unwrap_or(def.allowed_transports),
             allowed_transports: opt.allowed_transports.unwrap_or(def.allowed_transports),
-            transport_mixing: opt.transport_mixing.unwrap_or(def.transport_mixing),
+            mixed_transports: opt.mixed_transports.unwrap_or(def.mixed_transports),
             tor_socks5_proxy: opt.tor_socks5_proxy.unwrap_or(def.tor_socks5_proxy),
             tor_socks5_proxy: opt.tor_socks5_proxy.unwrap_or(def.tor_socks5_proxy),
             i2p_socks5_proxy: opt.i2p_socks5_proxy.unwrap_or(def.i2p_socks5_proxy),
             i2p_socks5_proxy: opt.i2p_socks5_proxy.unwrap_or(def.i2p_socks5_proxy),
             outbound_connections: opt.outbound_connections.unwrap_or(def.outbound_connections),
             outbound_connections: opt.outbound_connections.unwrap_or(def.outbound_connections),