diff --git a/Cargo.toml b/Cargo.toml index 5fce860..3488cc7 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -53,6 +53,7 @@ anyhow = "1.0" # HTTP reqwest = { version = "0.12", features = ["rustls-tls"], default-features = false } notify = { version = "6", features = ["macos_fsevent"] } +ipnetwork = "0.20" hyper = { version = "1", features = ["server", "http1"] } hyper-util = { version = "0.1", features = ["tokio", "server-auto"] } http-body-util = "0.1" diff --git a/src/config/defaults.rs b/src/config/defaults.rs index a022021..f9d878a 100644 --- a/src/config/defaults.rs +++ b/src/config/defaults.rs @@ -1,5 +1,6 @@ use std::net::IpAddr; use std::collections::HashMap; +use ipnetwork::IpNetwork; use serde::Deserialize; // Helper defaults kept private to the config module. @@ -66,8 +67,11 @@ pub(crate) fn default_weight() -> u16 { 1 } -pub(crate) fn default_metrics_whitelist() -> Vec { - vec!["127.0.0.1".parse().unwrap(), "::1".parse().unwrap()] +pub(crate) fn default_metrics_whitelist() -> Vec { + vec![ + "127.0.0.1/32".parse().unwrap(), + "::1/128".parse().unwrap(), + ] } pub(crate) fn default_prefer_4() -> u8 { diff --git a/src/config/types.rs b/src/config/types.rs index fa69c12..832070a 100644 --- a/src/config/types.rs +++ b/src/config/types.rs @@ -1,4 +1,5 @@ use chrono::{DateTime, Utc}; +use ipnetwork::IpNetwork; use serde::{Deserialize, Serialize}; use std::collections::HashMap; use std::net::IpAddr; @@ -304,7 +305,7 @@ pub struct ServerConfig { pub metrics_port: Option, #[serde(default = "default_metrics_whitelist")] - pub metrics_whitelist: Vec, + pub metrics_whitelist: Vec, #[serde(default)] pub listeners: Vec, diff --git a/src/metrics.rs b/src/metrics.rs index fa6c680..5222295 100644 --- a/src/metrics.rs +++ b/src/metrics.rs @@ -1,5 +1,5 @@ use std::convert::Infallible; -use std::net::{IpAddr, SocketAddr}; +use std::net::SocketAddr; use std::sync::Arc; use http_body_util::Full; @@ -7,12 +7,13 @@ use hyper::body::Bytes; use hyper::server::conn::http1; use hyper::service::service_fn; use hyper::{Request, Response, StatusCode}; +use ipnetwork::IpNetwork; use tokio::net::TcpListener; use tracing::{info, warn, debug}; use crate::stats::Stats; -pub async fn serve(port: u16, stats: Arc, whitelist: Vec) { +pub async fn serve(port: u16, stats: Arc, whitelist: Vec) { let addr = SocketAddr::from(([0, 0, 0, 0], port)); let listener = match TcpListener::bind(addr).await { Ok(l) => l, @@ -32,7 +33,7 @@ pub async fn serve(port: u16, stats: Arc, whitelist: Vec) { } }; - if !whitelist.is_empty() && !whitelist.contains(&peer.ip()) { + if !whitelist.is_empty() && !whitelist.iter().any(|net| net.contains(peer.ip())) { debug!(peer = %peer, "Metrics request denied by whitelist"); continue; }