hosts.rs 8.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267
  1. /* This file is part of DarkFi (https://dark.fi)
  2. *
  3. * Copyright (C) 2020-2023 Dyne.org foundation
  4. *
  5. * This program is free software: you can redistribute it and/or modify
  6. * it under the terms of the GNU Affero General Public License as
  7. * published by the Free Software Foundation, either version 3 of the
  8. * License, or (at your option) any later version.
  9. *
  10. * This program is distributed in the hope that it will be useful,
  11. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. * GNU Affero General Public License for more details.
  14. *
  15. * You should have received a copy of the GNU Affero General Public License
  16. * along with this program. If not, see <https://www.gnu.org/licenses/>.
  17. */
  18. use std::collections::HashSet;
  19. use async_std::sync::{Arc, RwLock};
  20. use log::debug;
  21. use rand::{prelude::IteratorRandom, rngs::OsRng};
  22. use url::Url;
  23. use super::settings::SettingsPtr;
  24. /// Atomic pointer to hosts object
  25. pub type HostsPtr = Arc<Hosts>;
  26. /// Manages a store of network addresses
  27. pub struct Hosts {
  28. /// Set of stored addresses
  29. addrs: RwLock<HashSet<Url>>,
  30. /// Pointer to configured P2P settings
  31. settings: SettingsPtr,
  32. }
  33. impl Hosts {
  34. /// Create a new hosts list. Also initializes private IP ranges used
  35. /// for filtering.
  36. pub fn new(settings: SettingsPtr) -> HostsPtr {
  37. Arc::new(Self { addrs: RwLock::new(HashSet::new()), settings })
  38. }
  39. /// Append given addrs to the known set. Filtering should be done externally.
  40. pub async fn store(&self, addrs: &[Url]) {
  41. debug!(target: "net::hosts::store()", "hosts::store() [START]");
  42. let filtered_addrs = self.filter_addresses(addrs).await;
  43. if !filtered_addrs.is_empty() {
  44. let mut addrs_map = self.addrs.write().await;
  45. for addr in filtered_addrs {
  46. debug!(target: "net::hosts::store()", "Inserting {}", addr);
  47. addrs_map.insert(addr);
  48. }
  49. }
  50. debug!(target: "net::hosts::store()", "hosts::store() [END]");
  51. }
  52. /// Filter given addresses based on certain rulesets and validity.
  53. async fn filter_addresses(&self, addrs: &[Url]) -> Vec<Url> {
  54. let mut ret = vec![];
  55. let localnet = self.settings.localnet;
  56. for _addr in addrs {
  57. // Validate that the format is `scheme://host_str:port`
  58. if _addr.host_str().is_none() ||
  59. _addr.port().is_none() ||
  60. _addr.cannot_be_a_base() ||
  61. _addr.path_segments().is_some()
  62. {
  63. continue
  64. }
  65. let host_str = _addr.host_str().unwrap();
  66. if !localnet {
  67. // Our own addresses should never enter the hosts set.
  68. let mut got_own = false;
  69. for ext in &self.settings.external_addrs {
  70. if host_str == ext.host_str().unwrap() {
  71. got_own = true;
  72. break
  73. }
  74. }
  75. if got_own {
  76. continue
  77. }
  78. }
  79. // We do this hack in order to parse IPs properly.
  80. // https://github.com/whatwg/url/issues/749
  81. let addr = Url::parse(&_addr.as_str().replace(_addr.scheme(), "http")).unwrap();
  82. // Filter non-global ranges if we're not allowing localnet.
  83. // Should never be allowed in production, so we don't really care
  84. // about some of them (e.g. 0.0.0.0, or broadcast, etc.).
  85. if !localnet {
  86. // Filter private IP ranges
  87. match addr.host().unwrap() {
  88. url::Host::Ipv4(ip) => {
  89. if !ip.is_global() {
  90. continue
  91. }
  92. }
  93. url::Host::Ipv6(ip) => {
  94. if !ip.is_global() {
  95. continue
  96. }
  97. }
  98. url::Host::Domain(d) => {
  99. // TODO: This could perhaps be more exhaustive?
  100. if d == "localhost" {
  101. continue
  102. }
  103. }
  104. }
  105. }
  106. match _addr.scheme() {
  107. // Validate that the address is an actual onion.
  108. #[cfg(feature = "p2p-transport-tor")]
  109. "tor" | "tor+tls" => {
  110. use std::str::FromStr;
  111. if tor_hscrypto::pk::HsId::from_str(host_str).is_err() {
  112. continue
  113. }
  114. }
  115. #[cfg(feature = "p2p-transport-nym")]
  116. "nym" | "nym+tls" => continue, // <-- Temp skip
  117. #[cfg(feature = "p2p-transport-tcp")]
  118. "tcp" | "tcp+tls" => {}
  119. _ => continue,
  120. }
  121. ret.push(_addr.clone());
  122. }
  123. ret
  124. }
  125. pub async fn remove(&self, url: &Url) -> bool {
  126. self.addrs.write().await.remove(url)
  127. }
  128. /// Check if the host list is empty.
  129. pub async fn is_empty(&self) -> bool {
  130. self.addrs.read().await.is_empty()
  131. }
  132. /// Check if host is already in the set
  133. pub async fn contains(&self, addr: &Url) -> bool {
  134. self.addrs.read().await.contains(addr)
  135. }
  136. /// Return all known hosts
  137. pub async fn load_all(&self) -> Vec<Url> {
  138. self.addrs.read().await.iter().cloned().collect()
  139. }
  140. /// Get up to n random hosts from the hosts set.
  141. pub async fn get_n_random(&self, n: u32) -> Vec<Url> {
  142. let n = n as usize;
  143. let addrs = self.addrs.read().await;
  144. let urls = addrs.iter().choose_multiple(&mut OsRng, n.min(addrs.len()));
  145. let urls = urls.iter().map(|&url| url.clone()).collect();
  146. urls
  147. }
  148. /// Get all peers that match the given transport schemes from the hosts set.
  149. pub async fn load_with_schemes(&self, schemes: &[String]) -> Vec<Url> {
  150. let mut ret = vec![];
  151. for addr in self.addrs.read().await.iter() {
  152. if schemes.contains(&addr.scheme().to_string()) {
  153. ret.push(addr.clone());
  154. }
  155. }
  156. ret
  157. }
  158. }
  159. #[cfg(test)]
  160. mod tests {
  161. use super::{super::settings::Settings, *};
  162. #[async_std::test]
  163. async fn test_store_localnet() {
  164. let mut settings = Settings::default();
  165. settings.localnet = true;
  166. settings.external_addrs = vec![
  167. Url::parse("tcp://foo.bar:123").unwrap(),
  168. Url::parse("tcp://lol.cat:321").unwrap(),
  169. ];
  170. let hosts = Hosts::new(Arc::new(settings.clone()));
  171. hosts.store(&settings.external_addrs).await;
  172. for i in settings.external_addrs {
  173. assert!(hosts.contains(&i).await);
  174. }
  175. let local_hosts = vec![
  176. Url::parse("tcp://localhost:3921").unwrap(),
  177. Url::parse("tcp://127.0.0.1:23957").unwrap(),
  178. Url::parse("tcp://[::1]:21481").unwrap(),
  179. Url::parse("tcp://192.168.10.65:311").unwrap(),
  180. Url::parse("tcp://0.0.0.0:2312").unwrap(),
  181. Url::parse("tcp://255.255.255.255:2131").unwrap(),
  182. ];
  183. hosts.store(&local_hosts).await;
  184. for i in local_hosts {
  185. assert!(hosts.contains(&i).await);
  186. }
  187. let remote_hosts = vec![
  188. Url::parse("tcp://dark.fi:80").unwrap(),
  189. Url::parse("tcp://top.kek:111").unwrap(),
  190. Url::parse("tcp://http.cat:401").unwrap(),
  191. ];
  192. hosts.store(&remote_hosts).await;
  193. for i in remote_hosts {
  194. assert!(hosts.contains(&i).await);
  195. }
  196. }
  197. #[async_std::test]
  198. async fn test_store() {
  199. let mut settings = Settings::default();
  200. settings.localnet = false;
  201. settings.external_addrs = vec![
  202. Url::parse("tcp://foo.bar:123").unwrap(),
  203. Url::parse("tcp://lol.cat:321").unwrap(),
  204. ];
  205. let hosts = Hosts::new(Arc::new(settings.clone()));
  206. hosts.store(&settings.external_addrs).await;
  207. assert!(hosts.is_empty().await);
  208. let local_hosts = vec![
  209. Url::parse("tcp://localhost:3921").unwrap(),
  210. Url::parse("tcp://127.0.0.1:23957").unwrap(),
  211. Url::parse("tor://[::1]:21481").unwrap(),
  212. Url::parse("tcp://192.168.10.65:311").unwrap(),
  213. Url::parse("tcp+tls://0.0.0.0:2312").unwrap(),
  214. Url::parse("tcp://255.255.255.255:2131").unwrap(),
  215. ];
  216. hosts.store(&local_hosts).await;
  217. assert!(hosts.is_empty().await);
  218. let remote_hosts = vec![
  219. Url::parse("tcp://dark.fi:80").unwrap(),
  220. Url::parse("tcp://http.cat:401").unwrap(),
  221. Url::parse("tcp://foo.bar:111").unwrap(),
  222. ];
  223. hosts.store(&remote_hosts).await;
  224. assert!(hosts.contains(&remote_hosts[0]).await);
  225. assert!(hosts.contains(&remote_hosts[1]).await);
  226. assert!(!hosts.contains(&remote_hosts[2]).await);
  227. }
  228. }