Allow CIDR ranges in Allowed IPs (#666)

* Allow CIDR ranges in Allowed IPs

* Catch mixed IPv4/IPv6 mappings that are probably intended to match
This commit is contained in:
Brian Bradley
2025-07-28 01:03:12 -04:00
committed by GitHub
parent 7af8e5b287
commit 4c1d7a61dc
5 changed files with 28 additions and 14 deletions

View File

@@ -129,3 +129,4 @@ colored = "3.0.0"
regex = "1.11.1"
bytes = "1.10.1"
bson = "2.15.0"
ipnetwork = { version = "0.21.1", features = ["serde"] }

View File

@@ -57,3 +57,4 @@ clap.workspace = true
envy.workspace = true
uuid.workspace = true
rand.workspace = true
ipnetwork.workspace = true

View File

@@ -1,5 +1,4 @@
use std::net::SocketAddr;
use std::net::{SocketAddr, IpAddr};
use anyhow::{Context, anyhow};
use axum::{
Router,
@@ -124,12 +123,24 @@ async fn guard_request_by_ip(
.context("could not get ConnectionInfo of request")
.status_code(StatusCode::UNAUTHORIZED)?;
let ip = socket_addr.ip();
if periphery_config().allowed_ips.contains(&ip) {
Ok(next.run(req).await)
let ip_match = periphery_config()
.allowed_ips
.iter()
.any(|net| {
net.contains(ip) ||
match ip {
IpAddr::V4(ipv4) => net.contains(IpAddr::V6(ipv4.to_ipv6_mapped())),
IpAddr::V6(_) => net.contains(ip.to_canonical()),
}
});
if ip_match {
Ok(next.run(req).await)
} else {
Err(
anyhow!("requesting ip {ip} not allowed")
.status_code(StatusCode::UNAUTHORIZED),
)
Err(
anyhow!("requesting ip {ip} not allowed")
.status_code(StatusCode::UNAUTHORIZED),
)
}
}

View File

@@ -43,4 +43,5 @@ strum.workspace = true
envy.workspace = true
uuid.workspace = true
clap.workspace = true
bson.workspace = true
bson.workspace = true
ipnetwork.workspace = true

View File

@@ -12,8 +12,8 @@
//! the configuration file.
//!
use std::{collections::HashMap, net::IpAddr, path::PathBuf};
use std::{collections::HashMap, path::PathBuf};
use ipnetwork::IpNetwork;
use clap::Parser;
use serde::Deserialize;
@@ -150,7 +150,7 @@ pub struct Env {
pub periphery_pretty_startup_config: Option<bool>,
/// Override `allowed_ips`
pub periphery_allowed_ips: Option<Vec<IpAddr>>,
pub periphery_allowed_ips: Option<Vec<IpNetwork>>,
/// Override `passkeys`
pub periphery_passkeys: Option<Vec<String>>,
/// Override `passkeys` from file
@@ -250,12 +250,12 @@ pub struct PeripheryConfig {
#[serde(default)]
pub pretty_startup_config: bool,
/// Limits which IPv4 addresses are allowed to call the api.
/// Limits which IP addresses are allowed to call the api.
/// Default: none
///
/// Note: this should be configured to increase security.
#[serde(default)]
pub allowed_ips: Vec<IpAddr>,
pub allowed_ips: Vec<IpNetwork>,
/// Limits the accepted passkeys.
/// Default: none