From 0f9a0d8f9194702a07ff0792f9c06c87b37b4bd5 Mon Sep 17 00:00:00 2001 From: Jeffrey Schiller Date: Fri, 9 Apr 2021 14:30:16 -0400 Subject: [PATCH] =?UTF-8?q?Add=20ability=20to=20configure=20=E2=80=9Cown?= =?UTF-8?q?=E2=80=9D=20addresses=20(#185)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Add ability to configure “own” addresses This configuration option permits the declaration of external or public addresses instead of attempting to learn them from port forwarding or interfaces. This is useful in situations where it isn’t possible to accurately obtain the correct external addresses that peers should use. * Update args and use better parse listen address Add the --advertise_addresses control argument to accompany the new configuration option. Also parse the listen address/port to extract the port to advertise with advertise_addresses instead of assuming it is just a port. --- src/cloud.rs | 27 +++++++++++++++++++++------ src/config.rs | 20 ++++++++++++++++++++ src/oldconfig.rs | 1 + 3 files changed, 42 insertions(+), 6 deletions(-) diff --git a/src/cloud.rs b/src/cloud.rs index 88e9c22..b12a0f7 100644 --- a/src/cloud.rs +++ b/src/cloud.rs @@ -29,7 +29,7 @@ use crate::{ AddrList, NodeInfo, PeerInfo, MESSAGE_TYPE_CLOSE, MESSAGE_TYPE_DATA, MESSAGE_TYPE_KEEPALIVE, MESSAGE_TYPE_NODE_INFO, }, - net::{mapped_addr, Socket}, + net::{mapped_addr, parse_listen, Socket}, payload::Protocol, poll::{WaitImpl, WaitResult}, port_forwarding::PortForwarding, @@ -222,11 +222,26 @@ impl GenericCloud io::Result<()> { self.own_addresses.clear(); - self.own_addresses.push(self.socket.address().map(mapped_addr)?); - if let Some(ref pfw) = self.port_forwarding { - self.own_addresses.push(pfw.get_internal_ip().into()); - self.own_addresses.push(pfw.get_external_ip().into()); - } + if self.config.advertise_addresses.len() > 0 && + !self.config.listen.starts_with("ws://") { + // Force advertised addresses based on configuration instead + // of discovery. Note: Disables port forwarding + // Because the listen config may contain a color (aka + // both address and port are specified) we parse it and + // then extract just the port. + let sockaddr = parse_listen(&self.config.listen); + let port = sockaddr.port(); + for address in &self.config.advertise_addresses { + let sockaddr = try_fail!(SocketAddr::from_str(&format!("{}:{}", address, port)), "Invalid IP Address or port {}"); + self.own_addresses.push(sockaddr); + } + } else { + self.own_addresses.push(self.socket.address().map(mapped_addr)?); + if let Some(ref pfw) = self.port_forwarding { + self.own_addresses.push(pfw.get_internal_ip().into()); + self.own_addresses.push(pfw.get_external_ip().into()); + } + } debug!("Own addresses: {:?}", self.own_addresses); // TODO: detect address changes and call event Ok(()) diff --git a/src/config.rs b/src/config.rs index 6152fe1..6c09b0a 100644 --- a/src/config.rs +++ b/src/config.rs @@ -19,6 +19,7 @@ pub struct Config { pub fix_rp_filter: bool, pub ip: Option, + pub advertise_addresses: Vec, pub ifup: Option, pub ifdown: Option, @@ -56,6 +57,7 @@ impl Default for Config { device_path: None, fix_rp_filter: false, ip: None, + advertise_addresses: vec![], ifup: None, ifdown: None, crypto: CryptoConfig::default(), @@ -105,6 +107,9 @@ impl Config { if let Some(val) = file.ip { self.ip = Some(val); } + if let Some(mut val) = file.advertise_addresses { + self.advertise_addresses.append(&mut val); + } if let Some(val) = file.ifup { self.ifup = Some(val); } @@ -212,6 +217,7 @@ impl Config { if let Some(val) = args.ifup { self.ifup = Some(val); } + self.advertise_addresses.append(&mut args.advertise_addresses); if let Some(val) = args.ifdown { self.ifdown = Some(val); } @@ -318,6 +324,7 @@ impl Config { ifup: self.ifup, ifdown: self.ifdown, ip: self.ip, + advertise_addresses: Some(self.advertise_addresses), keepalive: self.keepalive, listen: Some(self.listen), mode: Some(self.mode), @@ -467,6 +474,10 @@ pub struct Args { #[structopt(long)] pub ip: Option, + /// A list of IP Addresses to advertise as our external address(s) + #[structopt(long = "advertise_addresses", use_delimiter = true)] + pub advertise_addresses: Vec, + /// A command to setup the network interface #[structopt(long)] pub ifup: Option, @@ -606,6 +617,7 @@ pub struct ConfigFile { pub device: Option, pub ip: Option, + pub advertise_addresses: Option>, pub ifup: Option, pub ifdown: Option, @@ -638,6 +650,9 @@ device: name: vpncloud%d path: /dev/net/tun ip: 10.0.1.1/16 +advertise-addresses: + - 192.168.0.1 + - 192.168.1.1 ifup: ifconfig $IFNAME 10.0.1.1/16 mtu 1400 up ifdown: 'true' peers: @@ -673,6 +688,7 @@ statsd: fix_rp_filter: None }), ip: Some("10.0.1.1/16".to_string()), + advertise_addresses: Some(vec!["192.168.0.1".to_string(), "192.168.1.1".to_string()]), ifup: Some("ifconfig $IFNAME 10.0.1.1/16 mtu 1400 up".to_string()), ifdown: Some("true".to_string()), crypto: CryptoConfig::default(), @@ -721,6 +737,7 @@ fn config_merge() { fix_rp_filter: None, }), ip: None, + advertise_addresses: Some(vec![]), ifup: Some("ifconfig $IFNAME 10.0.1.1/16 mtu 1400 up".to_string()), ifdown: Some("true".to_string()), crypto: CryptoConfig::default(), @@ -757,6 +774,7 @@ fn config_merge() { device_name: "vpncloud%d".to_string(), device_path: None, ip: None, + advertise_addresses: vec![], ifup: Some("ifconfig $IFNAME 10.0.1.1/16 mtu 1400 up".to_string()), ifdown: Some("true".to_string()), listen: "3210".to_string(), @@ -816,6 +834,8 @@ fn config_merge() { device_path: Some("/dev/null".to_string()), fix_rp_filter: false, ip: None, + advertise_addresses: vec![], + ifup: Some("ifconfig $IFNAME 10.0.1.2/16 mtu 1400 up".to_string()), ifdown: Some("ifconfig $IFNAME down".to_string()), crypto: CryptoConfig { password: Some("anothersecret".to_string()), ..CryptoConfig::default() }, diff --git a/src/oldconfig.rs b/src/oldconfig.rs index bd9f72f..7628d5f 100644 --- a/src/oldconfig.rs +++ b/src/oldconfig.rs @@ -109,6 +109,7 @@ impl OldConfigFile { ifdown: self.ifdown, ifup: self.ifup, ip: None, + advertise_addresses: None, keepalive: self.keepalive, listen: self.listen.or(self.port.map(|p| format!("{}", p))), mode: self.mode,