diff --git a/src/config/defaults.rs b/src/config/defaults.rs index 09d146a..f02403e 100644 --- a/src/config/defaults.rs +++ b/src/config/defaults.rs @@ -185,6 +185,10 @@ pub(crate) fn default_proxy_protocol_header_timeout_ms() -> u64 { 500 } +pub(crate) fn default_proxy_protocol_trusted_cidrs() -> Vec { + vec!["0.0.0.0/0".parse().unwrap(), "::/0".parse().unwrap()] +} + pub(crate) fn default_server_max_connections() -> u32 { 10_000 } diff --git a/src/config/load.rs b/src/config/load.rs index 8f12757..2a501ea 100644 --- a/src/config/load.rs +++ b/src/config/load.rs @@ -1263,6 +1263,10 @@ mod tests { assert_eq!(cfg.general.update_every, default_update_every()); assert_eq!(cfg.server.listen_addr_ipv4, default_listen_addr_ipv4()); assert_eq!(cfg.server.listen_addr_ipv6, default_listen_addr_ipv6_opt()); + assert_eq!( + cfg.server.proxy_protocol_trusted_cidrs, + default_proxy_protocol_trusted_cidrs() + ); assert_eq!(cfg.server.api.listen, default_api_listen()); assert_eq!(cfg.server.api.whitelist, default_api_whitelist()); assert_eq!( @@ -1395,6 +1399,10 @@ mod tests { let server = ServerConfig::default(); assert_eq!(server.listen_addr_ipv6, Some(default_listen_addr_ipv6())); + assert_eq!( + server.proxy_protocol_trusted_cidrs, + default_proxy_protocol_trusted_cidrs() + ); assert_eq!(server.api.listen, default_api_listen()); assert_eq!(server.api.whitelist, default_api_whitelist()); assert_eq!( @@ -1430,6 +1438,41 @@ mod tests { assert_eq!(access.users, default_access_users()); } + #[test] + fn proxy_protocol_trusted_cidrs_missing_uses_trust_all_but_explicit_empty_stays_empty() { + let cfg_missing: ProxyConfig = toml::from_str( + r#" + [server] + [general] + [network] + [access] + "#, + ) + .unwrap(); + assert_eq!( + cfg_missing.server.proxy_protocol_trusted_cidrs, + default_proxy_protocol_trusted_cidrs() + ); + + let cfg_explicit_empty: ProxyConfig = toml::from_str( + r#" + [server] + proxy_protocol_trusted_cidrs = [] + + [general] + [network] + [access] + "#, + ) + .unwrap(); + assert!( + cfg_explicit_empty + .server + .proxy_protocol_trusted_cidrs + .is_empty() + ); + } + #[test] fn dc_overrides_allow_string_and_array() { let toml = r#" diff --git a/src/config/types.rs b/src/config/types.rs index 240d2f1..2d204e2 100644 --- a/src/config/types.rs +++ b/src/config/types.rs @@ -1240,9 +1240,10 @@ pub struct ServerConfig { /// Trusted source CIDRs allowed to send incoming PROXY protocol headers. /// - /// When non-empty, connections from addresses outside this allowlist are - /// rejected before `src_addr` is applied. - #[serde(default)] + /// If this field is omitted in config, it defaults to trust-all CIDRs + /// (`0.0.0.0/0` and `::/0`). If it is explicitly set to an empty list, + /// all PROXY protocol headers are rejected. + #[serde(default = "default_proxy_protocol_trusted_cidrs")] pub proxy_protocol_trusted_cidrs: Vec, /// Port for the Prometheus-compatible metrics endpoint. @@ -1287,7 +1288,7 @@ impl Default for ServerConfig { listen_tcp: None, proxy_protocol: false, proxy_protocol_header_timeout_ms: default_proxy_protocol_header_timeout_ms(), - proxy_protocol_trusted_cidrs: Vec::new(), + proxy_protocol_trusted_cidrs: default_proxy_protocol_trusted_cidrs(), metrics_port: None, metrics_listen: None, metrics_whitelist: default_metrics_whitelist(), diff --git a/src/proxy/client.rs b/src/proxy/client.rs index 0190e8e..0becac7 100644 --- a/src/proxy/client.rs +++ b/src/proxy/client.rs @@ -323,7 +323,7 @@ fn is_trusted_proxy_source(peer_ip: IpAddr, trusted: &[IpNetwork]) -> bool { let warned = EMPTY_PROXY_TRUST_WARNED.get_or_init(|| AtomicBool::new(false)); if !warned.swap(true, Ordering::Relaxed) { warn!( - "PROXY protocol enabled but server.proxy_protocol_trusted_cidrs is empty; rejecting all PROXY headers by default" + "PROXY protocol enabled but server.proxy_protocol_trusted_cidrs is empty; rejecting all PROXY headers" ); } return false;