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, we will see how to restrict IP addresses in ASP.NET Web API.
Check this Post for restricting IP Addresss in ASP.NET Core Web API
We will discuss the following in this post
- How to get the incoming IP Address
- What are Whitelist and Blacklist
- Writing a Handler to implement IP Filtering
- Recommended readings and courses
Get the incoming IP address:
Let’s built an extension method for HttpRequestMessage
to retrieve the IP address. The method for getting the IP address from the request varies depends on the hosting method. The following method gets the IP address from the request message. It works with the following hosting methods.
- OWIN Hosting
- Web Hosting
- Self Hosting
public static string GetIP(this HttpRequestMessage requestMessage)
{
// Owin Hosting
if (requestMessage.Properties.ContainsKey("MS_OwinContext"))
{
return HttpContext.Current != null ? HttpContext.Current.Request.GetOwinContext()
.Request.RemoteIpAddress : null;
}
// Web Hosting
if (requestMessage.Properties.ContainsKey("MS_HttpContext"))
{
return HttpContext.Current != null ? HttpContext.Current.Request.UserHostAddress : null;
}
// Self Hosting
if (requestMessage.Properties.ContainsKey(RemoteEndpointMessageProperty.Name))
{
RemoteEndpointMessageProperty property =
(RemoteEndpointMessageProperty)requestMessage .Properties[RemoteEndpointMessageProperty.Name];
return property != null ? property.Address : null;
}
return null;
}
Whitelist vs Blacklist
Now we have the IP address of the incoming request. We need to verify this 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 – Allow all traffic and block only known addresses
For this example, I am going to use a whitelist of IP Address. I have stored the IP Address in CSV format on the web.config. Alternatively, we can use a table-driven approach that allows the admin to add update entries easily.
<add key="WhiteListedIPAddresses" value="10.278.210.22,10.89.65.231" />
Validate incoming IP against the Whitelist
I have another extension method on HttpRequestMessage
to verify whether the IP address of the incoming request is whitelisted.
public static bool AllowIP(this HttpRequestMessage request)
{
var whiteListedIPs = ConfigurationManager.AppSettings["WhiteListedIPAddresses"];
if (!string.IsNullOrEmpty(whiteListedIPs))
{
var whiteListIPList = whiteListedIPs.Split(',').ToList();
var ipAddressString = request.GetIP();
var ipAddress = IPAddress.Parse(ipAddressString);
var isInwhiteListIPList =
whiteListIPList
.Where(a => a.Trim()
.Equals(ipAddressString, StringComparison.InvariantCultureIgnoreCase))
.Any();
return isInwhiteListIPList;
}
return true;
}
The above method reads the whitelisted IPs from the config file and verifies whether the incoming IP is on the list.
You can also store a range of IP addresses or an IP address with CIDR in the web.config to allow/deny access to multiple IP addresses. Please refer to this to link for more operations related to IP addresses.
Now we have the whitelisted IPs in the web.config and built the extension methods to read the IP address from request and validate it against the whitelist. How can we put this into action?
Create the Handler
Delegating handlers are used in Web API to represent Message Handlers before routing. Typically, a series of message handlers are chained together. The first handler receives an HTTP request, does some processing, and gives the request to the next handler. However, at any point, a handler can decide to take action and process the request returning the response without passing to the next one. Before we start creating the handler, please refer the following to know more about handler.
HTTP Message Handlers in ASP.NET Web API
public class IPFilterHandler : DelegatingHandler
{
protected override async Task SendAsync(HttpRequestMessage request,
CancellationToken cancellationToken)
{
if (request.AllowIP())
{
return await base.SendAsync(request, cancellationToken);
}
return request
.CreateErrorResponse(HttpStatusCode.Unauthorized
, "Not authorized to view/access this resource");
}
}
In the SendAsync method, the handler checks whether the IP address of the request is whitelisted. If so, it calls base.SendAsync to pass the message to the next handler. If not, it processes the request and returns an unauthorized error response with a custom message.
Register the Handler
To register a message handler on the server-side, add the handler to HttpConfiguration.MessageHandlers
collection in WebApiConfig
.
public static class WebApiConfig
{
public static void Register(HttpConfiguration config)
{
config.MapHttpAttributeRoutes();
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional });
config.MessageHandlers.Add(new IPFilterHandler());
}
}
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, Handler and an implementation example with ASP.NET Web API.
Recommended Courses
- RESTful API with ASP.NET Core Web API – Create and Consume
- Step-By-Step: Create Web API Using ASP.Net Core
- Learn Restful Api’s with .Net Core
- Beyond Basics: RESTful API with ASP.NET Core 3.0 and EF Core
- Designing RESTful Web APIs
- Documenting an ASP.NET Core API with OpenAPI / Swagger
- Using OpenAPI/Swagger for Testing and Code Generation in ASP.NET Core
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.
Pingback: Restrict IP Address ASP.NET Core Web API - Blog of Pi
Then sendasync method should return Task like:
protected override async Task SendAsync(HttpRequestMessage request, cancellationToken cancellationToken)
https://docs.microsoft.com/en-us/dotnet/api/system.net.http.delegatinghandler.sendasync?view=netframework-4.7.2
Thank you, this was helpful!