1
0

Changed behaviour of remote ip address detection, renamed ip allow/block lists

This commit is contained in:
2023-06-01 20:01:19 +02:00
parent d755754198
commit 371283e653
8 changed files with 135 additions and 77 deletions

View File

@@ -10,7 +10,7 @@ namespace Microsoft.AspNetCore.Mvc.Filters
/// <summary>
/// Implements an IP filter. Only defined addresses are allowed to access.
/// </summary>
public class IPWhitelistAttribute : ActionFilterAttribute
public class IPAllowListAttribute : ActionFilterAttribute
{
/// <summary>
/// Gets or sets a value indicating whether local (localhost) access is granted (Default: true).

View File

@@ -10,12 +10,12 @@ namespace Microsoft.AspNetCore.Mvc.Filters
/// <summary>
/// Implements an IP filter. The defined addresses are blocked.
/// </summary>
public class IPBlacklistAttribute : ActionFilterAttribute
public class IPBlockListAttribute : ActionFilterAttribute
{
/// <summary>
/// Gets or sets a value indicating whether local (localhost) access is blocked (Default: false).
/// </summary>
public bool RestrictLocalAccess { get; set; }
public bool BlockLocalAccess { get; set; }
/// <summary>
/// Gets or sets a configuration key where the blocked IP addresses are defined.
@@ -35,7 +35,7 @@ namespace Microsoft.AspNetCore.Mvc.Filters
/// <summary>
/// Gets or sets a comma separated list of blocked IP addresses.
/// </summary>
public string RestrictedIpAddresses { get; set; }
public string BlockedIpAddresses { get; set; }
/// <inheritdoc/>
public override void OnActionExecuting(ActionExecutingContext context)
@@ -43,13 +43,13 @@ namespace Microsoft.AspNetCore.Mvc.Filters
base.OnActionExecuting(context);
context.HttpContext.Items["RemoteAddress"] = context.HttpContext.GetRemoteIpAddress();
if (!RestrictLocalAccess && context.HttpContext.IsLocalRequest())
if (!BlockLocalAccess && context.HttpContext.IsLocalRequest())
return;
var remoteIpAddress = context.HttpContext.GetRemoteIpAddress();
if (!string.IsNullOrWhiteSpace(RestrictedIpAddresses))
if (!string.IsNullOrWhiteSpace(BlockedIpAddresses))
{
string[] ipAddresses = RestrictedIpAddresses.Split(',');
string[] ipAddresses = BlockedIpAddresses.Split(',');
foreach (string ipAddress in ipAddresses)
{
if (string.IsNullOrWhiteSpace(ipAddress))

View File

@@ -1,4 +1,5 @@
using System.Net;
using System.Linq;
using System.Net;
using Microsoft.AspNetCore.Antiforgery;
using Microsoft.Extensions.DependencyInjection;
@@ -9,30 +10,57 @@ namespace Microsoft.AspNetCore.Http
/// </summary>
public static class HttpContextExtensions
{
// Search these additional headers for a remote client ip address.
private static readonly string[] defaultIpHeaderNames = new[]
{
"X-Forwarded-For", // commonly used on all known proxies
"X-Real-IP", // wide-spread alternative to X-Forwarded-For
"CF-Connecting-IP" // set by Cloudflare
};
/// <summary>
/// Retrieves the antiforgery token.
/// </summary>
/// <param name="httpContext">The current <see cref="HttpContext"/>.</param>
/// <returns>Name and value of the token.</returns>
public static (string Name, string Value) GetAntiforgeryToken(this HttpContext httpContext)
/// <returns>FormName, HeaderName and Value of the antiforgery token.</returns>
public static (string FormName, string HeaderName, string Value) GetAntiforgeryToken(this HttpContext httpContext)
{
var af = httpContext.RequestServices.GetService<IAntiforgery>();
var set = af?.GetAndStoreTokens(httpContext);
var antiforgery = httpContext.RequestServices.GetService<IAntiforgery>();
var tokenSet = antiforgery?.GetAndStoreTokens(httpContext);
return (Name: set?.FormFieldName, Value: set?.RequestToken);
return (tokenSet?.FormFieldName, tokenSet?.HeaderName, tokenSet?.RequestToken);
}
/// <summary>
/// Returns the remote ip address.
/// </summary>
/// <remarks>
/// Searches for additional headers in the following order:
/// <list type="number">
/// <item>X-Forwarded-For</item>
/// <item>X-Real-IP</item>
/// <item>CF-Connecting-IP</item>
/// </list>
/// </remarks>
/// <param name="httpContext">The current <see cref="HttpContext"/>.</param>
/// <param name="headerName">The name of the header to resolve the <see cref="IPAddress"/> when behind a proxy (Default: X-Forwarded-For).</param>
/// <param name="ipHeaderName">The name of the header to resolve the <see cref="IPAddress"/> when behind a proxy.</param>
/// <returns>The ip address of the client.</returns>
public static IPAddress GetRemoteIpAddress(this HttpContext httpContext, string headerName = "X-Forwarded-For")
public static IPAddress GetRemoteIpAddress(this HttpContext httpContext, string ipHeaderName = null)
{
string forwardedHeader = httpContext.Request.Headers[headerName].ToString();
if (!string.IsNullOrWhiteSpace(forwardedHeader) && IPAddress.TryParse(forwardedHeader, out var forwarded))
return forwarded;
string forwardedForAddress = null;
var headerNames = string.IsNullOrWhiteSpace(ipHeaderName) ? defaultIpHeaderNames : new[] { ipHeaderName }.Concat(defaultIpHeaderNames);
foreach (string headerName in headerNames)
{
if (!httpContext.Request.Headers.ContainsKey(headerName))
continue;
forwardedForAddress = httpContext.Request.Headers[headerName].ToString();
break;
}
if (!string.IsNullOrWhiteSpace(forwardedForAddress) && IPAddress.TryParse(forwardedForAddress, out var remoteAddress))
return remoteAddress;
return httpContext.Connection.RemoteIpAddress;
}
@@ -40,12 +68,20 @@ namespace Microsoft.AspNetCore.Http
/// <summary>
/// Returns whether the request was made locally.
/// </summary>
/// <remarks>
/// Searches for additional headers in the following order:
/// <list type="number">
/// <item>X-Forwarded-For</item>
/// <item>X-Real-IP</item>
/// <item>CF-Connecting-IP</item>
/// </list>
/// </remarks>
/// <param name="httpContext">The current <see cref="HttpContext"/>.</param>
/// <param name="headerName">The name of the header to resolve the <see cref="IPAddress"/> when behind a proxy (Default: X-Forwarded-For).</param>
/// <param name="ipHeaderName">The name of the header to resolve the <see cref="IPAddress"/> when behind a proxy.</param>
/// <returns></returns>
public static bool IsLocalRequest(this HttpContext httpContext, string headerName = "X-Forwarded-For")
public static bool IsLocalRequest(this HttpContext httpContext, string ipHeaderName = null)
{
var remoteIpAddress = httpContext.GetRemoteIpAddress(headerName);
var remoteIpAddress = httpContext.GetRemoteIpAddress(ipHeaderName);
return httpContext.Connection.LocalIpAddress.Equals(remoteIpAddress);
}