Nginx+Lua脚本+Redis 实现自动封禁访问频率过高IP

1 、安装OpenResty
安装使用 OpenResty,这是一个集成了各种 Lua 模块的 Nginx 服务器,是一个以Nginx为核心同时包含很多第三方模块的Web应用服务器,使用Nginx的同时又能使用lua等模块实现复杂的控制。
(1)安装编译工具、依赖库
[root@test1 ~]# yum -y install readline-devel pcre-devel openssl-devel gcc
(2)下载openresty-1.13.6.1.tar.gz 源码包,并解压;下载ngx_cache_purge模块,该模块用于清理nginx缓存;下载nginx_upstream_check_module模块,该模块用于ustream健康检查。
cd /usr/local/
wget https://openresty.org/download/openresty-1.13.6.1.tar.gz
tar -zxvf openresty-1.13.6.1.tar.gz
cd openresty-1.13.6.1/bundle
wget http://labs.frickle.com/files/ngx_cache_purge-2.3.tar.gz
tar -zxvf ngx_cache_purge-2.3.tar.gz
wget https://github.com/yaoweibin/nginx_upstream_check_module/archive/v0.3.0.tar.gz
tar -zxvf v0.3.0.tar.gz
(3)配置需安装的模块
# ./configure --help可查询需要安装的模块并编译安装
./configure --prefix=/usr/local/openresty --with-luajit --with-http_ssl_module --user=root --group=root --with-http_realip_module --add-module=./bundle/ngx_cache_purge-2.3/ --add-module=./bundle/nginx_upstream_check_module-0.3.0/ --with-http_stub_status_module
make && make install
(5)启动nginx
/usr/local/openresty/nginx/sbin/nginx -c /usr/local/openresty/nginx/conf/nginx.conf
随后,打开浏览器访问页面。

(6)在Nginx上测试一下能否使用Lua脚本
vim /usr/local/openresty/nginx/conf/nginx.conf
在server里面加一个location /lua {default_type text/plain;content_by_lua 'ngx.say("hello,lua!")';
}

加完后重新reload配置。
在浏览器里输入 ip地址/lua,出现下面的字就表示Nginx能够成功使用lua了

2 、安装Redis
yum install -y redis
systemctl start redis
3 、Lua访问Redis
(1)连接redis,然后添加一些测试参数
redis-cli
set "123" "456"
(2)编写连接Redis的Lua脚本
vim /usr/local/openresty/nginx/conf/lua/redis.lua
local redis = require "resty.redis"
local conn = redis.new()
#根据自己情况写ip和端口号
conn.connect(conn, '192.168.20.205', '6379')
local res = conn:get("123")
if res==ngx.null thenngx.say("redis集群中不存在KEY——'123'")return
end
ngx.say(res)
(3)在nginx.conf配置文件中的server下添加以下location
vim /usr/local/openresty/nginx/conf/nginx.conf
location /lua_redis {default_type text/plain;content_by_lua_file /usr/local/openresty/nginx/conf/lua/redis.lua;
}

随后重新reload配置。
(4)验证Lua访问Redis的正确性
在浏览器输入ip/lua_redis, 如果能看到下图的内容表示Lua可以访问Redis。

准备工作已经完成,现在要实现OpenResty+Lua+Redis自动封禁并解封IP了。
4 、OpenResty+Lua实现
(1)添加访问控制的Lua脚本(只需要修改Lua脚本中连接Redis的IP和端口即可)
注意:如果在Nginx或者OpenResty的上层有用到阿里云的SLB负载均衡的话,需要修改一下脚本里的所有…ngx.var.remote_addr,把remote_addr替换成从SLB获取真实IP的字段即可,不然获取到的IP全都是阿里云SLB发过来的并且是处理过的IP,同时,这些IP全都是一个网段的,根本没有办法起到封禁的效果)
完整的Lua脚本如下所示。
vim /usr/local/openresty/nginx/conf/lua/access.lua
local ip_block_time=300 --封禁IP时间(秒)
local ip_time_out=30 --指定ip访问频率时间段(秒)
local ip_max_count=20 --指定ip访问频率计数最大值(秒)
local BUSINESS = ngx.var.business --nginx的location中定义的业务标识符,也可以不加,不过加了后方便区分--连接redis
local redis = require "resty.redis"
local conn = redis:new()
ok, err = conn:connect("192.168.20.205", 6379)
conn:set_timeout(2000) --超时时间2秒--如果连接失败,跳转到脚本结尾
if not ok thengoto FLAG
end--查询ip是否被禁止访问,如果存在则返回403错误代码
is_block, err = conn:get(BUSINESS.."-BLOCK-"..ngx.var.remote_addr)
if is_block == '1' thenngx.exit(403)goto FLAG
end--查询redis中保存的ip的计数器
ip_count, err = conn:get(BUSINESS.."-COUNT-"..ngx.var.remote_addr)if ip_count == ngx.null then --如果不存在,则将该IP存入redis,并将计数器设置为1、该KEY的超时时间为ip_time_outres, err = conn:set(BUSINESS.."-COUNT-"..ngx.var.remote_addr, 1)res, err = conn:expire(BUSINESS.."-COUNT-"..ngx.var.remote_addr, ip_time_out)
elseip_count = ip_count + 1 --存在则将单位时间内的访问次数加1if ip_count >= ip_max_count then --如果超过单位时间限制的访问次数,则添加限制访问标识,限制时间为ip_block_timeres, err = conn:set(BUSINESS.."-BLOCK-"..ngx.var.remote_addr, 1)res, err = conn:expire(BUSINESS.."-BLOCK-"..ngx.var.remote_addr, ip_block_time)elseres, err = conn:set(BUSINESS.."-COUNT-"..ngx.var.remote_addr,ip_count)res, err = conn:expire(BUSINESS.."-COUNT-"..ngx.var.remote_addr, ip_time_out)end
end-- 结束标记
::FLAG::
local ok, err = conn:close()
(2)在需要做访问限制的location里加两段代码即可,这里用刚才的/lua做演示
vim /usr/local/openresty/nginx/conf/nginx.conf

主要是添加如下配置:
access_by_lua_file /usr/local/openresty/nginx/conf/lua/access.lua;
其中,set $business “lua” 是为了把IP放进Redis的时候标明是哪个location的,可以不加这个配置。随后,重新reload配置。
(3)打开浏览器访问192.168.20.205/lua 并一直按F5刷新。

随后,连接Redis,查看IP的访问计数。
发现redis已经在统计访问lua这个网页ip的访问次数了

这个key的过期时间是30秒,如果30秒没有重复访问20次这个key就会消失,所以说正常用户一般不会触发这个封禁的脚本。
当30秒内访问超过了20次,发现触发脚本了,变成了403

再次查看Redis的key,发现多了一个lua-block-192.168.20.28,过期时间是300秒,就是说在300秒内这个ip无法继续访问192.168.20.205/lua这个页面了。

过五分钟后再去访问这个页面,又可以访问了。
这个脚本的目的很简单:一个IP如果在30秒内其访问次数达到20次则表明该IP访问频率太快了,因此将该IP封禁5分钟。同时由于计数的KEY在Redis中的超时时间设置成了30秒,所以如果两次访问间隔时间大于30秒将会重新开始计数。
相关文章:
Nginx+Lua脚本+Redis 实现自动封禁访问频率过高IP
1 、安装OpenResty 安装使用 OpenResty,这是一个集成了各种 Lua 模块的 Nginx 服务器,是一个以Nginx为核心同时包含很多第三方模块的Web应用服务器,使用Nginx的同时又能使用lua等模块实现复杂的控制。 (1)安装编译工具…...
PART 1 数据挖掘概论 — 数据挖掘方法论
目录 数据库知识发掘步骤 数据挖掘技术的产业标准 CRISP-DM SEMMA 数据库知识发掘步骤 数据库知识发掘(Knowledge Discovery in Database,KDD)是从数据库中的大量数据中发现不明显、之前未知、可能有用的知识。 知识发掘流程(Knowledge Discovery Process)包括属性选择…...
Centos安装ffmpeg的方法
推荐第一个,不要自己编译安装,太难了,坑多。 在 CentOS 上安装 FFmpeg 有几种方法,以下是两种常见的方法: ### 方法一:使用 RPM Fusion 仓库安装 1. **启用 RPM Fusion 仓库**: RPM Fusion 是一个第三方仓库,提供了许多 CentOS 官方仓库中没有的软件包。 ```bash…...
理解SQL中通配符的使用
前言 SQL 是一种标准化的结构化查询语言,涉及结构化查询时,高效地检索数据至关重要。而通配符是SQL中模式匹配的有效的方法。使用通配符可以更轻松地检索到所需的确切数据。通配符允许我们定义多功能查询条件。本文将 介绍SQL通配符的基础知识及用法。 …...
SpringBoot篇(简化操作的原理)
目录 一、代码位置 二、统一版本管理(parent) 三、提供 starter简化 Maven 配置 四、自动配置 Spring(引导类) 五、嵌入式 servlet 容器 一、代码位置 二、统一版本管理(parent) SpringBoot项目都会继…...
Cesium的模型(ModelVS)顶点着色器浅析
来自glTF和3D Tiles的模型会走ModelVS.glsl。这个文件不单独是把模型顶点转换为屏幕坐标,还包含了丰富的处理过程。 Cesium是根据定义的Define判断某个行为是否需要被执行,比如#define HAS_SILHOUETTE,说明需要计算模型外轮廓线。 Cesium的…...
机器人领域中的scaling law:通过复现斯坦福机器人UMI——探讨数据规模化定律(含UMI的复现关键)
前言 在24年10.26/10.27两天,我司七月在线举办的七月大模型机器人线下营时,我们带着大家一步步复现UMI,比如把杯子摆到杯盘上(其中1-2位学员朋友还亲自自身成功做到该任务) 此外,我还特地邀请了针对UMI做了改进工作的fastumi作者…...
C++之多态的深度剖析
目录 前言 1.多态的概念 2.多态的定义及实现 2.1多态的构成条件 2.1.1重要条件 2.1.2 虚函数 2.1.3 虚函数的重写/覆盖 2.1.4 选择题 2.1.5 虚函数其他知识 协变(了解) 析构函数的重写 override 和 final关键字 3. 重载,重写&…...
Microsoft Office PowerPoint制作科研论文用图
Microsoft Office PowerPoint制作科研论文用图 1. 获取高清图片2. 导入PPT3. 另存为“增强型windows元文件”emf格式4. 画图剪裁 1. 获取高清图片 这里指通过绘图软件画分辨率高的图片,我一般使用python画dpi600的图片。 2. 导入PPT 新建一个PPT(注意&a…...
go语言进阶之并发基础
并发 什么是并发,也就是我们常说的多线程,多个程序同时执行。 并发的基础 线程和进程 进程 进程是操作系统中一个重要的概念,指的是一个正在运行的程序的实例。它包含程序代码、当前活动的状态、变量、程序计数器和内存等资源。进程是系…...
po、dto、vo的使用场景
现在项目中有两类模型类:DTO数据传输对象、PO持久化对象,DTO用于接口层向业务层之间传输数据,PO用于业务层与持久层之间传输数据,有些项目还会设置VO对象,VO对象用在前端与接口层之间传输数据,如下图&#…...
聊一聊Elasticsearch的一些基本信息
一、Elasticsearch是什么 Elasticsearch简称ES,是一款分布式搜索引擎。它是在Apache Lucene基础之上采用Java语言开发的。 Elasticsearch的官方网站对它的解释是:Elasticsearch是一个分布式、RESTful的搜索和数据分析引擎。 通过上边的官方解释&#…...
Unity 两篇文章熟悉所有编辑器拓展关键类 (上)
本专栏基础资源来自唐老狮和siki学院,仅作学习交流使用,不作任何商业用途,吃水不忘打井人,谨遵教诲 编辑器扩展内容实在是太多太多了(本篇就有五千字) 所以分为两个篇章而且只用一些常用api举例,…...
Spring SPI、Solon SPI 有点儿像(Maven 与 Gradle)
一、什么是 SPI SPI 全名 Service Provider interface,翻译过来就是“服务提供接口”。基本效果是,申明一个接口,然后通过配置获取它的实现,进而实现动态扩展。 Java SPI 是 JDK 内置的一种动态加载扩展点的实现。 一般的业务代…...
合并排序算法(C语言版)
#include <stdio.h> void Copy(int *a, int *b, int left, int right) { int i; for(i0;i<right-left1;i) { a[ileft] b[i]; } } // 将 a[left,middle] 和 a[middle1,right]合并到 b[left, right]中 void Merge(int *a, int left, int midd…...
C++——输入一行文字,找出其中的大写字母、小写字母、空格数字以及其他字符各有多少。用指针或引用方法处理。
没注释的源代码 #include <iostream> using namespace std; int main() { char c; int ul0,ll0,sp0,di0,other0; cout<<"please input script c:"; while(cin.get(c)) { if(c\n) break; else if(c>A&&…...
【skywalking】maximum query complexity exceeded 3336 > 3000
问题 skywalking相关版本信息 jdk:17skywalking:10.1.0apache-skywalking-java-agent:9.3.0ElasticSearch : 8.8.2 问题描述 maximum query complexity exceeded 3336 > 3000 最大查询复杂度超过3336>3000 可能原因 查询条件过于复…...
开源一个开发的聊天应用与AI开发框架,集成 ChatGPT,支持私有部署的源码
大家好,我是一颗甜苞谷,今天分享一个开发的聊天应用与AI开发框架,集成 ChatGPT,支持私有部署的源码。 介绍 当前系统集成了ChatGPT的聊天应用,不仅提供了基本的即时通讯功能,还引入了先进的AI技术&#x…...
开发了一个成人学位英语助考微信小程序
微信小程序名称:石榴英语 全称:石榴英语真题助手 功能定位 北京成人学士学位英语辅助学习工具,包含记高频单词,高频词组,专项练习,模拟考试等功能。 开发背景 个人工作需要提高学习英文水平ÿ…...
LeetCode16:最接近的三数之和
原题地址:. - 力扣(LeetCode) 题目描述 给你一个长度为 n 的整数数组 nums 和 一个目标值 target。请你从 nums 中选出三个整数,使它们的和与 target 最接近。 返回这三个数的和。 假定每组输入只存在恰好一个解。 示例 1…...
C++初阶-list的底层
目录 1.std::list实现的所有代码 2.list的简单介绍 2.1实现list的类 2.2_list_iterator的实现 2.2.1_list_iterator实现的原因和好处 2.2.2_list_iterator实现 2.3_list_node的实现 2.3.1. 避免递归的模板依赖 2.3.2. 内存布局一致性 2.3.3. 类型安全的替代方案 2.3.…...
docker详细操作--未完待续
docker介绍 docker官网: Docker:加速容器应用程序开发 harbor官网:Harbor - Harbor 中文 使用docker加速器: Docker镜像极速下载服务 - 毫秒镜像 是什么 Docker 是一种开源的容器化平台,用于将应用程序及其依赖项(如库、运行时环…...
在 Nginx Stream 层“改写”MQTT ngx_stream_mqtt_filter_module
1、为什么要修改 CONNECT 报文? 多租户隔离:自动为接入设备追加租户前缀,后端按 ClientID 拆分队列。零代码鉴权:将入站用户名替换为 OAuth Access-Token,后端 Broker 统一校验。灰度发布:根据 IP/地理位写…...
对WWDC 2025 Keynote 内容的预测
借助我们以往对苹果公司发展路径的深入研究经验,以及大语言模型的分析能力,我们系统梳理了多年来苹果 WWDC 主题演讲的规律。在 WWDC 2025 即将揭幕之际,我们让 ChatGPT 对今年的 Keynote 内容进行了一个初步预测,聊作存档。等到明…...
Spring Boot+Neo4j知识图谱实战:3步搭建智能关系网络!
一、引言 在数据驱动的背景下,知识图谱凭借其高效的信息组织能力,正逐步成为各行业应用的关键技术。本文聚焦 Spring Boot与Neo4j图数据库的技术结合,探讨知识图谱开发的实现细节,帮助读者掌握该技术栈在实际项目中的落地方法。 …...
BCS 2025|百度副总裁陈洋:智能体在安全领域的应用实践
6月5日,2025全球数字经济大会数字安全主论坛暨北京网络安全大会在国家会议中心隆重开幕。百度副总裁陈洋受邀出席,并作《智能体在安全领域的应用实践》主题演讲,分享了在智能体在安全领域的突破性实践。他指出,百度通过将安全能力…...
PAN/FPN
import torch import torch.nn as nn import torch.nn.functional as F import mathclass LowResQueryHighResKVAttention(nn.Module):"""方案 1: 低分辨率特征 (Query) 查询高分辨率特征 (Key, Value).输出分辨率与低分辨率输入相同。"""def __…...
【JVM】Java虚拟机(二)——垃圾回收
目录 一、如何判断对象可以回收 (一)引用计数法 (二)可达性分析算法 二、垃圾回收算法 (一)标记清除 (二)标记整理 (三)复制 (四ÿ…...
在鸿蒙HarmonyOS 5中使用DevEco Studio实现企业微信功能
1. 开发环境准备 安装DevEco Studio 3.1: 从华为开发者官网下载最新版DevEco Studio安装HarmonyOS 5.0 SDK 项目配置: // module.json5 {"module": {"requestPermissions": [{"name": "ohos.permis…...
Unity UGUI Button事件流程
场景结构 测试代码 public class TestBtn : MonoBehaviour {void Start(){var btn GetComponent<Button>();btn.onClick.AddListener(OnClick);}private void OnClick(){Debug.Log("666");}}当添加事件时 // 实例化一个ButtonClickedEvent的事件 [Formerl…...
