[os-nginx] Add native Layer-7 enforcement of the autoblock/banned IP list behind trusted reverse proxies/CDNs
Nobody has claimed this yet.
- Dominant language
- PHP
- Stars
- 1.2k
- Forks
- 863
- Avg merge
- 2d 6h
- Merged PRs (30d)
- 10
Description
Important notices
Before you add a new report, we ask you kindly to acknowledge the following:
- I have read the contributing guide lines at https://github.com/opnsense/plugins/blob/master/CONTRIBUTING.md
- I have searched the existing issues, open and closed, and I'm convinced that mine is new.
- When the request is meant for an existing plugin, I've added its name to the title.
Is your feature request related to a problem? Please describe.
Yes.
The os-nginx autoblock/permanent-ban functionality can detect an offending client and add its IP address to the existing Nginx Banned list and nginx_autoblock PF table.
This works well when clients connect directly to OPNsense, because PF sees the actual client IP as the TCP source.
However, when os-nginx is used behind a trusted reverse proxy or CDN such as Cloudflare, PF only sees the proxy/CDN address as the TCP source.
Nginx itself can correctly restore the real client IP, for example using:
real_ip_header CF-Connecting-IP;
set_real_ip_from <trusted proxy networks>;
After real-IP processing Nginx therefore knows the real attacking client IP, and that real IP can correctly end up in the existing OPNsense Nginx Banned list.
The problem is that PF still cannot enforce the ban against that restored client IP, because the underlying TCP connection originates from the CDN/reverse proxy.
Adding the restored client IP to a PF table therefore does not block the proxied connection. Blocking the CDN address instead is not acceptable because one CDN address can serve many unrelated visitors.
This creates a Layer-3 / Layer-7 enforcement gap for os-nginx deployments behind trusted reverse proxies or CDNs.
Describe the solution you'd like
I would like an optional native Nginx Layer-7 enforcement mechanism for the existing os-nginx banned/autoblock list.
For example:
- Generate an Nginx
geoormapfrom the existing active Nginx banned IP entries. - Respect the existing
ban_ttl. - Enforce the ban against
$remote_addrafter trusted real-IP processing. - Keep the existing PF
nginx_autoblockmechanism for direct connections. - Make Layer-7 enforcement optional.
- Allow enforcement globally or on selected HTTP server objects.
- Allow an optional trusted/exempt ACL, for example management LAN or VPN networks.
- Support both IPv4 and IPv6 entries.
- Reload Nginx only when the effective ban list changes.
A possible GUI implementation could be similar to:
[ ] Enforce banned IPs inside Nginx (Layer 7)
Scope: [All enabled HTTP servers / Selected HTTP servers]
Exempt ACL: [optional ACL]
This would also make it possible for one central os-nginx ban to be enforced across multiple public virtual hosts, even when requests arrive through a trusted reverse proxy/CDN.
Describe alternatives you've considered
- Existing PF
nginx_autoblock
This works correctly for clients connecting directly to OPNsense, but cannot match a restored Layer-7 client IP when the TCP source is a CDN/reverse proxy.
- Blocking the CDN/reverse-proxy address
This is not appropriate because a single proxy address can serve many unrelated visitors.
- CDN-specific API blocking
For example, Cloudflare API/WAF rules could be used, but this is vendor-specific and duplicates ban state that os-nginx already maintains.
- Custom Nginx include hooks
I tested a working workaround using the existing os-nginx include hooks, an Nginx geo map, a small synchronization script, the existing ban_ttl, and trusted-network exemptions.
The workaround works, but native os-nginx support would be preferable because OPNsense could manage its lifecycle, configuration regeneration, server selection and exemptions.
Additional context
I tested the Layer-7 approach successfully with os-nginx behind Cloudflare.
The tested flow was:
malicious request
->
os-nginx detects the request
->
real client IP enters the existing OPNsense Nginx Banned list
->
active bans are made available to an Nginx geo map
->
restored client IP is rejected inside Nginx
->
HTTP 403 on all selected public virtual hosts
The test confirmed that:
- the actual client IP was banned instead of a Cloudflare edge IP;
- the same banned client was subsequently blocked on other public os-nginx virtual hosts;
- Cloudflare addresses themselves were not blocked;
- unlocking the IP through Services -> Nginx -> Banned restored access after synchronization;
- IPv4 and IPv6 entries can be handled by the Nginx geo mechanism.
This request does not need to replace the current PF autoblock mechanism. Layer-7 enforcement could be an additional option specifically useful for trusted reverse-proxy/CDN deployments.
This is related to, but different from #4294. That issue concerns CrowdSec bouncers behind Cloudflare. This request is specifically about enforcing the existing native os-nginx autoblock/banned-IP list inside Nginx.
Replaces #5661, which was closed and recreated using the official Feature Request template at the request of OPNsense-bot.
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start by tracing the existing os-nginx Nginx Banned list, autoblock/PF handling, and include hooks, then review how the existing ban_ttl is exposed. Define the native geo or map synchronization, trusted-network exemptions, server scope, and reload behavior; done means restored IPv4 and IPv6 client addresses are blocked on selected hosts without blocking proxy addresses, while direct PF enforcement remains intact.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- nginx
- Domain
- devops, networking, security
- Issue type
- Feature
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Active
- Clarity
- Mostly clear
- Newbie friendliness
- 35/100