Asp.Net Core security - client IP whitelist restrictions

Posted by LAEinc. Creations on Sat, 09 Oct 2021 04:02:51 +0200

catalogue

preface

middleware

Action filter

summary

preface

This article shows how to set up two ways of IP whitelist verification in ASP.NET Core applications.

You can use the following 2 methods:

  • Middleware for checking the remote IP address of each request.

  • MVC action filter that checks the remote IP address of a request for a specific controller or action method.

middleware

The Startup.Configure method will be customized   AdminSafeListMiddleware   The middleware type is added to the request pipeline of the application.   The security is retrieved using the. NET Core configuration provider and passed as a constructor parameter.

app.UseMiddleware<AdminSafeListMiddleware>("127.0.0.1;192.168.1.5;::1");

The middleware analyzes the string into an array and searches for the remote IP address in the array.   If the remote IP address cannot be found, the middleware will return HTTP 403 to prohibit access.   For HTTP GET requests, this validation process is skipped.

public class AdminSafeListMiddleware
{
    private readonly RequestDelegate _next;
    private readonly ILogger<AdminSafeListMiddleware> _logger;
    private readonly string _safelist;

    public AdminSafeListMiddleware(
        RequestDelegate next,
        ILogger<AdminSafeListMiddleware> logger,
        string safelist)
    {
        _safelist = safelist;
        _next = next;
        _logger = logger;
    }

    public async Task Invoke(HttpContext context)
    {
        if (context.Request.Method != HttpMethod.Get.Method)
        {
            var remoteIp = context.Connection.RemoteIpAddress;
            _logger.LogDebug("Request from Remote IP address: {RemoteIp}", remoteIp);

            string[] ip = _safelist.Split(';');

            var bytes = remoteIp.GetAddressBytes();
            var badIp = true;
            foreach (var address in ip)
            {
                var testIp = IPAddress.Parse(address);
                if (testIp.GetAddressBytes().SequenceEqual(bytes))
                {
                    badIp = false;
                    break;
                }
            }

            if (badIp)
            {
                _logger.LogWarning(
                    "Forbidden Request from Remote IP address: {RemoteIp}", remoteIp);
                context.Response.StatusCode = StatusCodes.Status403Forbidden;
                return;
            }
        }

        await _next.Invoke(context);
    }
}

Action filter

If you need secure access control for a specific MVC controller or action method, use the action filter.   For example:

public class ClientIpCheckActionFilter : ActionFilterAttribute
{
    private readonly ILogger _logger;
    private readonly string _safelist;

    public ClientIpCheckActionFilter(string safelist, ILogger logger)
    {
        _safelist = safelist;
        _logger = logger;
    }

    public override void OnActionExecuting(ActionExecutingContext context)
    {
        var remoteIp = context.HttpContext.Connection.RemoteIpAddress;
        _logger.LogDebug("Remote IpAddress: {RemoteIp}", remoteIp);
        var ip = _safelist.Split(';');
        var badIp = true;

        if (remoteIp.IsIPv4MappedToIPv6)
        {
            remoteIp = remoteIp.MapToIPv4();
        }

        foreach (var address in ip)
        {
            var testIp = IPAddress.Parse(address);

            if (testIp.Equals(remoteIp))
            {
                badIp = false;
                break;
            }
        }

        if (badIp)
        {
            _logger.LogWarning("Forbidden Request from IP: {RemoteIp}", remoteIp);
            context.Result = new StatusCodeResult(StatusCodes.Status403Forbidden);
            return;
        }

        base.OnActionExecuting(context);
    }
}

In   Startup.ConfigureServices  , Adds an action filter to the MVC filter collection.   In the following example,   ClientIpCheckActionFilter   Added an action filter.   The security log and console logger instances are passed as constructor parameters. ​​​​​​​

services.AddScoped<ClientIpCheckActionFilter>(container =>
{
    var loggerFactory = container.GetRequiredService<ILoggerFactory>();
    var logger = loggerFactory.CreateLogger<ClientIpCheckActionFilter>();

    return new ClientIpCheckActionFilter(
        "127.0.0.1;192.168.1.5;::1", logger);
});

You can then apply an action filter to a with   [ServiceFilter]   Property's controller or operation method:

[ServiceFilter(typeof(ClientIpCheckActionFilter))]
[HttpGet]
public IEnumerable<string> Get()

In the example application, the action filter is applied to the controller   Get   Operation method.   When you test an application by sending:

  • HTTP GET request, the   [ServiceFilter]   Property to verify the client IP address.   If access is allowed   Get   Action methods, the action filter and action methods generate variations of the following console output:

dbug: ClientIpSafelistComponents.Filters.ClientIpCheckActionFilter[0]
      Remote IpAddress: ::1
dbug: ClientIpAspNetCore.Controllers.ValuesController[0]
      successful HTTP GET

HTTP request predicates other than GET will   AdminSafeListMiddleware   Verify the client IP address.

summary

The case can be transformed into blacklist interception.

Topics: ASP.NET mvc