匿名
未登录
登录
Linux78|wiki
搜索
查看“Nginx+Lua+Redis 实现自动封禁访问频率过高IP”的源代码
来自Linux78|wiki
名字空间
页面
讨论
更多
更多
页面选项
查看
查看源代码
历史
←
Nginx+Lua+Redis 实现自动封禁访问频率过高IP
因为以下原因,您没有权限编辑本页:
您所请求的操作仅限于该用户组的用户使用:
wiki:用户|用户
您可以查看与复制此页面的源代码。
安装好redis ,openresty 与ngx_cache_purge模块,该模块用于清理nginx缓存 nginx_upstream_check_module模块,该模块用于ustream健康检查 ==== 在Nginx中使用Lua脚本访问Redis ==== ===== 连接redis,然后添加一些测试参数 ===== [root@test1 utils]# redis-cli -h 192.168.1.222 -p 6379 192.168.1.222:6379> set "123" "456" OK ===== 编写链接Redis的Lua脚本 ===== vim /usr/local/openresty/nginx/conf/lua/redis.lua local redis = require "resty.redis" local conn = redis.new() conn.connect(conn, '192.168.1.222', '6379') #根据自己情况写ip和端口号 local res = conn:get("123") if res==ngx.null then ngx.say("redis集群中不存在KEY——'123'") return end ngx.say(res) ===== 在nginx配置文件中添加以下location ===== vim /usr/local/openresty/nginx/conf/nginx.conf location / { root html; } location /lua { default_type text/plain; content_by_lua 'ngx.say("hello,lua")'; } location /lua_redis { default_type text/plain; content_by_lua_file /usr/local/openresty/nginx/conf/lua/redis.lua; } ===== 验证 ===== 在浏览器输入ip/lua_redis 看能不能获取到刚才在redis添加的"123" 这个key 并获取到他的值 如果能看到下图的内容表示可以访问redis 准备工作已经准备好了,现在要来最终的Nginx+Lua+Redis自动封禁并解封IP了 ==== Nginx+Lua+Redis ==== ===== 添加访问控制的Lua脚本 ===== (此脚本需要改的只有下面的这一句,把redis的ip和端口替换一下即可 ok, err = conn:connect(“192.168.1.222”, 6379) 温馨提示:如果在nginx的上层有用到阿里云的SLB负载均衡的话需要修改一下脚本里的所有…ngx.var.remote_addr 把remote_addr替换成从SLB获取真实IP的字段即可,不然获取到的IP全都是阿里云SLB发过来处理过的IP,全都是一个网段的,根本没有办法起到封禁的效果) [root@test1 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.1.222", 6379) conn:set_timeout(2000) --超时时间2秒 --如果连接失败,跳转到脚本结尾 if not ok then goto FLAG end --查询ip是否被禁止访问,如果存在则返回403错误代码 is_block, err = conn:get(BUSINESS.."-BLOCK-"..ngx.var.remote_addr) if is_block == '1' then ngx.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_out res, err = conn:set(BUSINESS.."-COUNT-"..ngx.var.remote_addr, 1) res, err = conn:expire(BUSINESS.."-COUNT-"..ngx.var.remote_addr, ip_time_out) else ip_count = ip_count + 1 --存在则将单位时间内的访问次数加1 if ip_count >= ip_max_count then --如果超过单位时间限制的访问次数,则添加限制访问标识,限制时间为ip_block_time res, err = conn:set(BUSINESS.."-BLOCK-"..ngx.var.remote_addr, 1) res, err = conn:expire(BUSINESS.."-BLOCK-"..ngx.var.remote_addr, ip_block_time) else res, 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做演示 [root@test1 lua]# vim /usr/local/openresty/nginx/conf/nginx.conf location / { root html; } location /lua { set $business "lua"; #加这个是为了知道存在redis的数据是哪个localtion access_by_lua_file /usr/local/openresty/nginx/conf/lua/access.lua; default_type text/plain; content_by_lua 'ngx.say("hello,lua")'; } location /lua_redis { default_type text/plain; content_by_lua_file /usr/local/openresty/nginx/conf/lua/redis.lua; } 主要添加 access_by_lua_file /usr/local/openresty/nginx/conf/lua/access.lua; 让没一个请求都去调用这个lua脚本,注意路径和名字不要写错 set $business “lua” 是为了把IP放进redis的时候标明是哪个location的,可以不加 [root@test1 lua]# nginx -s reload #修改完后重启nginx 3、去访问192.168.1.222/lua 并一直按F5刷新 连接redis [root@test1 ~]# redis-cli -h 192.168.1.222 -p 6379 发现redis已经在统计访问lua这个网页ip的访问次数了 192.168.1.22:6379> KEYS * 1) "lua-COUNT-192.168.1.11" 192.168.1.22:6379> GET "lua-COUNT-192.168.1.11" "8" 这个key的过期时间是30秒,如果30秒没有重复访问20次这个key就会消失,所以说正常用户一般不会触发这个封禁的脚本 192.168.1.22:6379> ttl "lua-COUNT-192.168.1.11" (integer) 20 192.168.1.22:6379> ttl "lua-COUNT-192.168.1.11" (integer) 19 当30秒内访问超过了20次 发现触发脚本了,变成了403 进到redis里发现多了一个lua-block-192.168.1.11 过期时间是300秒,就是说在300秒内这个ip无法继续访问192.168.1.222/lua这个页面了 这个脚本的目的很简单:一个IP如果在30秒内其访问次数达到20次则表明该IP访问频率太快了,因此将该IP封禁5分钟。同时由于计数的KEY在Redis中的超时时间设置成了30秒,所以如果两次访问间隔时间大于30秒将会重新开始计数
返回至
Nginx+Lua+Redis 实现自动封禁访问频率过高IP
。
导航
导航
首页
最近更改
随机页面
栏目
Nginx
Kubernetes
Spring Cloud
Wiki工具
Wiki工具
特殊页面
页面工具
页面工具
用户页面工具
更多
链入页面
相关更改
页面信息
页面日志