You are currently viewing Restrict IP Address ASP.NET Core Web API

Restrict IP Address ASP.NET Core Web API

There are several ways to restrict access to a Web server based on the requestor’s IP address.  We can do that from IIS or using inbound Firewall rules. But If you want to restrict access to one of the applications deployed in the server based on the IP Address then you have to achieve that programmatically.  In this post, I will guide you on how to restrict IP address in ASP.NET Core

Check this post for restricting IP Address in classic ASP.NET Web API

We will discuss the following in this post

  • What is Whitelist and Blacklist and how to configure and read it from appsettings.json
  • Writing a Middleware to implement IP Filtering
  • Recommended readings and courses

Whitelist vs Blacklist

To provide access or deny, we have to get the IP Address of the incoming request. We need to verify that against a list.  When I say list, you can use this list to grant or deny access.  If you use the list to grant access, it is called Whitelist else it is called Blacklist.

  • Whitelisting – Allow traffic only to known addresses
  • Blacklisting – Deny traffic to known addresses

For this example, I am going to use a whitelist of IP Address and use middleware to provide access only to the IP Address I have configured.  I have the list of IP Addresses stored in an array format inside “ApplicationOptions” in the appsettings.json. Alternatively, we can use a table-driven approach that allows the admin to add update entries easily.

{
  "Logging": {
    "LogLevel": {
      "Default": "Warning"
    }
  },
  "AllowedHosts": "*",

  "ApplicationOptions": {
    "Whitelist": [ "172.0.0.1", "::1" ]
  }
}

How to read values from appsettings.json?

The package Microsoft.Extensions.Options comes in handy for reading the values from appsettings.json and inject into the configuration class.  To do that we need to have a model class for ApplicationOptions and the ConfigureServices method of Startup class similar to the one below.

public void ConfigureServices(IServiceCollection services)
{
    // Inject Application Options
    services.Configure<ApplicationOptions>(Configuration.GetSection("ApplicationOptions"));
    services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
}
public class ApplicationOptions 
{ 
    public Lis<string> Whitelist { get; set; } 
}

What is middleware?

ASP.NET Core request pipeline consists of a series of request delegates that are chained together. The first one receives an HTTP request, does some processing, and gives the request to the next. However, at any point, a request delegate can decide to take action and process the request returning the response without passing to the next one.

Restrict IP Address - Request Delegate Pipeline
Source – Microsoft Docs

IP Filter Middleware:

Following is the code for the IP Filter Middleware

public class IPFilter
{
    private readonly RequestDelegate _next;
    private readonly ApplicationOptions _applicationOptions;
    public IPFilter(RequestDelegate next, IOptions<ApplicationOptions> applicationOptionsAccessor)
    {
        _next = next;
        applicationOptions = applicationOptionsAccessor.Value;
    }

    public async Task Invoke(HttpContext context)
    {
        var ipAddress = context.Connection.RemoteIpAddress;
        List<string> whiteListIPList = _applicationOptions.Whitelist;

        var isInwhiteListIPList = whiteListIPList
            .Where(a => IPAddress.Parse(a)
            .Equals(ipAddress))
            .Any();
        if (!isInwhiteListIPList)
        {
            context.Response.StatusCode = (int)HttpStatusCode.Forbidden;
            return;
        }
        await _next.Invoke(context);
    }
}

We have to write an extension method to add the middleware to the HTTP request pipeline

public static class MiddlewareExtensions
{
    public static IApplicationBuilder UseIPFilter(this IApplicationBuilder builder)
    {
        return builder.UseMiddleware<IPFilter>();
    }
}

Once we are done with the middleware and the extension, we have to register the middleware in the Configure method of Startup.cs

public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
    if (env.IsDevelopment())
    {
        app.UseDeveloperExceptionPage();
    }
    app.UseIPFilter();
    app.UseMvc();
}
 

Okay, now there are other questions 

  1. Do I need to enable this IP restriction for the entire application only?
  2. What if I want to restrict only for a certain controller or action?

Please refer the following link to enable authorization on controller or action level

Policy-based authorization in ASP.NET Core

Summary

This article tried to provide a summary of the very unique requirement of implementing security to Web API by IP Address.  We discussed the basic concepts, Middleware and an implementation example with ASP.NET Web API. 

The full implementation of this post can be found in Github

Recommended Courses

We may receive a commission for purchases made through these links.

Further Reading

You can refer to the following link if you want to learn more about Web API Security.

This Post Has 10 Comments

  1. fs

    Hello,
    very good contribution. I would like to know how a global blacklist and whitelist can be implemented for just a single controller. Can you help me with this?

    Thanks and kind regrds
    fs

  2. Chris S.

    Works fine when the Web API app is running locally, but why does this throw the HttpStatusCode 403 code when it’s published to Azure App Services?
    I have a separate Frontend application, which is currently running and being tested locally on a different port and it is receiving the 403 code. Debug logs in Azure are just stating that the request is forbidden.

    1. Admin

      The 403 (Forbidden) status code indicates that the server understood the request but refuses to authorize it. A 403 response is not a case of insufficient client credentials; that would be 401 (“Unauthorized”). REST APIs use 403 to enforce application-level permissions. For example, a client may be authorized to interact with some, but not all of a REST API’s resources. If the client attempts a resource interaction that is outside of its permitted scope, the REST API should respond with 403.

      Please refer
      https://stackoverflow.com/questions/3297048/403-forbidden-vs-401-unauthorized-http-responses
      https://stackoverflow.com/questions/50143518/401-unauthorized-vs-403-forbidden-which-is-the-right-status-code-for-when-the-u

  3. Mark Nadig

    Thanks for the article. Typo in ApplicationOptions.cs, missing T in List
    “public Lis Whitelist { get; set; } “

  4. Shahar Rave

    Thank you very much!
    I did find the extension method part a bit redundant and just skipped it and also you can just use “Any” with predicate, rather than “Where” and then “Any” but all in all, very helpful 🙂

  5. Anonymous

    Very good article, thank you 🙂

  6. Mostafa

    Very good article, thanks for sharing 🙂

  7. Mark Nadig

    Very helpful, thanks.

Leave a Reply