diff --git a/src/core/config/check.rs b/src/core/config/check.rs index a631c4f8dec4b8457d27ad2ee1497bcc9be8c8e1..403aa27c746daeac7664ab04c9a19a8d4b1a3b6f 100644 --- a/src/core/config/check.rs +++ b/src/core/config/check.rs @@ -27,46 +27,43 @@ pub fn check(config: &Config) -> Result<(), Error> { )); } - if config.address.is_loopback() && cfg!(unix) { - debug!( - "Found loopback listening address {}, running checks if we're in a container.", - config.address - ); - - #[cfg(unix)] - if Path::new("/proc/vz").exists() /* Guest */ && !Path::new("/proc/bz").exists() - /* Host */ - { - error!( - "You are detected using OpenVZ with a loopback/localhost listening address of {}. If you are using \ - OpenVZ for containers and you use NAT-based networking to communicate with the host and guest, this \ - will NOT work. Please change this to \"0.0.0.0\". If this is expected, you can ignore.", - config.address - ); - } - - #[cfg(unix)] - if Path::new("/.dockerenv").exists() { - error!( - "You are detected using Docker with a loopback/localhost listening address of {}. If you are using a \ - reverse proxy on the host and require communication to conduwuit in the Docker container via \ - NAT-based networking, this will NOT work. Please change this to \"0.0.0.0\". If this is expected, \ - you can ignore.", - config.address - ); + config.get_bind_addrs().iter().for_each(|addr| { + if addr.ip().is_loopback() && cfg!(unix) { + debug!("Found loopback listening address {addr}, running checks if we're in a container.",); + + #[cfg(unix)] + if Path::new("/proc/vz").exists() /* Guest */ && !Path::new("/proc/bz").exists() + /* Host */ + { + error!( + "You are detected using OpenVZ with a loopback/localhost listening address of {addr}. If you are \ + using OpenVZ for containers and you use NAT-based networking to communicate with the host and \ + guest, this will NOT work. Please change this to \"0.0.0.0\". If this is expected, you can \ + ignore.", + ); + } + + #[cfg(unix)] + if Path::new("/.dockerenv").exists() { + error!( + "You are detected using Docker with a loopback/localhost listening address of {addr}. If you are \ + using a reverse proxy on the host and require communication to conduwuit in the Docker container \ + via NAT-based networking, this will NOT work. Please change this to \"0.0.0.0\". If this is \ + expected, you can ignore.", + ); + } + + #[cfg(unix)] + if Path::new("/run/.containerenv").exists() { + error!( + "You are detected using Podman with a loopback/localhost listening address of {addr}. If you are \ + using a reverse proxy on the host and require communication to conduwuit in the Podman container \ + via NAT-based networking, this will NOT work. Please change this to \"0.0.0.0\". If this is \ + expected, you can ignore.", + ); + } } - - #[cfg(unix)] - if Path::new("/run/.containerenv").exists() { - error!( - "You are detected using Podman with a loopback/localhost listening address of {}. If you are using a \ - reverse proxy on the host and require communication to conduwuit in the Podman container via \ - NAT-based networking, this will NOT work. Please change this to \"0.0.0.0\". If this is expected, \ - you can ignore.", - config.address - ); - } - } + }); // rocksdb does not allow max_log_files to be 0 if config.rocksdb_max_log_files == 0 && cfg!(feature = "rocksdb") { diff --git a/src/core/config/mod.rs b/src/core/config/mod.rs index bb13923beb37369a8ec84a317c573de5c2357933..67b8397505f9705ead01383ec1fe18e3d174d5b2 100644 --- a/src/core/config/mod.rs +++ b/src/core/config/mod.rs @@ -1,7 +1,7 @@ use std::{ collections::BTreeMap, fmt::{self, Write as _}, - net::{IpAddr, Ipv6Addr, SocketAddr}, + net::{IpAddr, Ipv4Addr, Ipv6Addr, SocketAddr}, path::PathBuf, }; @@ -36,13 +36,20 @@ struct ListeningPort { ports: Either<u16, Vec<u16>>, } +#[derive(Deserialize, Clone, Debug)] +#[serde(transparent)] +struct ListeningAddr { + #[serde(with = "either::serde_untagged")] + addrs: Either<IpAddr, Vec<IpAddr>>, +} + /// all the config options for conduwuit #[derive(Clone, Debug, Deserialize)] #[allow(clippy::struct_excessive_bools)] pub struct Config { /// [`IpAddr`] conduwuit will listen on (can be IPv4 or IPv6) #[serde(default = "default_address")] - pub address: IpAddr, + address: ListeningAddr, /// default TCP port(s) conduwuit will listen on #[serde(default = "default_port")] port: ListeningPort, @@ -471,22 +478,27 @@ fn is_dual_listening(raw_config: &Figment) -> bool { #[must_use] pub fn get_bind_addrs(&self) -> Vec<SocketAddr> { + let mut addrs = Vec::new(); + for host in &self.get_bind_hosts() { + for port in &self.get_bind_ports() { + addrs.push(SocketAddr::new(*host, *port)); + } + } + + addrs + } + + fn get_bind_hosts(&self) -> Vec<IpAddr> { + match &self.address.addrs { + Left(addr) => vec![*addr], + Right(addrs) => addrs.clone(), + } + } + + fn get_bind_ports(&self) -> Vec<u16> { match &self.port.ports { - Left(port) => { - // Left is only 1 value, so make a vec with 1 value only - let port_vec = [port]; - - port_vec - .iter() - .copied() - .map(|port| SocketAddr::from((self.address, *port))) - .collect::<Vec<_>>() - }, - Right(ports) => ports - .iter() - .copied() - .map(|port| SocketAddr::from((self.address, port))) - .collect::<Vec<_>>(), + Left(port) => vec![*port], + Right(ports) => ports.clone(), } } @@ -875,7 +887,11 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { fn true_fn() -> bool { true } -fn default_address() -> IpAddr { Ipv6Addr::LOCALHOST.into() } +fn default_address() -> ListeningAddr { + ListeningAddr { + addrs: Right(vec![Ipv4Addr::LOCALHOST.into(), Ipv6Addr::LOCALHOST.into()]), + } +} fn default_port() -> ListeningPort { ListeningPort {