I am trying to restrict a site by IP address. In previous MVC versions I'd add something like the following to the web.config:
<security>
<ipSecurity allowUnlisted="false" denyAction="NotFound">
<add allowed="true" ipAddress="XX.XX.XX.XX" subnetMask="255.255.255.0"/>
</ipSecurity>
</security>
But adding this to a AspNetCore project causes the application to fails on startup with the error
Unable to start process The web server request failed with status code 500, internal server error
Evidently I broke the config as its not handled in here anymore. The error produces a HttpFailure log, which looks like:
What's the best way to handle this now, something built-in or otherwise
If you want to whitelist IP address ranges, then you can use the Nuget package IPAddressRange, which supports various formats such as "192.168. 0.0/24" and "192.168. 0.0/255.255. 255.0", including CIDR expressions and IPv6.
You'll probably want to check this for every request, which can be done either in the OnInit method of every page (that you want to block) or in the BeginRequest event of the application (typically in Global. asax ). If you detect a blocked address, you can output an empty (placeholder) page using Server.
ASP.NET Core security featuresASP.NET Core provides many tools and libraries to secure ASP.NET Core apps such as built-in identity providers and third-party identity services such as Facebook, Twitter, and LinkedIn. ASP.NET Core provides several approaches to store app secrets.
Damian Bod has made a blog post demonstrating how to implement middleware to handle IP whitelisting.
He gives examples of global middleware or action filter.
Either way you need to add permitted IP addresses to your appsettings.json
, and check the client IP address against them.
Client IP address is available via HttpContext
(e.g. context.Connection.RemoteIpAddress
).
If you want to whitelist IP address ranges, then you can use the Nuget package IPAddressRange, which supports various formats such as "192.168.0.0/24" and "192.168.0.0/255.255.255.0", including CIDR expressions and IPv6.
Here's an example of how to do that in a filter:
appsettings.json:
{
"IPAddressWhitelistConfiguration": {
"AuthorizedIPAddresses": [
"::1", // IPv6 localhost
"127.0.0.1", // IPv4 localhost
"192.168.0.0/16", // Local network
"10.0.0.0/16", // Local network
]
}
}
IPWhiteListConfiguration.cs:
namespace My.Web.Configuration
{
using System.Collections.Generic;
public class IPWhitelistConfiguration : IIPWhitelistConfiguration
{
public IEnumerable<string> AuthorizedIPAddresses { get; set; }
}
}
IIPWhiteListConfiguration.cs:
namespace My.Web.Configuration
{
using System.Collections.Generic;
public interface IIPWhitelistConfiguration
{
IEnumerable<string> AuthorizedIPAddresses { get; }
}
}
Startup.cs:
public class Startup
{
// ...
public void ConfigureServices(IServiceCollection services)
{
// ...
services.Configure<IPWhitelistConfiguration>(
this.Configuration.GetSection("IPAddressWhitelistConfiguration"));
services.AddSingleton<IIPWhitelistConfiguration>(
resolver => resolver.GetRequiredService<IOptions<IPWhitelistConfiguration>>().Value);
// ...
}
}
ClientIPAddressFilterAttribute.cs:
namespace My.Web.Filters
{
using System.Collections.Generic;
using System.Linq;
using System.Net;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Filters;
using NetTools;
using My.Web.Configuration;
public class ClientIPAddressFilterAttribute : ActionFilterAttribute
{
private readonly IEnumerable<IPAddressRange> authorizedRanges;
public ClientIPAddressFilterAttribute(IIPWhitelistConfiguration configuration)
{
this.authorizedRanges = configuration.AuthorizedIPAddresses
.Select(item => IPAddressRange.Parse(item));
}
public override void OnActionExecuting(ActionExecutingContext context)
{
var clientIPAddress = context.HttpContext.Connection.RemoteIpAddress;
if (!this.authorizedRanges.Any(range => range.Contains(clientIPAddress)))
{
context.Result = new UnauthorizedResult();
}
}
}
I needed something similar, except that "safelisting" a single IP Address wasn't good enough for me, because I had to enable a whole range of IP addresses through a CIDR notation (for Cloudflare). I blogged about it yesterday, but in short you can install the Firewall NuGet package and then configure IP filter settings like this:
namespace BasicApp
{
public class Startup
{
public void Configure(IApplicationBuilder app)
{
var allowedIPs =
new List<IPAddress>
{
IPAddress.Parse("10.20.30.40"),
IPAddress.Parse("1.2.3.4"),
IPAddress.Parse("5.6.7.8")
};
var allowedCIDRs =
new List<CIDRNotation>
{
CIDRNotation.Parse("110.40.88.12/28"),
CIDRNotation.Parse("88.77.99.11/8")
};
app.UseFirewall(
FirewallRulesEngine
.DenyAllAccess()
.ExceptFromIPAddressRanges(allowedCIDRs)
.ExceptFromIPAddresses(allowedIPs));
app.Run(async (context) =>
{
await context.Response.WriteAsync("Hello World!");
});
}
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With