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,