Nginx R31 doc-14-Dynamic Denylisting of IP Addresses 动态拒绝IP地址

前言

大家好,我是老马。很高兴遇到你。

我们为 java 开发者实现了 java 版本的 nginx

github.com/houbb/nginx...

如果你想知道 servlet 如何处理的,可以参考我的另一个项目:

手写从零实现简易版 tomcat minicat

手写 nginx 系列

如果你对 netty 不是很熟悉,可以读一下

从零手写实现 nginx-01-为什么不能有 java 版本的 nginx?

从零手写实现 nginx-02-nginx 的核心能力

从零手写实现 nginx-03-nginx 基于 Netty 实现

从零手写实现 nginx-04-基于 netty http 出入参优化处理

从零手写实现 nginx-05-MIME类型(Multipurpose Internet Mail Extensions,多用途互联网邮件扩展类型)

从零手写实现 nginx-06-文件夹自动索引

从零手写实现 nginx-07-大文件下载

从零手写实现 nginx-08-范围查询

从零手写实现 nginx-09-文件压缩

动态拒绝IP地址

使用NGINX Plus的键值存储和API,您可以控制特定客户端IP地址对站点或应用程序的访问权限,创建和维护IP地址的动态拒绝列表或允许列表。

概述

在NGINX Plus Release 13(R13)及更高版本中,您可以拒绝一些IP地址,并创建和维护一个包含拒绝IP地址的数据库。

您还可以明确地允许其他IP地址。IP地址数据库通过NGINX Plus API和keyval模块进行管理。

NGINX Plus Release 19(R19)通过将IP地址与子网或网络范围中的任何地址进行匹配,扩展了此功能。

先决条件

NGINX Plus Release 13及更高版本,NGINX Plus Release 19及更高版本支持网络范围。

设置

首先,启用用于存储拒绝和允许的IP地址列表的数据库。

在NGINX Plus配置文件中,在http上下文中包含keyval_zone指令,以创建一个用于存储键和值的内存区域。此示例指令创建了一个名为one的1兆字节区域。

nginx 复制代码
http {
    # ...
    keyval_zone zone=one:1m;
 }

要执行IP地址与子网(例如,192.168.13.0/24)的匹配,请指定keyval_zone指令的type=ip参数:

nginx 复制代码
http {
    # ...
    keyval_zone zone=one:1m type=ip;
 }

请注意,由于type=ip参数还在区域中启用了一个额外的索引,因此keyval_zone的大小也应相应增加。

您还可以使用state参数来创建一个文件,其中存储了键值数据库,因此可以在NGINX Plus重新加载和重新启动时保持。在此示例中,为one.keyval:

nginx 复制代码
keyval_zone zone=one:1m state=one.keyval;

使用api指令将NGINX Plus API启用为读-写模式:

nginx 复制代码
# ...
 server {
     listen 80;
     server_name www.example.com;

     location /api {
         api write=on;
     }
 }

我们强烈建议限制对此位置的访问,例如仅允许从本地主机(127.0.0.1)访问,并使用HTTP基本身份验证将使用PATCH、POST和DELETE方法的使用限制为指定的一组用户:

nginx 复制代码
# ...
 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;
         }
     }
 }

使用API的POST方法将键值对数据库填充数据,以JSON格式提供数据。您可以像以下示例中那样使用curl命令。如果区域为空,则可以一次输入多个键值对;否则,必须逐个添加对。

sh 复制代码
$ 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

如果已经指定了IP地址与网络范围的匹配(使用keyval_zone指令的type=ip参数),请以CIDR表示法发送带有网络范围的POST命令:

sh 复制代码
$ curl -X POST -d '{
   "192.168.13.0/24": "1"
 }' -s http://www.example.com/api/6/http/keyvals/one

通过在http上下文中包含keyval指令,定义如何根据客户端IP地址与键值数据库进行匹配。

该指令利用了标准的NGINX和NGINX Plus变量$remote_addr,该变量自动设置为每个请求的客户端IP地址。

在处理每个请求时,NGINX Plus:

在键值数据库中查找第一个参数(这里是 <math xmlns="http://www.w3.org/1998/Math/MathML"> r e m o t e a d d r ,自动设置为客户端的 I P 地址)在 z o n e = 参数指定的键值数据库中。如果数据库中的键与 remote_addr,自动设置为客户端的IP地址)在zone=参数指定的键值数据库中。如果数据库中的键与 </math>remoteaddr,自动设置为客户端的IP地址)在zone=参数指定的键值数据库中。如果数据库中的键与remote_addr完全匹配,则将第二个参数(这里是$target)设置为与键对应的值。在我们的示例中,拒绝列表中的地址值为1,允许列表中的地址值为0。

nginx 复制代码
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地址允许或拒绝访问。通过这个规则,当 <math xmlns="http://www.w3.org/1998/Math/MathML"> t a r g e t 为 0 时允许访问,当 target为0时允许访问,当 </math>target为0时允许访问,当target为1时拒绝访问:

nginx 复制代码
if ($target) {
    return 403;
}

此方法允许您动态地创建和更新拒绝IP地址列表,并根据需要阻止或允许特定的客户端IP地址访问您的站点或应用程序。

管理键-值数据库

使用 API 方法动态更新键-值数据库,无需重新加载 NGINX Plus。

以下示例均操作一个区域,在 www.example.com/api/6/http/... 可访问。

获取区域的所有数据库条目列表:

bash 复制代码
curl -X GET 'http://www.example.com/api/6/http/keyvals/one'

更新现有条目的值(例如,将 IP 地址 10.0.0.4 的访问状态从允许更改为拒绝):

bash 复制代码
curl -X PATCH -d '{"10.0.0.4": "1"}' -s 'http://www.example.com/api/6/http/keyvals/one'

向已填充的区域添加条目:

bash 复制代码
curl -X POST -d '{"10.0.0.5": "1"}' -s 'http://www.example.com/api/6/http/keyvals/one'

删除条目:

bash 复制代码
curl -X PATCH -d '{"10.0.0.4":null}' -s 'http://www.example.com/api/6/http/keyvals/one'

完整示例

完整的 NGINX Plus 配置:

nginx 复制代码
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;
        }
    }
}

此配置:

  • 创建了一个 1 MB 的 keyval 区域 one,接受网络范围,并创建文件 one.keyval 以使键-值对数据库在 NGINX Plus 重新加载和重启时保持持久化。
  • 启用了 NGINX Plus API 写入模式,以便使用 IP 地址填充区域。
  • 启用了将 IP 地址 <math xmlns="http://www.w3.org/1998/Math/MathML"> r e m o t e a d d r 在键 − 值数据库中查找的功能,将找到的键的值放入 remote_addr 在键-值数据库中查找的功能,将找到的键的值放入 </math>remoteaddr在键−值数据库中查找的功能,将找到的键的值放入target 变量。
  • 启用了一个简单的规则来检查结果值:如果 $target 的值为 1(地址在拒绝列表中),则向客户端返回 403(禁止)。

以下 curl 命令将空的 keyval 区域 one 填充了拒绝列表(值为 1)或允许列表(值为 0)的 IP 地址:

bash 复制代码
$ 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'

参见

使用 NGINX Plus 和 fail2ban 进行动态 IP 拒绝列表

参考资料

docs.nginx.com/nginx/admin...

相关推荐
Uranus^10 分钟前
使用Spring Boot和Spring Security结合JWT实现安全的RESTful API
java·spring boot·spring security·jwt·restful api
FAQEW14 分钟前
介绍一下什么是反射(面试题详细讲解)
java·开发语言·反射
是三好1 小时前
并发容器(Collections)
java·多线程·juc
jian110581 小时前
java项目实战、pom.xml配置解释、pojo 普通java对象
java·开发语言·python
述雾学java1 小时前
Spring Boot是什么?MybatisPlus常用注解,LambdaQueryWrapper常用方法
java·spring boot·后端
jinhuazhe20131 小时前
maven 3.0多线程编译提高编译速度
java·maven
xosg2 小时前
HTMLUnknownElement的使用
java·前端·javascript
forestsea3 小时前
Java虚拟机面试题:内存管理(上)
java·开发语言
yueyekkx3 小时前
Ubuntu24.04 LTS安装java8、mysql8.0
java·mysql·ubuntu
若水uy3 小时前
静态分配动态绑定
java