From 3698452e92fe319221108ceec2edd93e1131af29 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20M=C3=BCller?= Date: Thu, 13 Nov 2025 21:01:50 +0100 Subject: [PATCH] Fixing IPNetwork for .NET 10 --- .../Attributes/IPAllowListAttribute.cs | 5 + .../Attributes/IPBlockListAttribute.cs | 5 + .../ApplicationBuilderExtensions.cs | 130 +++++++++++++----- 3 files changed, 107 insertions(+), 33 deletions(-) diff --git a/src/AMWD.Common.AspNetCore/Attributes/IPAllowListAttribute.cs b/src/AMWD.Common.AspNetCore/Attributes/IPAllowListAttribute.cs index 5db301a..db2c3d0 100644 --- a/src/AMWD.Common.AspNetCore/Attributes/IPAllowListAttribute.cs +++ b/src/AMWD.Common.AspNetCore/Attributes/IPAllowListAttribute.cs @@ -3,7 +3,12 @@ using System.Net; using Microsoft.AspNetCore.Http; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; + +#if NET10_0_OR_GREATER +using IPNetwork = System.Net.IPNetwork; +#else using IPNetwork = Microsoft.AspNetCore.HttpOverrides.IPNetwork; +#endif namespace Microsoft.AspNetCore.Mvc.Filters { diff --git a/src/AMWD.Common.AspNetCore/Attributes/IPBlockListAttribute.cs b/src/AMWD.Common.AspNetCore/Attributes/IPBlockListAttribute.cs index 3b4ba29..dc3d847 100644 --- a/src/AMWD.Common.AspNetCore/Attributes/IPBlockListAttribute.cs +++ b/src/AMWD.Common.AspNetCore/Attributes/IPBlockListAttribute.cs @@ -3,7 +3,12 @@ using System.Net; using Microsoft.AspNetCore.Http; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; + +#if NET10_0_OR_GREATER +using IPNetwork = System.Net.IPNetwork; +#else using IPNetwork = Microsoft.AspNetCore.HttpOverrides.IPNetwork; +#endif namespace Microsoft.AspNetCore.Mvc.Filters { diff --git a/src/AMWD.Common.AspNetCore/Extensions/ApplicationBuilderExtensions.cs b/src/AMWD.Common.AspNetCore/Extensions/ApplicationBuilderExtensions.cs index 293d7b1..9c0c96f 100644 --- a/src/AMWD.Common.AspNetCore/Extensions/ApplicationBuilderExtensions.cs +++ b/src/AMWD.Common.AspNetCore/Extensions/ApplicationBuilderExtensions.cs @@ -2,7 +2,12 @@ using System.Net; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.HttpOverrides; + +#if NET10_0_OR_GREATER +using IPNetwork = System.Net.IPNetwork; +#else using IPNetwork = Microsoft.AspNetCore.HttpOverrides.IPNetwork; +#endif namespace Microsoft.AspNetCore.Builder { @@ -19,9 +24,9 @@ namespace Microsoft.AspNetCore.Builder /// A base path (e.g. running in a sub-directory /app) for the application can be defined via ASPNETCORE_APPL_PATH environment variable. ///
///
- /// Additionally you can specify the proxy server by using or a when there are multiple proxy servers. + /// Additionally you can specify the proxy server by using or a when there are multiple proxy servers. ///
- /// When neither nor is set, the default subnets are configured: + /// When neither nor is set, the default subnets are configured: /// /// 127.0.0.0/8 /// ::1/128 @@ -32,49 +37,108 @@ namespace Microsoft.AspNetCore.Builder /// fd00::/8 /// /// - /// The application builder. - /// The where proxy requests are received from (optional). - /// The where proxy requests are received from (optional). + /// The application builder. + /// The where proxy requests are received from (optional). + /// The where proxy requests are received from (optional). /// A custom base path (optional, ASPNETCORE_APPL_PATH is prefererred). - public static IApplicationBuilder UseProxyHosting(this IApplicationBuilder app, IPNetwork network = null, IPAddress address = null, string basePath = null) +#if NET10_0_OR_GREATER + public static IApplicationBuilder UseProxyHosting(this IApplicationBuilder appBuilder, IPNetwork? proxyNetwork = null, IPAddress proxyAddress = null, string basePath = null) +#else + + public static IApplicationBuilder UseProxyHosting(this IApplicationBuilder appBuilder, IPNetwork proxyNetwork = null, IPAddress proxyAddress = null, string basePath = null) +#endif { - string path = Environment.GetEnvironmentVariable("ASPNETCORE_APPL_PATH"); - if (string.IsNullOrWhiteSpace(path)) - path = basePath; + string envPath = Environment.GetEnvironmentVariable("ASPNETCORE_APPL_PATH"); + string envProxy = Environment.GetEnvironmentVariable("ASPNETCORE_APPL_PROXY"); - if (!string.IsNullOrWhiteSpace(path)) - app.UsePathBase(new PathString(path)); + if (string.IsNullOrWhiteSpace(envPath)) + envPath = basePath; - var options = new ForwardedHeadersOptions { ForwardedHeaders = ForwardedHeaders.All }; - options.KnownProxies.Clear(); - options.KnownNetworks.Clear(); + // Set PathBase from environment variable when available. + // This allows the application to be hosted behind a reverse proxy with a specific sub-path. + if (!string.IsNullOrWhiteSpace(envPath)) + appBuilder.UsePathBase(new PathString(envPath)); - if (network == null && address == null) + // Configure Forwarded Headers to correctly handle reverse proxy scenarios. + var forwardedHeadersOptions = new ForwardedHeadersOptions { - // localhost - options.KnownNetworks.Add(new IPNetwork(IPAddress.Loopback, 8)); - options.KnownNetworks.Add(new IPNetwork(IPAddress.IPv6Loopback, 128)); + ForwardedHeaders = ForwardedHeaders.All + }; - // private IPv4 networks - // see https://en.wikipedia.org/wiki/Private_network#Private_IPv4_addresses - options.KnownNetworks.Add(new IPNetwork(IPAddress.Parse("10.0.0.0"), 8)); - options.KnownNetworks.Add(new IPNetwork(IPAddress.Parse("172.16.0.0"), 12)); - options.KnownNetworks.Add(new IPNetwork(IPAddress.Parse("192.168.0.0"), 16)); + // Reset KnownProxies and KnownNetworks to avoid default restrictions. + forwardedHeadersOptions.KnownProxies.Clear(); - // private IPv6 networks - // see https://en.wikipedia.org/wiki/Private_network#Private_IPv6_addresses - options.KnownNetworks.Add(new IPNetwork(IPAddress.Parse("fd00::"), 8)); +#if NET10_0_OR_GREATER + forwardedHeadersOptions.KnownIPNetworks.Clear(); +#else + forwardedHeadersOptions.KnownNetworks.Clear(); +#endif + + // If no specific proxy address or network is provided, use environment variable or defaults. + if (proxyAddress == null && proxyNetwork == null) + { + if (string.IsNullOrWhiteSpace(envProxy)) + { +#if NET10_0_OR_GREATER + // Always trust localhost. + forwardedHeadersOptions.KnownIPNetworks.Add(IPNetwork.Parse("127.0.0.0/8")); + forwardedHeadersOptions.KnownIPNetworks.Add(IPNetwork.Parse("::1/128")); + + // Trust common private network ranges. + forwardedHeadersOptions.KnownIPNetworks.Add(IPNetwork.Parse("10.0.0.0/8")); + forwardedHeadersOptions.KnownIPNetworks.Add(IPNetwork.Parse("172.16.0.0/12")); + forwardedHeadersOptions.KnownIPNetworks.Add(IPNetwork.Parse("192.168.0.0/16")); + forwardedHeadersOptions.KnownIPNetworks.Add(IPNetwork.Parse("fd00::/8")); +#else + // Always trust localhost. + forwardedHeadersOptions.KnownNetworks.Add(IPNetwork.Parse("127.0.0.0/8")); + forwardedHeadersOptions.KnownNetworks.Add(IPNetwork.Parse("::1/128")); + + // Trust common private network ranges. + forwardedHeadersOptions.KnownNetworks.Add(IPNetwork.Parse("10.0.0.0/8")); + forwardedHeadersOptions.KnownNetworks.Add(IPNetwork.Parse("172.16.0.0/12")); + forwardedHeadersOptions.KnownNetworks.Add(IPNetwork.Parse("192.168.0.0/16")); + forwardedHeadersOptions.KnownNetworks.Add(IPNetwork.Parse("fd00::/8")); +#endif + } + else + { + // Try to parse proxies from environment variable. + string[] envProxies = envProxy.Split(',', StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries); + foreach (string proxy in envProxies) + { + if (IPAddress.TryParse(proxy, out var address)) + { + forwardedHeadersOptions.KnownProxies.Add(address); + continue; + } + + if (IPNetwork.TryParse(proxy, out var network)) + { +#if NET10_0_OR_GREATER + forwardedHeadersOptions.KnownIPNetworks.Add(network); +#else + forwardedHeadersOptions.KnownNetworks.Add(network); +#endif + continue; + } + } + } } - if (network != null) - options.KnownNetworks.Add(network); + if (proxyAddress != null) + forwardedHeadersOptions.KnownProxies.Add(proxyAddress); - if (address != null) - options.KnownProxies.Add(address); +#if NET10_0_OR_GREATER + if (proxyNetwork.HasValue) + forwardedHeadersOptions.KnownIPNetworks.Add(proxyNetwork.Value); +#else + if (proxyNetwork != null) + forwardedHeadersOptions.KnownNetworks.Add(proxyNetwork); +#endif - app.UseForwardedHeaders(options); - - return app; + appBuilder.UseForwardedHeaders(forwardedHeadersOptions); + return appBuilder; } } }