A high‑performance NGINX module that lets you whitelist or blacklist client IP addresses using the Linux ipset kernel facility.
All look‑ups are made in userspace via libipset
and cached per worker thread to minimise overhead.
- Zero‑runtime overhead – IPSet sessions are initialised once and cached with thread‑local storage.
- Whitelist & Blacklist modes – block everything except the listed sets, or allow everything except the listed sets.
- Dynamic updates – modifying an
ipset
does not require an NGINX reload. - Native RPM packages for RHEL / Alma / Rocky and derivatives via GetPageSpeed repository.
┌ Client ──► NGINX worker
│ │
│ ├─► Thread‑local ipset session (libipset)
│ │ ├─ Test client IP against one or more sets
│ │ └─ Cache session handle for reuse
│ │
└─────────────┴── Allow / Deny based on match & mode
The module:
- Initialises
libipset
once per worker process. - Caches a session handle in POSIX thread‑specific data (
pthread_setspecific
). - Evaluates the client’s IPv4 address (
AF_INET
) against each configured set. - Returns 403 Forbidden (or custom code 444 when
blacklist
mode is selected and the IP matches).
- NGINX ≥ 1.22 (compiled with standard module API).
- Linux with ipset support (
nf_tables
oripset
kernel module). libipset
development headers at build‑time.
sudo dnf --assumeyes install https://extras.getpagespeed.com/release-latest.rpm
sudo dnf --assumeyes install nginx-module-ipset-access
Tip: The package is signed; make sure you have
gpgcheck=1
enabled.
Enable the module in /etc/nginx/nginx.conf
before any http {}
blocks:
load_module modules/ngx_http_ipset_access.so;
Reload NGINX to apply:
sudo systemctl reload nginx
# Install build dependencies
sudo dnf group install --assumeyes "Development Tools"
sudo dnf --assumeyes install libipset-devel pcre2-devel zlib-devel openssl-devel
# Clone NGINX and the module
git clone https://github.com/nginx/nginx.git
git clone https://example.com/ngx_ipset_access.git
cd nginx
./auto/configure --with-compat --add-dynamic-module=../ngx_ipset_access
make -j$(nproc)
sudo make install
The build produces objs/ngx_http_ipset_access.so
; copy it to your NGINX modules directory and add load_module
as shown above.
Context: http
, server
Blocks requests if the client IP appears in any of the listed ipset(s).
Context: http
, server
Allows requests only if the client IP appears in a listed set. All other IPs are rejected.
Either directive accepts the literal word off
to disable processing for the current context:
server {
listen 80;
blacklist off; # no ipset filtering in this virtual‑host
}
# Create an ipset of blocked addresses
sudo ipset create bad_guys hash:ip
sudo ipset add bad_guys 203.0.113.4
sudo ipset add bad_guys 198.51.100.23
load_module modules/ngx_http_ipset_access.so;
http {
# Block any IP found in "bad_guys"
blacklist bad_guys;
server {
listen 80 default_server;
root /usr/share/nginx/html;
}
}
Because look‑ups are live, adding or removing IPs from bad_guys
takes effect instantly without reloading NGINX.
Build NGINX with --with-debug
and set error_log /var/log/nginx/error.log debug;
to see verbose output such as:
test bad_guys 203.0.113.4 -> IPS_TEST_IS_IN_SET
Blocking 203.0.113.4 due to IPSET
Mode | IP match result | HTTP status |
---|---|---|
whitelist |
Not in any set | 403 |
blacklist |
In a configured set | 403 (module can be patched to 444) |
Any | Error contacting ipset | 403 (treated as deny for safety) |
- IPv4 only –
AF_INET6
is not yet supported. - Uses synchronous libipset calls; at very high request rates the kernel may be faster with
nft set
rules alone. - Custom return status 444 is prepared but commented; enable if you need drop‑without‑reply semantics.
- Fork the repository
- Create a feature branch
- Submit a pull‑request following the GitHub Flow.
Please run clang-format
before committing.
MIT – see LICENSE
.
Mohammad Mahdi Roozitalab [email protected]
RPM packaging & documentation maintained by GetPageSpeed.