Nginx配置IP地址的动态黑名单
本节介绍如何创建特定客户端IP地址的黑名单或白名单,拒绝或允许它们访问您的站点以及如何动态维护地址列表。
总览
在NGINX Plus 版本13(R13)和更高版本中,您可以将某些IP地址列入黑名单,以及创建和维护列入黑名单的IP地址的数据库。您还可以将其他IP地址明确列入白名单。IP地址数据库由NGINX Plus API和keyval模块管理。
在NGINX Plus 版本19(R19)中,通过将IP地址与子网或网络范围内的任何地址进行匹配来扩展此功能。
先决条件
NGINX Plus 版本13或更高版本,NGINX Plus 版本19,用于网络范围支持。
设定
首先,启用数据库以存储列入黑名单和白名单的IP地址列表。
-
在NGINX Plus配置文件中,
keyval_zone
在http
上下文中包含指令以创建用于存储键和值的存储区。此示例指令创建一个1 MB的区域称为一个。http { # ... keyval_zone zone=one:1m; }
要对子网进行IP地址匹配(例如
192.168.13.0/24
),请指定伪指令的type=ip
参数keyval_zone
:http { # ... keyval_zone zone=one:1m type=ip; }
请注意,
keyval_zone
还应增加的大小,因为该type=ip
参数还会启用存储在区域中的额外索引。您可以选择包含该
state
参数来创建一个文件,该文件存储了键值数据库,因此在NGINX Plus重新加载和重新启动后仍然存在;在此示例中,one.keyval:keyval_zone zone=one:1m state=one.keyval;
-
使用以下
api
指令以读写模式启用NGINX Plus API :# ... server { listen 80; server_name www.example.com; location /api { api write=on; } }
我们强烈建议限制访问到这个位置,例如通过只允许从接入
localhost
(127.0.0.1
),并通过限制访问PATCH
,POST
和DELETE
方法向某些用户以HTTP基本身份验证:# ... server { listen 80; server_name www.example.com; location /api { limit_except GET { auth_basic "NGINX Plus API"; auth_basic_user_file /path/to/passwd/file; } api write=on; allow 127.0.0.1; deny all; } }
-
使用API的
POST
方法填充键值数据库,并以JSON格式提供数据。您可以使用curl
以下示例中的命令。如果区域为空,则可以一次输入多个键值对;否则,必须一次添加一对。$ 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/5/http/keyvals/one In case you have specified matching an IP address against network ranges (t
如果您已指定IP地址与网络范围匹配(伪指令的
type=ip
参数keyval_zone
,请发送带有网络范围的POST命令。该范围必须以CIDR表示法指定:$ curl -X POST -d '{ "192.168.13.0/24": "1" }' -s http://www.example.com/api/5/http/keyvals/one
-
通过将
keyval
指令包括在http
上下文中,定义如何根据键值数据库评估客户端IP地址。该指令利用标准的NGINX和NGINX Plus变量
$remote_addr
,该变量会为每个请求自动设置为客户端IP地址。在处理每个请求时,NGINX Plus:
$remote_addr
在由zone=
参数指定的键值数据库(此处为一个)中查找第一个参数(此处为,预设为客户端的IP地址)。- 如果数据库中的某个键完全匹配
$remote_addr
,则将第二个参数(此处为$target
)设置为与该键对应的值。在我们的示例中,该值1
用于列入黑名单的地址或0
列入白名单的地址。
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; }
-
使用
if
指令根据客户端IP地址创建允许或拒绝访问的规则。使用此规则,访问是在被允许时被允许,而在$target
被访问时被0
拒绝1
:if ($target) { return 403; }
管理键值数据库
您可以使用API方法即时更新键值数据库,而无需重新加载NGINX Plus。
以下所有示例均在一个区域中进行操作,可从http://www.example.com/api/5/http/keyvals/one访问该区域。
-
要获取区域的所有数据库条目的列表:
$ curl -X GET 'http://www.example.com/api/5/http/keyvals/one'
-
要更新现有条目的值(在本示例中,将IP地址的访问状态
10.0.0.4
从白名单更改为黑名单):$ curl -X PATCH -d '{"10.0.0.4": "1"}' -s 'http://www.example.com/api/5/http/keyvals/one'
-
要将条目添加到填充区域:
$ curl -X POST -d '{"10.0.0.5": "1"}' -s 'http://www.example.com/api/5/http/keyvals/one'
-
删除条目:
$ curl -X PATCH -d '{"10.0.0.4":null}' -s 'http://www.example.com/api/5/http/keyvals/one'
完整的例子
完整的NGINX Plus配置:
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 {
limit_except GET {
auth_basic "NGINX Plus API";
auth_basic_user_file /path/to/passwd/file;
}
api write=on;
allow 127.0.0.1;
deny all;
}
if ($target) {
return 403;
}
}
}
此配置:
- 创建一个1 MB KEYVAL区一个接受网络范围,并创建文件one.keyval使整个重载和NGINX加的重启键-值对仍然存在的数据库。
- 在写入模式下启用NGINX Plus API,以便可以使用IP地址填充区域
- 启用
$remote_addr
在键值数据库中查找IP地址作为键的功能,并将找到的键的值放入$target
变量中。 - 启用一条简单的规则来检查结果值:如果
$target
is 的值1
(地址被列入黑名单),则返回到客户端。403 (Forbidden)
以下curl
命令填充空KEYVAL区一个与被列入黑名单(值是IP地址1
)或白名单中(值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/5/http/keyvals/one'