This section describes how to create a denylist or allowlist of specific client IP addresses, which denies or allows them access to your site, and how to dynamically maintain the list of addresses.
In F5 NGINX Plus Release 13 (R13) and later, you can denylist some IP addresses as well as create and maintain a database of denylisted IP addresses. You can also explicitly allowlist other IP addresses. The IP addresses database is managed with the NGINXÂ Plus API and keyval modules.
NGINXÂ Plus Release 19 extends this capability by matching an IP address to any address within a subnet or network range.
NGINXÂ Plus Release 13 and later, NGINXÂ Plus Release 19 and later for network ranges support.
First, enable the database for storing the list of denylisted and allowlisted IP addresses.
In NGINXÂ Plus configuration file, include the keyval_zone directive in the http context to create a memory zone for storing keys and values. This sample directive creates a 1âMB zone called one.
nginxhttp {
# ...
keyval_zone zone=one:1m;
}
http {
# ...
keyval_zone zone=one:1m;
}
To perform matching of an IP address against subnets (for example, 192.168.13.0/24
), specify the type=ip
parameter of the keyval_zone directive:
http {
# ...
keyval_zone zone=one:1m type=ip;
}
http {
# ...
keyval_zone zone=one:1m type=ip;
}
Note that the size of keyval_zone should also be increased as the type=ip
parameter also enables an extra index stored in the zone.
You can optionally include the state
parameter to create a file where the keyâvalue database is stored and so persists across NGINXÂ Plus reloads and restarts; in this example, one.keyval:
keyval_zone zone=one:1m state=one.keyval;
keyval_zone zone=one:1m state=one.keyval;
Enable the NGINXÂ Plus API in readâwrite mode with the api directive:
nginx# ...
server {
listen 80;
server_name www.example.com;
location /api {
api write=on;
}
}
# ...
server {
listen 80;
server_name www.example.com;
location /api {
api write=on;
}
}
We strongly recommend restricting access to this location, for example by allowing access only from localhost
(127.0.0.1
), and by using HTTP basic authentication to restrict use of the PATCH
, POST
, and DELETE
methods to a specified set of users:
# ...
server {
listen 80;
server_name www.example.com;
location /api {
api write=on;
allow 127.0.0.1;
deny all;
limit_except GET {
auth_basic "NGINX Plus API";
auth_basic_user_file /path/to/passwd/file;
}
}
}
# ...
server {
listen 80;
server_name www.example.com;
location /api {
api write=on;
allow 127.0.0.1;
deny all;
limit_except GET {
auth_basic "NGINX Plus API";
auth_basic_user_file /path/to/passwd/file;
}
}
}
Populate the keyâvalue database with the API’s POST method, supplying the data in JSON format. You can use the curl
command as in the following example. If the zone is empty, you can enter several keyâvalue pairs at once; otherwise, pairs must be added one at a time.
$ curl -X POST -d '{
"10.0.0.1": "1",
"10.0.0.2": "1",
"10.0.0.3": "0",
"10.0.0.4": "0"
}' -s http://www.example.com/api/6/http/keyvals/one
$ curl -X POST -d '{
"10.0.0.1": "1",
"10.0.0.2": "1",
"10.0.0.3": "0",
"10.0.0.4": "0"
}' -s http://www.example.com/api/6/http/keyvals/one
If you have specified matching of IP addresses against network ranges (with the type=ip
parameter of the keyval_zone directive), send the POST
command with the network range specified in CIDR notation:
$ curl -X POST -d '{
"192.168.13.0/24": "1"
}' -s http://www.example.com/api/6/http/keyvals/one
$ curl -X POST -d '{
"192.168.13.0/24": "1"
}' -s http://www.example.com/api/6/http/keyvals/one
Define how client IP addresses are evaluated against the keyâvalue database, by including the keyval directive in the http context.
The directive takes advantage of the standard NGINX and NGINXÂ Plus variable $remote_addr
, which is set to the client IP address automatically for every request.
As it processes each request, NGINXÂ Plus:
Looks up the first parameter (here, $remote_addr
, preset to the client’s IP address) in the keyâvalue database specified by the zone=
parameter (here, one).
If a key in the database exactly matches $remote_addr
, sets the second parameter (here, $target
) to the value corresponding to the key. In our example, the value is 1
for denylisted addresses or 0
for allowlisted addresses.
http {
# ...
keyval_zone zone=one:1m type=ip state=one.keyval;
keyval $remote_addr $target zone=one; # Client address is the key,
# $target is the value;
}
http {
# ...
keyval_zone zone=one:1m type=ip state=one.keyval;
keyval $remote_addr $target zone=one; # Client address is the key,
# $target is the value;
}
Create a rule with the if directive that either allows or denies access depending on the client IP address. With this rule, access is allowed when $target
is 0
and denied when it is 1
:
if ($target) {
return 403;
}
if ($target) {
return 403;
}
Managing the Key-Value Database
You can use API methods to update a keyâvalue database dynamically, without requiring a reload of NGINXÂ Plus.
All of the following examples operate on the one zone, which is accessible at http://www.example.com/api/6/http/keyvals/one.
To get the list of all database entries for a zone:
curl -X GET 'http://www.example.com/api/6/http/keyvals/one'
curl -X GET 'http://www.example.com/api/6/http/keyvals/one'
To update the value for an existing entry (in this example to change the access status for IP address 10.0.0.4
from allowlisted to denylisted):
curl -X PATCH -d '{"10.0.0.4": "1"}' -s 'http://www.example.com/api/6/http/keyvals/one'
curl -X PATCH -d '{"10.0.0.4": "1"}' -s 'http://www.example.com/api/6/http/keyvals/one'
To add an entry to a populated zone:
curl -X POST -d '{"10.0.0.5": "1"}' -s 'http://www.example.com/api/6/http/keyvals/one'
curl -X POST -d '{"10.0.0.5": "1"}' -s 'http://www.example.com/api/6/http/keyvals/one'
To delete an entry:
curl -X PATCH -d '{"10.0.0.4":null}' -s 'http://www.example.com/api/6/http/keyvals/one'
curl -X PATCH -d '{"10.0.0.4":null}' -s 'http://www.example.com/api/6/http/keyvals/one'
The full NGINXÂ Plus configuration:
nginxhttp {
# ...
keyval_zone zone=one:1m type=ip state=one.keyval;
keyval $remote_addr $target zone=one;
server {
listen 80;
server_name www.example.com;
location /api {
api write=on;
allow 127.0.0.1;
deny all;
limit_except GET {
auth_basic "NGINX Plus API";
auth_basic_user_file /path/to/passwd/file;
}
}
if ($target) {
return 403;
}
}
}
http {
# ...
keyval_zone zone=one:1m type=ip state=one.keyval;
keyval $remote_addr $target zone=one;
server {
listen 80;
server_name www.example.com;
location /api {
api write=on;
allow 127.0.0.1;
deny all;
limit_except GET {
auth_basic "NGINX Plus API";
auth_basic_user_file /path/to/passwd/file;
}
}
if ($target) {
return 403;
}
}
}
This configuration:
Creates a 1Â MB keyval zone one that accepts network ranges and also creates the file one.keyval to make the database of keyâvalue pairs persists across reloads and restarts of NGINXÂ Plus.
Enables the NGINXÂ Plus API in write mode so that the zone can populated with IP addresses.
Enables lookup of the IP address $remote_addr
in the key-value database as the key, and puts the value of the found key into the $target
variable.
Enables a simple rule to check for the resulting value: if the value of $target
is 1
(address is denylisted), return 403 (Forbidden)
to the client.
The following curl
command populates the empty keyval zone one with IP addresses that are denylisted (value is 1
) or allowlisted (value is 0
):
curl -X POST -d '{
"10.0.0.1": "1",
"192.168.13.0/24": "1",
"10.0.0.3": "0",
"10.0.0.4": "0"
}' -s 'http://www.example.com/api/6/http/keyvals/one'
curl -X POST -d '{
"10.0.0.1": "1",
"192.168.13.0/24": "1",
"10.0.0.3": "0",
"10.0.0.4": "0"
}' -s 'http://www.example.com/api/6/http/keyvals/one'
RetroSearch is an open source project built by @garambo | Open a GitHub Issue
Search and Browse the WWW like it's 1997 | Search results from DuckDuckGo
HTML:
3.2
| Encoding:
UTF-8
| Version:
0.7.4