YARP IP Filters

YARP IP Filters

IP filtering middleware for Microsoft YARP

NuGet
License: MIT

A customizable IP filtering middleware for Microsoft's YARP (Yet Another Reverse Proxy) that provides fine-grained control over allowed or blocked IP addresses globally and per-route, ensuring secure and flexible access management.

Features

  • Global IP filtering — a single policy evaluated for every proxied request before route-specific rules
  • Route-specific policies — attach a named policy to any YARP route via route metadata
  • Allowlist and blocklist modes — allow only known IPs, or block known-bad IPs
  • IP address and CIDR network matching — mix individual addresses and network ranges in one policy
  • Dynamic reload — configuration changes are picked up at runtime without a restart
  • Fast lookupsHashSet for addresses and a trie-based collection for networks on the critical path
  • Built-in tracing — an ActivitySource emits a span per evaluation

Installation

Install the package via NuGet:

dotnet add package BBelius.Yarp.ReverseProxy.IPFilters

The package targets .NET 8 and .NET 9 and depends on Yarp.ReverseProxy 2.x.

Quick Start

1. Register the policy provider

Add the IP filter policy provider to your DI container, binding it from configuration:

using BBelius.Yarp.ReverseProxy.IPFilters;

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddReverseProxy()
    .LoadFromConfig(builder.Configuration.GetSection("ReverseProxy"));

builder.Services.AddIPFilterPolicies(builder.Configuration);

2. Add the middleware to the YARP pipeline

Register the middleware inside MapReverseProxy. Add it before any other YARP middleware so blocked requests are rejected as early as possible.

var app = builder.Build();

app.MapReverseProxy(proxyPipeline =>
{
    proxyPipeline.UseIPFilterPolicies();
    proxyPipeline.UseLoadBalancing();
});

app.Run();

Important: Add the middleware to YARP's middleware pipeline via UseIPFilterPolicies()not to the regular ASP.NET Core request pipeline. It requires access to the YARP HttpContext route feature, which is only available inside MapReverseProxy. See the YARP middleware documentation.

3. Configure policies

Define your policies in appsettings.json:

{
  "IPFilterConfiguration": {
    "EnableGlobalPolicy": true,
    "GlobalPolicyName": "Global",
    "Policies": [
      {
        "PolicyName": "Global",
        "Mode": "BlockList",
        "IPAddresses": ["192.168.0.3", "192.168.0.4"]
      },
      {
        "PolicyName": "Intranet",
        "Mode": "AllowList",
        "IPNetworks": ["192.168.0.0/24"]
      }
    ]
  }
}

4. Attach policies to routes

Reference a policy by name in a route's Metadata:

{
  "ReverseProxy": {
    "Routes": [
      {
        "RouteId": "route1",
        "ClusterId": "cluster1",
        "Match": { "Path": "/{**catch-all}" },
        "Metadata": { "IPFilterPolicy": "Intranet" }
      }
    ]
  }
}

Documentation

TopicDescription
ConfigurationService registration and the IPFilterConfiguration section
PoliciesPolicy modes, IP address and CIDR network matching
Route ConfigurationAttaching policies to YARP routes via metadata
Global PolicyThe global policy evaluated for every request
TracingThe ActivitySource and emitted span tags
AdvancedProgrammatic configuration, dynamic reload, custom providers

How it works

For each proxied request the middleware:

  1. Resolves the client IP from HttpContext.Connection.RemoteIpAddress (IPv4-mapped IPv6 addresses are

normalised back to IPv4).

  1. If a global policy is enabled and the IP is not allowed by it, responds 403 Forbidden

and stops.

  1. Reads the IPFilterPolicy key from the current route's metadata. If absent, the request passes straight through.
  2. Looks up the named policy. A Disabled policy passes through; otherwise the IP is matched

against the policy's addresses and networks in the configured mode.

  1. Allowed requests continue down the pipeline; blocked requests get 403 Forbidden.

A referenced-but-missing policy is a configuration error: the middleware logs a critical event, responds 500 Internal Server Error, and throws IPFilterPolicyNotFoundException.

License

Licensed under the MIT License. Contributions are welcome — open an issue or submit a pull request on GitHub.