Service Registration
Two things must be wired up: the policy provider (a singleton service that holds the parsed policies) and the middleware (added to YARP's pipeline).
AddIPFilterPolicies() — from configuration
The common path binds the IPFilterConfiguration section from your IConfiguration:
builder.Services.AddIPFilterPolicies(builder.Configuration);
The section name defaults to "IPFilterConfiguration". Pass a different name if you keep the policies elsewhere:
builder.Services.AddIPFilterPolicies(builder.Configuration, configSectionName: "MyIpFilters");
This registers IIPFilterPolicyProvider (implemented by IPFilterPolicyProvider) as a singleton and binds IPFilterPoliciesConfiguration via the options system, so configuration reloads are picked up at runtime.
AddIPFilterPolicies() — from code
To build policies imperatively instead of from configuration, pass a configuration action:
builder.Services.AddIPFilterPolicies(policies =>
{
policies.Add(new IPFilterPolicy
{
PolicyName = "Intranet",
Mode = IPFilterPolicyMode.AllowList,
IPNetworks = ["192.168.0.0/24"]
});
});
See Advanced for the full programmatic setup, including the global policy.
UseIPFilterPolicies() — the middleware
Register the middleware inside MapReverseProxy:
app.MapReverseProxy(proxyPipeline =>
{
proxyPipeline.UseIPFilterPolicies();
proxyPipeline.UseLoadBalancing();
});
Important:
UseIPFilterPolicies()extends YARP'sIReverseProxyApplicationBuilder. Do not add the middleware to the regular ASP.NET Core pipeline (app.UseMiddleware<...>()) — it reads the current route from the YARP reverse-proxy feature, which is only present insideMapReverseProxy. Adding it first means blocked requests are rejected before load balancing, session affinity, or transforms run.
The IPFilterConfiguration section
{
"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"]
},
{
"PolicyName": "TestPolicy",
"Mode": "Disabled",
"IPAddresses": ["192.168.0.3", "192.168.0.4"],
"IPNetworks": ["192.168.0.0/24"]
}
]
}
}
Top-level keys
| Key | Type | Default | Description | ||
|---|---|---|---|---|---|
Policies | array | [] | The list of policies. Each PolicyName must be unique — the provider indexes policies by name. | ||
EnableGlobalPolicy | bool | false | When true, the policy named by GlobalPolicyName is evaluated for every request before route-specific policies. See Global Policy. | ||
GlobalPolicyName | string | "Global" | The name of the policy used as the global policy when EnableGlobalPolicy is true. |
When
EnableGlobalPolicyistruebut no policy matchesGlobalPolicyName, the provider throws at startup (and on every reload). Either add the matching policy or setEnableGlobalPolicytofalse.
Policy keys
| Key | Type | Default | Description | ||
|---|---|---|---|---|---|
PolicyName | string | "DefaultPolicy" | Unique name used to reference the policy from route metadata or as the global policy. | ||
Mode | enum | AllowList | Disabled, AllowList, or BlockList. See Policies. | ||
IPAddresses | array | [] | Individual IP addresses (IPv4 or IPv6). | ||
IPNetworks | array | [] | CIDR networks, e.g. "192.168.0.0/24". |
IPAddresses and IPNetworks may be used together in a single policy — a request matches the policy if it matches either list. See Policies for exactly how each mode interprets a match.
Logging
The middleware logs through Microsoft.Extensions.Logging. It uses the high-performance LoggerMessage pattern on the request-handling path, with these events:
| Event ID | Level | When | ||
|---|---|---|---|---|
1001 RequestBlockedGlobal | Warning | A request was blocked by the global policy. | ||
1002 NoIPPolicyFound | Debug | The route has no IPFilterPolicy metadata; middleware is bypassed. | ||
1003 PolicyIsNull | Critical | A route references a policy name that does not exist. | ||
1004 PolicyIsDisabled | Information | The referenced policy is in Disabled mode; request passes through. | ||
1005 RequestBlocked | Warning | A request was blocked by a route-specific policy. | ||
1006 RequestAllowed | Information | A request was allowed by a route-specific policy. |
Configure levels per category as you would for any ASP.NET Core app:
{
"Logging": {
"LogLevel": {
"BBelius.Yarp.ReverseProxy.IPFilters": "Information"
}
}
}