Block non-public IPR/NR checks (#6670)
* Block non-public IPR/NR checks * Add CLI override flag
This commit is contained in:
@@ -38,6 +38,7 @@ default = []
|
||||
openapi = ["utoipa"]
|
||||
output_format = ["serde_json", "dep:clap"]
|
||||
bin_info_schema = ["schemars"]
|
||||
ip_check = []
|
||||
basic_tracing = ["dep:tracing", "dep:tracing-subscriber"]
|
||||
otel-otlp = [
|
||||
"basic_tracing",
|
||||
|
||||
+13
-18
@@ -1,29 +1,12 @@
|
||||
// Copyright 2025 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: GPL-3.0-only
|
||||
|
||||
use std::net::{IpAddr, Ipv4Addr, Ipv6Addr};
|
||||
|
||||
// use `ip` feature without nightly
|
||||
// issue: https://github.com/rust-lang/rust/issues/27709
|
||||
pub(crate) const fn is_global_ip(ip: &IpAddr) -> bool {
|
||||
pub const fn is_global_ip(ip: &IpAddr) -> bool {
|
||||
match ip {
|
||||
IpAddr::V4(addr) => is_global_ipv4(addr),
|
||||
IpAddr::V6(addr) => is_global_ipv6(addr),
|
||||
}
|
||||
}
|
||||
|
||||
const fn is_shared_ipv4(ip: &Ipv4Addr) -> bool {
|
||||
ip.octets()[0] == 100 && (ip.octets()[1] & 0b1100_0000 == 0b0100_0000)
|
||||
}
|
||||
|
||||
const fn is_benchmarking_ipv4(ip: &Ipv4Addr) -> bool {
|
||||
ip.octets()[0] == 198 && (ip.octets()[1] & 0xfe) == 18
|
||||
}
|
||||
|
||||
const fn is_reserved_ipv4(ip: &Ipv4Addr) -> bool {
|
||||
ip.octets()[0] & 240 == 240 && !ip.is_broadcast()
|
||||
}
|
||||
|
||||
const fn is_global_ipv4(ip: &Ipv4Addr) -> bool {
|
||||
!(ip.octets()[0] == 0 // "This network"
|
||||
|| ip.is_private()
|
||||
@@ -42,6 +25,18 @@ const fn is_global_ipv4(ip: &Ipv4Addr) -> bool {
|
||||
|| ip.is_broadcast())
|
||||
}
|
||||
|
||||
const fn is_shared_ipv4(ip: &Ipv4Addr) -> bool {
|
||||
ip.octets()[0] == 100 && (ip.octets()[1] & 0b1100_0000 == 0b0100_0000)
|
||||
}
|
||||
|
||||
const fn is_benchmarking_ipv4(ip: &Ipv4Addr) -> bool {
|
||||
ip.octets()[0] == 198 && (ip.octets()[1] & 0xfe) == 18
|
||||
}
|
||||
|
||||
const fn is_reserved_ipv4(ip: &Ipv4Addr) -> bool {
|
||||
ip.octets()[0] & 240 == 240 && !ip.is_broadcast()
|
||||
}
|
||||
|
||||
const fn is_documentation_ipv6(ip: &Ipv6Addr) -> bool {
|
||||
(ip.segments()[0] == 0x2001) && (ip.segments()[1] == 0xdb8)
|
||||
}
|
||||
@@ -9,3 +9,6 @@ pub mod completions;
|
||||
|
||||
#[cfg(feature = "output_format")]
|
||||
pub mod output_format;
|
||||
|
||||
#[cfg(feature = "ip_check")]
|
||||
pub mod ip_check;
|
||||
|
||||
@@ -58,6 +58,7 @@ sysinfo = { workspace = true }
|
||||
nym-bin-common = { workspace = true, features = [
|
||||
"basic_tracing",
|
||||
"output_format",
|
||||
"ip_check"
|
||||
] }
|
||||
nym-client-core-config-types = { workspace = true, features = [
|
||||
"disk-persistence",
|
||||
|
||||
@@ -5,7 +5,7 @@ use crate::config::upgrade_helpers::try_load_current_config;
|
||||
use crate::error::NymNodeError;
|
||||
use crate::node::NymNode;
|
||||
use crate::node::bonding_information::BondingInformation;
|
||||
use crate::node::mixnet::packet_forwarding::global::is_global_ip;
|
||||
use nym_bin_common::ip_check::is_global_ip;
|
||||
use std::fs;
|
||||
use std::net::IpAddr;
|
||||
use tracing::{debug, info, trace, warn};
|
||||
|
||||
@@ -512,6 +512,26 @@ pub(crate) struct ExitGatewayArgs {
|
||||
env = NYMNODE_OPEN_PROXY_ARG,
|
||||
)]
|
||||
pub(crate) open_proxy: Option<bool>,
|
||||
|
||||
/// Allow the network requester to forward traffic to non-globally-routable
|
||||
/// addresses. Intended for local development, private-network deployments,
|
||||
/// and testnet scenarios.
|
||||
/// Not recommended on production exit gateway unless you know what you're doing.
|
||||
#[clap(
|
||||
long,
|
||||
env = NYMNODE_NR_ALLOW_LOCAL_IPS_ARG,
|
||||
)]
|
||||
pub(crate) nr_allow_local_ips: Option<bool>,
|
||||
|
||||
/// Allow the IP packet router to forward traffic to non-globally-routable
|
||||
/// addresses. Intended for local development, private-network deployments,
|
||||
/// and testnet scenarios.
|
||||
/// Not recommended on production exit gateway unless you know what you're doing.
|
||||
#[clap(
|
||||
long,
|
||||
env = NYMNODE_IPR_ALLOW_LOCAL_IPS_ARG,
|
||||
)]
|
||||
pub(crate) ipr_allow_local_ips: Option<bool>,
|
||||
}
|
||||
|
||||
impl ExitGatewayArgs {
|
||||
@@ -533,6 +553,12 @@ impl ExitGatewayArgs {
|
||||
if let Some(open_proxy) = self.open_proxy {
|
||||
section.open_proxy = open_proxy
|
||||
}
|
||||
if let Some(allow_local_ips) = self.nr_allow_local_ips {
|
||||
section.network_requester.allow_local_ips = allow_local_ips
|
||||
}
|
||||
if let Some(allow_local_ips) = self.ipr_allow_local_ips {
|
||||
section.ip_packet_router.allow_local_ips = allow_local_ips
|
||||
}
|
||||
|
||||
section
|
||||
}
|
||||
|
||||
@@ -107,6 +107,7 @@ pub fn gateway_tasks_config(config: &Config) -> GatewayTasksConfig {
|
||||
},
|
||||
network_requester: nym_network_requester::config::NetworkRequester {
|
||||
open_proxy: config.service_providers.open_proxy,
|
||||
allow_local_ips: config.service_providers.network_requester.allow_local_ips,
|
||||
disable_poisson_rate: config
|
||||
.service_providers
|
||||
.network_requester
|
||||
@@ -150,6 +151,7 @@ pub fn gateway_tasks_config(config: &Config) -> GatewayTasksConfig {
|
||||
},
|
||||
ip_packet_router: nym_ip_packet_router::config::IpPacketRouter {
|
||||
open_proxy: config.service_providers.open_proxy,
|
||||
allow_local_ips: config.service_providers.ip_packet_router.allow_local_ips,
|
||||
disable_poisson_rate: config
|
||||
.service_providers
|
||||
.ip_packet_router
|
||||
|
||||
@@ -938,6 +938,7 @@ pub async fn try_upgrade_config_v12<P: AsRef<Path>>(
|
||||
open_proxy: old_cfg.service_providers.open_proxy,
|
||||
upstream_exit_policy_url: old_cfg.service_providers.upstream_exit_policy_url,
|
||||
network_requester: NetworkRequester {
|
||||
allow_local_ips: false,
|
||||
debug: NetworkRequesterDebug {
|
||||
enabled: old_cfg.service_providers.network_requester.debug.enabled,
|
||||
disable_poisson_rate: old_cfg
|
||||
@@ -953,6 +954,7 @@ pub async fn try_upgrade_config_v12<P: AsRef<Path>>(
|
||||
},
|
||||
},
|
||||
ip_packet_router: IpPacketRouter {
|
||||
allow_local_ips: false,
|
||||
debug: IpPacketRouterDebug {
|
||||
enabled: old_cfg.service_providers.ip_packet_router.debug.enabled,
|
||||
disable_poisson_rate: old_cfg
|
||||
|
||||
@@ -75,6 +75,11 @@ impl ServiceProvidersConfig {
|
||||
|
||||
#[derive(Debug, Clone, Copy, Deserialize, PartialEq, Serialize)]
|
||||
pub struct NetworkRequester {
|
||||
/// Allow the network requester to forward traffic to non-globally-routable addresses.
|
||||
/// Intended for development & testing.
|
||||
#[serde(default)]
|
||||
pub allow_local_ips: bool,
|
||||
|
||||
#[serde(default)]
|
||||
pub debug: NetworkRequesterDebug,
|
||||
}
|
||||
@@ -83,6 +88,7 @@ pub struct NetworkRequester {
|
||||
impl Default for NetworkRequester {
|
||||
fn default() -> Self {
|
||||
NetworkRequester {
|
||||
allow_local_ips: false,
|
||||
debug: Default::default(),
|
||||
}
|
||||
}
|
||||
@@ -117,6 +123,11 @@ impl Default for NetworkRequesterDebug {
|
||||
|
||||
#[derive(Debug, Clone, Deserialize, PartialEq, Serialize)]
|
||||
pub struct IpPacketRouter {
|
||||
/// Allow the IP packet router to forward traffic to non-globally-routable addresses.
|
||||
/// Intended for development & testing.
|
||||
#[serde(default)]
|
||||
pub allow_local_ips: bool,
|
||||
|
||||
#[serde(default)]
|
||||
pub debug: IpPacketRouterDebug,
|
||||
}
|
||||
@@ -125,6 +136,7 @@ pub struct IpPacketRouter {
|
||||
impl Default for IpPacketRouter {
|
||||
fn default() -> Self {
|
||||
IpPacketRouter {
|
||||
allow_local_ips: false,
|
||||
debug: Default::default(),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -70,6 +70,8 @@ pub mod vars {
|
||||
// exit gateway:
|
||||
pub const NYMNODE_UPSTREAM_EXIT_POLICY_ARG: &str = "NYMNODE_UPSTREAM_EXIT_POLICY";
|
||||
pub const NYMNODE_OPEN_PROXY_ARG: &str = "NYMNODE_OPEN_PROXY";
|
||||
pub const NYMNODE_NR_ALLOW_LOCAL_IPS_ARG: &str = "NYMNODE_NR_ALLOW_LOCAL_IPS";
|
||||
pub const NYMNODE_IPR_ALLOW_LOCAL_IPS_ARG: &str = "NYMNODE_IPR_ALLOW_LOCAL_IPS";
|
||||
|
||||
// LP:
|
||||
pub const NYMNODE_LP_CONTROL_BIND_ADDRESS_ARG: &str = "NYMNODE_LP_CONTROL_BIND_ADDRESS";
|
||||
|
||||
@@ -15,8 +15,6 @@ use std::io;
|
||||
use tokio::time::Instant;
|
||||
use tracing::{debug, error, trace, warn};
|
||||
|
||||
pub(crate) mod global;
|
||||
|
||||
pub struct PacketForwarder<C, F> {
|
||||
delay_queue: NonExhaustiveDelayQueue<MixPacket>,
|
||||
mixnet_client: C,
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
// Copyright 2025 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: GPL-3.0-only
|
||||
|
||||
use crate::node::mixnet::packet_forwarding::global::is_global_ip;
|
||||
use crate::node::routing_filter::RoutingFilter;
|
||||
use arc_swap::ArcSwap;
|
||||
use nym_bin_common::ip_check::is_global_ip;
|
||||
use std::collections::HashSet;
|
||||
use std::net::IpAddr;
|
||||
use std::sync::Arc;
|
||||
|
||||
@@ -19,7 +19,7 @@ etherparse = { workspace = true }
|
||||
futures = { workspace = true }
|
||||
log = { workspace = true }
|
||||
|
||||
nym-bin-common = { workspace = true, features = ["clap", "basic_tracing"] }
|
||||
nym-bin-common = { workspace = true, features = ["clap", "basic_tracing", "ip_check"] }
|
||||
nym-client-core = { workspace = true }
|
||||
nym-config = { workspace = true }
|
||||
nym-crypto = { workspace = true }
|
||||
|
||||
@@ -192,6 +192,11 @@ pub struct IpPacketRouter {
|
||||
/// and thus would attempt to resolve **ANY** request it receives.
|
||||
pub open_proxy: bool,
|
||||
|
||||
/// Allow the IP packet router to forward traffic to non-globally-routable addresses.
|
||||
/// Intended for development & testing.
|
||||
#[serde(default)]
|
||||
pub allow_local_ips: bool,
|
||||
|
||||
/// Disable Poisson sending rate.
|
||||
pub disable_poisson_rate: bool,
|
||||
|
||||
@@ -204,6 +209,7 @@ impl Default for IpPacketRouter {
|
||||
fn default() -> Self {
|
||||
IpPacketRouter {
|
||||
open_proxy: false,
|
||||
allow_local_ips: false,
|
||||
disable_poisson_rate: true,
|
||||
#[allow(clippy::expect_used)]
|
||||
upstream_exit_policy_url: Some(
|
||||
|
||||
@@ -95,6 +95,7 @@ impl From<IpPacketRouterV1> for IpPacketRouter {
|
||||
fn from(value: IpPacketRouterV1) -> Self {
|
||||
IpPacketRouter {
|
||||
open_proxy: false,
|
||||
allow_local_ips: false,
|
||||
disable_poisson_rate: value.disable_poisson_rate,
|
||||
upstream_exit_policy_url: value.upstream_exit_policy_url,
|
||||
}
|
||||
|
||||
@@ -4,6 +4,8 @@
|
||||
use std::net::SocketAddr;
|
||||
|
||||
use crate::error::IpPacketRouterError;
|
||||
use log::warn;
|
||||
use nym_bin_common::ip_check::is_global_ip;
|
||||
use nym_exit_policy::ExitPolicy;
|
||||
use nym_exit_policy::client::get_exit_policy;
|
||||
use reqwest::IntoUrl;
|
||||
@@ -13,10 +15,14 @@ pub struct ExitPolicyRequestFilter {
|
||||
#[allow(unused)]
|
||||
upstream: Option<Url>,
|
||||
policy: ExitPolicy,
|
||||
allow_local_ips: bool,
|
||||
}
|
||||
|
||||
impl ExitPolicyRequestFilter {
|
||||
pub(crate) async fn new_upstream(url: impl IntoUrl) -> Result<Self, IpPacketRouterError> {
|
||||
pub(crate) async fn new_upstream(
|
||||
url: impl IntoUrl,
|
||||
allow_local_ips: bool,
|
||||
) -> Result<Self, IpPacketRouterError> {
|
||||
let url = url
|
||||
.into_url()
|
||||
.map_err(|source| IpPacketRouterError::MalformedExitPolicyUpstreamUrl { source })?;
|
||||
@@ -24,21 +30,24 @@ impl ExitPolicyRequestFilter {
|
||||
Ok(ExitPolicyRequestFilter {
|
||||
upstream: Some(url.clone()),
|
||||
policy: get_exit_policy(url).await?,
|
||||
allow_local_ips,
|
||||
})
|
||||
}
|
||||
|
||||
#[allow(unused)]
|
||||
pub(crate) fn new(policy: ExitPolicy) -> Self {
|
||||
pub(crate) fn new(policy: ExitPolicy, allow_local_ips: bool) -> Self {
|
||||
ExitPolicyRequestFilter {
|
||||
upstream: None,
|
||||
policy,
|
||||
allow_local_ips,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn new_from_policy(policy: ExitPolicy) -> Self {
|
||||
pub fn new_from_policy(policy: ExitPolicy, allow_local_ips: bool) -> Self {
|
||||
ExitPolicyRequestFilter {
|
||||
upstream: None,
|
||||
policy,
|
||||
allow_local_ips,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -53,6 +62,13 @@ impl ExitPolicyRequestFilter {
|
||||
}
|
||||
|
||||
pub(crate) async fn check(&self, addr: &SocketAddr) -> Result<bool, IpPacketRouterError> {
|
||||
// private ranges are disallowed regardless of policy: end user has
|
||||
// no business with internal/private IP ranges of IPR
|
||||
if !self.allow_local_ips && !is_global_ip(&addr.ip()) {
|
||||
warn!("Rejecting non-global address {addr}");
|
||||
return Ok(false);
|
||||
}
|
||||
|
||||
self.policy
|
||||
.allows_sockaddr(addr)
|
||||
.ok_or(IpPacketRouterError::AddressNotCoveredByExitPolicy { addr: *addr })
|
||||
|
||||
@@ -43,15 +43,23 @@ impl RequestFilter {
|
||||
}
|
||||
|
||||
async fn new_exit_policy_filter(config: &Config) -> Result<Self, IpPacketRouterError> {
|
||||
let allow_local_ips = config.ip_packet_router.allow_local_ips;
|
||||
if allow_local_ips {
|
||||
warn!(
|
||||
"Requests to non-global destinations are allowed by the policy guard. \
|
||||
This is intended for local development and NOT recommended in production \
|
||||
unless you know what you're doing."
|
||||
);
|
||||
}
|
||||
let policy_filter = if config.ip_packet_router.open_proxy {
|
||||
ExitPolicyRequestFilter::new_from_policy(ExitPolicy::new_open())
|
||||
ExitPolicyRequestFilter::new_from_policy(ExitPolicy::new_open(), allow_local_ips)
|
||||
} else {
|
||||
let upstream_url = config
|
||||
.ip_packet_router
|
||||
.upstream_exit_policy_url
|
||||
.as_ref()
|
||||
.ok_or(IpPacketRouterError::NoUpstreamExitPolicy)?;
|
||||
ExitPolicyRequestFilter::new_upstream(upstream_url.clone()).await?
|
||||
ExitPolicyRequestFilter::new_upstream(upstream_url.clone(), allow_local_ips).await?
|
||||
};
|
||||
|
||||
Ok(RequestFilter {
|
||||
|
||||
@@ -44,7 +44,7 @@ zeroize = { workspace = true }
|
||||
|
||||
# internal
|
||||
nym-async-file-watcher = { workspace = true }
|
||||
nym-bin-common = { workspace = true, features = ["output_format", "clap", "basic_tracing"] }
|
||||
nym-bin-common = { workspace = true, features = ["output_format", "clap", "basic_tracing", "ip_check"] }
|
||||
nym-client-core = { workspace = true, features = ["cli", "fs-gateways-storage", "fs-surb-storage"] }
|
||||
nym-client-websocket-requests = { workspace = true }
|
||||
nym-config = { workspace = true }
|
||||
|
||||
@@ -210,6 +210,11 @@ pub struct NetworkRequester {
|
||||
/// and thus would attempt to resolve **ANY** request it receives.
|
||||
pub open_proxy: bool,
|
||||
|
||||
/// Allow the network requester to forward traffic to non-globally-routable addresses.
|
||||
/// Intended for development & testing.
|
||||
#[serde(default)]
|
||||
pub allow_local_ips: bool,
|
||||
|
||||
/// Disable Poisson sending rate.
|
||||
/// This is equivalent to setting debug.traffic.disable_main_poisson_packet_distribution = true,
|
||||
pub disable_poisson_rate: bool,
|
||||
@@ -223,6 +228,7 @@ impl Default for NetworkRequester {
|
||||
fn default() -> Self {
|
||||
NetworkRequester {
|
||||
open_proxy: false,
|
||||
allow_local_ips: false,
|
||||
disable_poisson_rate: true,
|
||||
upstream_exit_policy_url: Some(
|
||||
mainnet::EXIT_POLICY_URL
|
||||
|
||||
@@ -113,6 +113,7 @@ impl From<NetworkRequesterV5> for NetworkRequester {
|
||||
fn from(value: NetworkRequesterV5) -> Self {
|
||||
NetworkRequester {
|
||||
open_proxy: value.open_proxy,
|
||||
allow_local_ips: false,
|
||||
disable_poisson_rate: value.disable_poisson_rate,
|
||||
upstream_exit_policy_url: value.upstream_exit_policy_url,
|
||||
}
|
||||
|
||||
@@ -81,6 +81,11 @@ nr_description = '{{ storage_paths.nr_description }}'
|
||||
# and thus would attempt to resolve **ANY** request it receives.
|
||||
open_proxy = {{ network_requester.open_proxy }}
|
||||
|
||||
# Allow forwarding traffic to non-globally-routable addresses.
|
||||
# Intended for local development for security reasons.
|
||||
# Only enable if you know what you're doing.
|
||||
allow_local_ips = {{ network_requester.allow_local_ips }}
|
||||
|
||||
# Disable Poisson sending rate
|
||||
# This is equivalent to setting debug.traffic.disable_main_poisson_packet_distribution = true,
|
||||
disable_poisson_rate = {{ network_requester.disable_poisson_rate }}
|
||||
|
||||
@@ -3,7 +3,8 @@
|
||||
|
||||
use crate::config::Config;
|
||||
use crate::error::NetworkRequesterError;
|
||||
use log::trace;
|
||||
use log::{trace, warn};
|
||||
use nym_bin_common::ip_check::is_global_ip;
|
||||
use nym_exit_policy::ExitPolicy;
|
||||
use nym_exit_policy::client::get_exit_policy;
|
||||
use nym_socks5_requests::RemoteAddress;
|
||||
@@ -14,16 +15,20 @@ use url::Url;
|
||||
pub struct ExitPolicyRequestFilter {
|
||||
upstream: Option<Url>,
|
||||
policy: ExitPolicy,
|
||||
allow_local_ips: bool,
|
||||
}
|
||||
|
||||
impl From<ExitPolicy> for ExitPolicyRequestFilter {
|
||||
fn from(value: ExitPolicy) -> Self {
|
||||
ExitPolicyRequestFilter::new_from_policy(value)
|
||||
ExitPolicyRequestFilter::new_from_policy(value, false)
|
||||
}
|
||||
}
|
||||
|
||||
impl ExitPolicyRequestFilter {
|
||||
pub(crate) async fn new_upstream(url: impl IntoUrl) -> Result<Self, NetworkRequesterError> {
|
||||
pub(crate) async fn new_upstream(
|
||||
url: impl IntoUrl,
|
||||
allow_local_ips: bool,
|
||||
) -> Result<Self, NetworkRequesterError> {
|
||||
let url = url
|
||||
.into_url()
|
||||
.map_err(|source| NetworkRequesterError::MalformedExitPolicyUpstreamUrl { source })?;
|
||||
@@ -31,27 +36,37 @@ impl ExitPolicyRequestFilter {
|
||||
Ok(ExitPolicyRequestFilter {
|
||||
upstream: Some(url.clone()),
|
||||
policy: get_exit_policy(url).await?,
|
||||
allow_local_ips,
|
||||
})
|
||||
}
|
||||
|
||||
pub(crate) async fn new(config: &Config) -> Result<Self, NetworkRequesterError> {
|
||||
let allow_local_ips = config.network_requester.allow_local_ips;
|
||||
if allow_local_ips {
|
||||
warn!(
|
||||
"Requests to non-global destinations are allowed by the policy guard. \
|
||||
This is intended for local development and NOT recommended in production \
|
||||
unless you know what you're doing."
|
||||
);
|
||||
}
|
||||
let policy_filter = if config.network_requester.open_proxy {
|
||||
ExitPolicyRequestFilter::new_from_policy(ExitPolicy::new_open())
|
||||
ExitPolicyRequestFilter::new_from_policy(ExitPolicy::new_open(), allow_local_ips)
|
||||
} else {
|
||||
let upstream_url = config
|
||||
.network_requester
|
||||
.upstream_exit_policy_url
|
||||
.as_ref()
|
||||
.ok_or(NetworkRequesterError::NoUpstreamExitPolicy)?;
|
||||
ExitPolicyRequestFilter::new_upstream(upstream_url.clone()).await?
|
||||
ExitPolicyRequestFilter::new_upstream(upstream_url.clone(), allow_local_ips).await?
|
||||
};
|
||||
Ok(policy_filter)
|
||||
}
|
||||
|
||||
pub fn new_from_policy(policy: ExitPolicy) -> Self {
|
||||
pub fn new_from_policy(policy: ExitPolicy, allow_local_ips: bool) -> Self {
|
||||
ExitPolicyRequestFilter {
|
||||
upstream: None,
|
||||
policy,
|
||||
allow_local_ips,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -89,6 +104,13 @@ impl ExitPolicyRequestFilter {
|
||||
// if the remote decided to give us an address that can resolve to multiple socket addresses,
|
||||
// they'd better make sure all of them are allowed by the exit policy.
|
||||
for addr in addrs {
|
||||
// private ranges are disallowed regardless of policy: end user has
|
||||
// no business with internal/private IP ranges of network requester
|
||||
if !self.allow_local_ips && !is_global_ip(&addr.ip()) {
|
||||
warn!("Rejecting non-global address {addr} for '{remote}'");
|
||||
return Ok(false);
|
||||
}
|
||||
// exit policy determines which PUBLIC facing addresses are allowed
|
||||
if !self
|
||||
.policy
|
||||
.allows_sockaddr(&addr)
|
||||
|
||||
Reference in New Issue
Block a user