settings.rs
1 /* This file is part of DarkFi (https://dark.fi) 2 * 3 * Copyright (C) 2020-2025 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 19 use structopt::StructOpt; 20 use url::Url; 21 22 type BlacklistEntry = (String, Vec<String>, Vec<u16>); 23 24 /// Ban policies definitions. 25 /// 26 /// If the ban policy is set to `Relaxed` will not ban peers in case 27 /// they send a message without a corresponding MessageDispatcher. 28 /// This is useful for nodes that may not be subscribed to protocols, 29 /// such as Lilith. For most uses this should be set to `Strict`. 30 /// 31 /// TODO: this will be deprecated when we introduce the p2p resource 32 /// mananger. 33 #[derive(Clone, Debug, Default, PartialEq, serde::Deserialize, serde::Serialize)] 34 #[serde(rename_all = "lowercase")] 35 pub enum BanPolicy { 36 #[default] 37 Strict, 38 39 Relaxed, 40 } 41 42 /// P2P network settings. The scope of this is a P2P network instance 43 /// configured by the library user. 44 #[derive(Debug, Clone)] 45 pub struct Settings { 46 /// Only used for debugging, compromises privacy when set 47 pub node_id: String, 48 /// P2P accept addresses the instance listens on for inbound connections 49 pub inbound_addrs: Vec<Url>, 50 /// P2P external addresses the instance advertises so other peers can 51 /// reach us and connect to us, as long as inbound addrs are configured 52 pub external_addrs: Vec<Url>, 53 /// Peer nodes to manually connect to 54 pub peers: Vec<Url>, 55 /// Seed nodes to connect to for peer discovery and/or advertising our 56 /// own external addresses 57 pub seeds: Vec<Url>, 58 /// Magic bytes should be unique per P2P network. 59 /// Avoid bleeding of networks. 60 pub magic_bytes: MagicBytes, 61 /// Application version, used for convenient protocol matching 62 pub app_version: semver::Version, 63 /// Whitelisted network transports for outbound connections 64 pub allowed_transports: Vec<String>, 65 /// Transports allowed to be mixed (tcp, tcp+tls, tor, tor+tls) 66 /// When transport is added to this list the corresponding transport 67 /// in allowed_transports is used to connect to the node. 68 /// Supported mixing scenarios include 69 /// allowed_transport | mixed_transport 70 /// tor | tcp 71 /// tor+tls | tcp+tls 72 /// socks5 | tor 73 /// socks5 | tcp 74 /// socks5+tls | tor+tls 75 /// socks5+tls | tcp+tls 76 pub mixed_transports: Vec<String>, 77 /// Tor socks5 proxy to connect to when socks5 or socks5+tls are added to allowed transports 78 /// and transport mixing is enabled 79 pub tor_socks5_proxy: Option<Url>, 80 /// Nym socks5 proxy to connect to when socks5 or socks5+tls are added to allowed transports 81 /// and transport mixing is enabled 82 pub nym_socks5_proxy: Option<Url>, 83 /// I2p Socks5 proxy to connect to i2p eepsite (hidden services) 84 pub i2p_socks5_proxy: Url, 85 /// Outbound connection slots number, this many connections will be 86 /// attempted. (This does not include manual connections) 87 pub outbound_connections: usize, 88 /// Inbound connection slots number, this many active listening connections 89 /// will be allowed. (This does not include manual connections) 90 pub inbound_connections: usize, 91 /// Outbound connection timeout (in seconds) 92 pub outbound_connect_timeout: u64, 93 /// Exchange versions (handshake) timeout (in seconds) 94 pub channel_handshake_timeout: u64, 95 /// Ping-pong exchange execution interval (in seconds) 96 pub channel_heartbeat_interval: u64, 97 /// Allow localnet hosts 98 pub localnet: bool, 99 /// Cooling off time for peer discovery when unsuccessful 100 pub outbound_peer_discovery_cooloff_time: u64, 101 /// Time between peer discovery attempts 102 pub outbound_peer_discovery_attempt_time: u64, 103 /// Maximum number of addresses (with preferred transports) to receive from 104 /// seeds and peers. 105 /// If undefined, `outbound_connections` will be used instead. 106 pub getaddrs_max: Option<u32>, 107 /// P2P datastore path 108 pub p2p_datastore: Option<String>, 109 /// Hostlist storage path 110 pub hostlist: Option<String>, 111 /// Pause interval within greylist refinery process 112 pub greylist_refinery_interval: u64, 113 /// Percent of connections to come from the whitelist 114 pub white_connect_percent: usize, 115 /// Number of goldlist connections 116 pub gold_connect_count: usize, 117 /// If this is true, strictly follow the gold_connect_count and 118 /// white_connect_percent settings. Otherwise, connect to greylist 119 /// entries if we have no white or gold connections. 120 pub slot_preference_strict: bool, 121 /// Number of seconds with no connections after which refinery 122 /// process is paused. 123 pub time_with_no_connections: u64, 124 /// Nodes to avoid interacting with for the duration of the program, 125 /// in the format ["host", ["scheme", "scheme"], [port, port]] 126 /// If scheme is left empty it will default to "tcp+tls". 127 /// If ports are left empty all ports from this peer will be blocked. 128 pub blacklist: Vec<BlacklistEntry>, 129 /// Do not ban nodes that send messages without dispatchers if set 130 /// to `Relaxed`. For most uses, should be set to `Strict`. 131 pub ban_policy: BanPolicy, 132 } 133 134 impl Default for Settings { 135 fn default() -> Self { 136 let version = option_env!("CARGO_PKG_VERSION").unwrap_or("0.0.0"); 137 let app_version = semver::Version::parse(version).unwrap(); 138 139 Self { 140 node_id: String::new(), 141 inbound_addrs: vec![], 142 external_addrs: vec![], 143 magic_bytes: Default::default(), 144 peers: vec![], 145 seeds: vec![], 146 app_version, 147 allowed_transports: vec!["tcp+tls".to_string()], 148 mixed_transports: vec![], 149 tor_socks5_proxy: None, 150 nym_socks5_proxy: None, 151 i2p_socks5_proxy: Url::parse("socks5://127.0.0.1:4447").unwrap(), 152 outbound_connections: 8, 153 inbound_connections: 8, 154 outbound_connect_timeout: 15, 155 channel_handshake_timeout: 10, 156 channel_heartbeat_interval: 30, 157 localnet: false, 158 outbound_peer_discovery_cooloff_time: 30, 159 outbound_peer_discovery_attempt_time: 5, 160 getaddrs_max: None, 161 p2p_datastore: None, 162 hostlist: None, 163 greylist_refinery_interval: 15, 164 white_connect_percent: 70, 165 gold_connect_count: 2, 166 slot_preference_strict: false, 167 time_with_no_connections: 30, 168 blacklist: vec![], 169 ban_policy: BanPolicy::Strict, 170 } 171 } 172 } 173 174 // The following is used so we can have P2P settings configurable 175 // from TOML files. 176 177 /// Distinguishes distinct P2P networks 178 #[derive(serde::Deserialize, Debug, Clone)] 179 pub struct MagicBytes(pub [u8; 4]); 180 181 impl Default for MagicBytes { 182 fn default() -> Self { 183 Self([0xd9, 0xef, 0xb6, 0x7d]) 184 } 185 } 186 187 /// Defines the network settings. 188 #[derive(Clone, Debug, serde::Deserialize, structopt::StructOpt, structopt_toml::StructOptToml)] 189 #[structopt()] 190 pub struct SettingsOpt { 191 /// P2P accept address node listens to for inbound connections 192 #[serde(default)] 193 #[structopt(long = "accept")] 194 pub inbound: Vec<Url>, 195 196 /// Outbound connection slots number 197 #[structopt(long = "outbound-slots")] 198 pub outbound_connections: Option<usize>, 199 200 /// Inbound connection slots number 201 #[structopt(long = "inbound-slots")] 202 pub inbound_connections: Option<usize>, 203 204 #[serde(default)] 205 #[structopt(skip)] 206 /// Magic bytes used to distinguish P2P distinct networks and 207 /// avoid nodes bleeding due to user config error. 208 pub magic_bytes: MagicBytes, 209 210 /// P2P external addresses node advertises so other peers can 211 /// reach us and connect to us, as long as inbound addresses 212 /// are also configured 213 #[serde(default)] 214 #[structopt(long)] 215 pub external_addrs: Vec<Url>, 216 217 /// Peer nodes to manually connect to 218 #[serde(default)] 219 #[structopt(long)] 220 pub peers: Vec<Url>, 221 222 /// Seed nodes to connect to for peers retrieval and/or 223 /// advertising our own external addresses 224 #[serde(default)] 225 #[structopt(long)] 226 pub seeds: Vec<Url>, 227 228 /// Connection establishment timeout in seconds 229 #[structopt(skip)] 230 pub outbound_connect_timeout: Option<u64>, 231 232 /// Exchange versions (handshake) timeout in seconds 233 #[structopt(skip)] 234 pub channel_handshake_timeout: Option<u64>, 235 236 /// Ping-pong exchange execution interval in seconds 237 #[structopt(skip)] 238 pub channel_heartbeat_interval: Option<u64>, 239 240 /// Only used for debugging. Compromises privacy when set. 241 #[serde(default)] 242 #[structopt(skip)] 243 pub node_id: String, 244 245 /// Preferred transports for outbound connections 246 #[serde(default)] 247 #[structopt(long = "transports")] 248 pub allowed_transports: Option<Vec<String>>, 249 250 /// Transports allowed to be mixed (tcp, tcp+tls, tor, tor+tls) 251 /// When transport is added to this list the corresponding transport 252 /// in allowed_transports is used to connect to the node. 253 /// Supported mixing scenarios include 254 /// allowed_transport | mixed_transport 255 /// tor | tcp 256 /// tor+tls | tcp+tls 257 /// socks5 | tor 258 /// socks5 | tcp 259 /// socks5+tls | tor+tls 260 /// socks5+tls | tcp+tls 261 #[serde(default)] 262 #[structopt(long = "mixed-transports")] 263 pub mixed_transports: Option<Vec<String>>, 264 265 /// Tor socks5 proxy to connect to when socks5 or socks5+tls are added to allowed transports 266 /// and transport mixing is enabled 267 #[structopt(long)] 268 pub tor_socks5_proxy: Option<Url>, 269 270 /// Nym socks5 proxy to connect to when socks5 or socks5+tls are added to allowed transports 271 /// and transport mixing is enabled 272 #[structopt(long)] 273 pub nym_socks5_proxy: Option<Url>, 274 275 /// I2p Socks5 proxy to connect to i2p eepsite (hidden services) 276 #[structopt(long)] 277 pub i2p_socks5_proxy: Option<Url>, 278 279 /// If this is true, strictly follow the gold_connect_count and 280 /// white_connect_percent settings. Otherwise, connect to greylist 281 /// entries if we have no white or gold connections. 282 #[serde(default)] 283 #[structopt(long)] 284 pub localnet: bool, 285 286 /// Cooling off time for peer discovery when unsuccessful 287 #[structopt(skip)] 288 pub outbound_peer_discovery_cooloff_time: Option<u64>, 289 290 /// Time between peer discovery attempts 291 #[structopt(skip)] 292 pub outbound_peer_discovery_attempt_time: Option<u64>, 293 294 /// Maximum number of addresses (with preferred transports) to receive from 295 /// seeds and peers. 296 /// If undefined, `outbound_connections` will be used instead. 297 #[structopt(skip)] 298 pub getaddrs_max: Option<u32>, 299 300 /// P2P datastore path 301 #[serde(default)] 302 #[structopt(long)] 303 pub p2p_datastore: Option<String>, 304 305 /// Hosts .tsv file to use 306 #[serde(default)] 307 #[structopt(long)] 308 pub hostlist: Option<String>, 309 310 /// Pause interval within greylist refinery process 311 #[structopt(skip)] 312 pub greylist_refinery_interval: Option<u64>, 313 314 /// Number of whitelist connections 315 #[structopt(skip)] 316 pub white_connect_percent: Option<usize>, 317 318 /// Number of goldlist connections 319 #[structopt(skip)] 320 pub gold_connect_count: Option<usize>, 321 322 /// Allow localnet hosts 323 #[serde(default)] 324 #[structopt(long)] 325 pub slot_preference_strict: bool, 326 327 /// Number of seconds with no connections after which refinery 328 /// process is paused. 329 #[structopt(skip)] 330 pub time_with_no_connections: Option<u64>, 331 332 /// Nodes to avoid interacting with for the duration of the program, 333 /// in the format ["host", ["scheme", "scheme"], [port, port]] 334 /// If scheme is left empty it will default to "tcp+tls". 335 /// If ports are left empty all ports from this peer will be blocked. 336 #[serde(default)] 337 #[structopt(skip)] 338 pub blacklist: Vec<BlacklistEntry>, 339 340 /// Do not ban nodes that send messages without dispatchers if set 341 /// to `Relaxed`. For most uses, should be set to `Strict`. 342 #[serde(default)] 343 #[structopt(skip)] 344 pub ban_policy: BanPolicy, 345 } 346 347 impl From<SettingsOpt> for Settings { 348 fn from(opt: SettingsOpt) -> Self { 349 let def = Settings::default(); 350 351 Self { 352 node_id: opt.node_id, 353 inbound_addrs: opt.inbound, 354 external_addrs: opt.external_addrs, 355 magic_bytes: opt.magic_bytes, 356 peers: opt.peers, 357 seeds: opt.seeds, 358 app_version: def.app_version, 359 allowed_transports: opt.allowed_transports.unwrap_or(def.allowed_transports), 360 mixed_transports: opt.mixed_transports.unwrap_or(def.mixed_transports), 361 tor_socks5_proxy: opt.tor_socks5_proxy, 362 nym_socks5_proxy: opt.nym_socks5_proxy, 363 i2p_socks5_proxy: opt.i2p_socks5_proxy.unwrap_or(def.i2p_socks5_proxy), 364 outbound_connections: opt.outbound_connections.unwrap_or(def.outbound_connections), 365 inbound_connections: opt.inbound_connections.unwrap_or(def.inbound_connections), 366 outbound_connect_timeout: opt 367 .outbound_connect_timeout 368 .unwrap_or(def.outbound_connect_timeout), 369 channel_handshake_timeout: opt 370 .channel_handshake_timeout 371 .unwrap_or(def.channel_handshake_timeout), 372 channel_heartbeat_interval: opt 373 .channel_heartbeat_interval 374 .unwrap_or(def.channel_heartbeat_interval), 375 localnet: opt.localnet, 376 outbound_peer_discovery_cooloff_time: opt 377 .outbound_peer_discovery_cooloff_time 378 .unwrap_or(def.outbound_peer_discovery_cooloff_time), 379 outbound_peer_discovery_attempt_time: opt 380 .outbound_peer_discovery_attempt_time 381 .unwrap_or(def.outbound_peer_discovery_attempt_time), 382 getaddrs_max: opt.getaddrs_max, 383 p2p_datastore: opt.p2p_datastore, 384 hostlist: opt.hostlist, 385 greylist_refinery_interval: opt 386 .greylist_refinery_interval 387 .unwrap_or(def.greylist_refinery_interval), 388 white_connect_percent: opt.white_connect_percent.unwrap_or(def.white_connect_percent), 389 gold_connect_count: opt.gold_connect_count.unwrap_or(def.gold_connect_count), 390 slot_preference_strict: opt.slot_preference_strict, 391 time_with_no_connections: opt 392 .time_with_no_connections 393 .unwrap_or(def.time_with_no_connections), 394 blacklist: opt.blacklist, 395 ban_policy: opt.ban_policy, 396 } 397 } 398 }