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秒将会重新开始计数。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/459871.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

批量剪辑视频软件源码搭建全解析,支持OEM

一、引言 在当今数字化内容创作的时代,视频制作的需求呈爆发式增长。无论是社交媒体上的短视频创作者,还是专业的视频制作团队,都面临着大量视频剪辑的任务。批量剪辑视频软件应运而生,它能够显著提高视频剪辑的效率,满…

C语言笔记(指针题目)例题+图解

本文分为两部分 ,第一部分为数组、字符串、字符指针在sizeof和strlen中的辨析,第二部分是一些笔试题目。若有错误,请批评指正。 目录 1.第一部分 1.1.数组名的使用 1.1.1一维整型数组在sizeof中的使用 1.1.2一维字符数组在sizeof中的使用…

015:地理信息系统开发平台ArcGIS Engine10.2与ArcGIS SDK for the Microsoft .NET Framework安装教程

摘要:本文详细介绍地理信息系统开发平台ArcGIS Engine10.2与ArcGIS SDK for the Microsoft .NET Framework的安装流程。 一、软件介绍 ArcGIS Engine 10.2是由Esri公司开发的一款强大的GIS(地理信息系统)开发平台。该软件基于ArcGIS 10.2 fo…

华为手机卸载系统应用的方法

摘要: 1.手机环境:手机需要开启开发者模式并使用usb连接电脑,并选择文件传输模式 2.电脑环境:使用鸿蒙工具箱进行傻瓜操作或安装adb工具进行命令卸载 3.鸿蒙工具箱和adb工具本质都是使用adb shell pm uninstall -k --user 0 xx…

大数据中心年度数据运营服务项目实施技术方案(183页WORD)

文档介绍: 本大数据中心年度数据运营服务项目实施技术方案,通过构建高效的数据集成与治理平台、数据分析平台以及创新的数据服务模式,旨在为企业内外部用户提供更加精准、高效的数据支持。同时,注重安全与合规保障,确…

【linux网络编程】| socket套接字 | 实现UDP协议聊天室

前言:本节内容将带友友们实现一个UDP协议的聊天室。 主要原理是客户端发送数据给服务端。 服务端将数据再转发给所有链接服务端的客户端。 所以, 我们主要就是要实现客户端以及服务端的逻辑代码。 那么, 接下来开始我们的学习吧。 ps:本节内容…

TIFS-2024 FIRe2:细粒度表示和重组在换衣行人重识别中的应用

总体结论 本文提出了一种新的细粒度表示与重构(FIRe2)框架,用于解决布变人重识别问题。通过细粒度特征挖掘和属性重构,FIRe2在不依赖任何辅助信息的情况下,实现了最先进的性能。该方法在多个基准数据集上取得了显著的…

一款专业获取 iOS 设备的 UDID 工具|一键获取iPhone iPad设备的 UDID

什么是UDID? UDID,是iOS设备的一个唯一识别码,每台iOS设备都有一个独一无二的编码,这个编码,我们称之为识别码,也叫做UDID( Unique Device Identifier) 扫描后系统提示输入密码&am…

HTML--浮动布局练习

<!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><title>Document</title><style>/* 整个浏览器页…

ES6 变量的解构赋值

数组的解构赋值 对象的解构赋值 字符串的解构赋值

利用游戏引擎的优势

大家好&#xff0c;我是小蜗牛。 在当今快速发展的游戏产业中&#xff0c;选择合适的游戏引擎对开发者来说至关重要。Cocos Creator作为一款功能强大且灵活的游戏引擎&#xff0c;为开发者提供了丰富的工具和资源&#xff0c;使他们能够高效地开发出优秀的游戏。本文将探讨如何…

Python+Selenium+Pytest+POM自动化测试框架封装(完整版)

&#x1f345; 点击文末小卡片 &#xff0c;免费获取软件测试全套资料&#xff0c;资料在手&#xff0c;涨薪更快 1、测试框架简介 1&#xff09;测试框架的优点 代码复用率高&#xff0c;如果不使用框架的话&#xff0c;代码会显得很冗余。可以组装日志、报告、邮件等一些高…

【鸿蒙HarmonyOS实战:通过华为应用市场上架测试版App实现HBuilder X打包的UniApp项目的app转hap教程(邀请码)方式教程详解】

鸿蒙HarmonyOS实战&#xff1a;通过华为应用市场上架测试版App实现HBuilder X打包的UniApp项目的app转hap教程&#xff08;邀请码&#xff09;方式详解 在使用uniapp打包的鸿蒙项目的过程中&#xff0c;由于生成的是app文件&#xff0c;而hdc传给鸿蒙HarmonyOS系统需要的是hap文…

【Apache Zookeeper】

一、简介 1、场景 如何让⼀个应⽤中多个独⽴的程序协同⼯作是⼀件⾮常困难的事情。开发这样的应⽤&#xff0c;很容易让很多开发⼈员陷⼊如何使多个程序协同⼯作的逻辑中&#xff0c;最后导致没有时间更好地思考和实现他们⾃⼰的应⽤程序逻辑&#xff1b;又或者开发⼈员对协同…

名词(术语)了解--SSR/CSR

名词&#xff08;术语&#xff09;了解–SSR/CSR 什么是服务器端渲染(SSR)? 服务器端渲染是指由服务器生成完整的 HTML 页面&#xff0c;然后发送给客户端的过程。 这与客户端渲染&#xff08;CSR&#xff09;形成对比&#xff0c;后者主要依赖浏览器端的 JavaScript 来渲染…

有趣智力题(非编程题)

目录 赛马烧香问题 赛马 题目描述: 一共有36匹马 6个跑道 在没有计时器的情况下 请问: 最少进行多少次赛马 可以确定前三名? 答案:8次 图解思路: 注意下图写错了 注释没写错 图画错了 正确的是下图 烧香问题 题目描述: 有两根香 材质不均匀 但是每一根香 烧完都需要1h 请利用…

学习threejs,使用粒子实现下雪特效

&#x1f468;‍⚕️ 主页&#xff1a; gis分享者 &#x1f468;‍⚕️ 感谢各位大佬 点赞&#x1f44d; 收藏⭐ 留言&#x1f4dd; 加关注✅! &#x1f468;‍⚕️ 收录于专栏&#xff1a;threejs gis工程师 文章目录 一、&#x1f340;前言1.1 ☘️THREE.Points简介1.11 ☘️…

Golang | Leetcode Golang题解之第517题超级洗衣机

题目&#xff1a; 题解&#xff1a; func findMinMoves(machines []int) (ans int) {tot : 0for _, v : range machines {tot v}n : len(machines)if tot%n > 0 {return -1}avg : tot / nsum : 0for _, num : range machines {num - avgsum numans max(ans, max(abs(sum…

算法练习:209. 长度最小的子数组

题目链接&#xff1a;209. 长度最小的子数组。 这里ans来统计最小长度&#xff0c;所以初始值设置为INT_MAX.最后如果ans结果还是INT_MAX时&#xff0c;说明无此数组。 class Solution { public:int minSubArrayLen(int target, vector<int>& nums) {if (nums.size(…

WPF+MVVM案例实战(十一)- 环形进度条实现

文章目录 1、运行效果2、功能实现1、文件创建与代码实现2、角度转换器实现3、命名空间引用 3、源代码下载 1、运行效果 2、功能实现 1、文件创建与代码实现 打开 Wpf_Examples 项目&#xff0c;在Views 文件夹下创建 CircularProgressBar.xaml 窗体文件。 CircularProgressBa…