设为首页 收藏本站
查看: 802|回复: 0

[经验分享] 通过 lua 进行 nginx redis 访问控制

[复制链接]

尚未签到

发表于 2018-11-3 09:57:49 | 显示全部楼层 |阅读模式
导读Nginx来处理访问控制的方法有多种,实现的效果也有多种,访问IP段,访问内容限制,访问频率限制等。  1. 需求分析
  1. Nginx来处理访问控制的方法有多种,实现的效果也有多种,访问IP段,访问内容限制,访问频率限制等。
  2. 用Nginx+Lua+Redis来做访问限制主要是考虑到高并发环境下快速访问控制的需求。
  3. Nginx处理请求的过程一共划分为11个阶段,分别是:
post-read、server-rewrite、find-config、rewrite、post-rewrite、 preaccess、access、post-access、try-files、content、log.  在openresty中,可以找到:
set_by_lua,access_by_lua,content_by_lua,rewrite_by_lua等方法。  那么访问控制应该是,access阶段。
  解决方案
  按照正常的逻辑思维,我们会想到的访问控制方案如下:
  1.检测是否被forbidden?
  =》是,forbidden是否到期:是,清除记录,返回200,正常访问;否,返回403;
  =》否,返回200,正常访问
  2.每次访问,访问用户的访问频率+1处理
  3.检测访问频率是否超过限制,超过即添加forbidden记录,返回403
  这是简单地方案,还可以添加点枝枝叶叶,访问禁止时间通过算法导入,每次凹曲线增加。
  实现方法
  首先为nginx添加vhost配置文件,vhost.conf部分内容如下:
lua_package_path "/usr/local/openresty/lualib/?.lua;;";#告诉openresty库地址  
lua_package_cpath "/usr/local/openresty/lualib/?.so;;";
  
error_log /usr/local/openresty/nginx/logs/openresty.debug.log debug;
  

  
server {
  
    listen 8080 default;
  
    server_name www.ttlsa.com;
  
    root  /www/openresty;
  

  
    location /login {
  
        default_type 'text/html';
  
        access_by_lua_file "/usr/local/openresty/nginx/lua/access_by_redis.lua";#通过lua来处理访问控制
  
    }
  
}
  Access_by_redis.lua
  参考了下v2ex.com的做法,redis存储方案只做简单地string存储就足够了。key分别是:
  用户登录记录:user:127.0.0.1:time(unix时间戳)
  访问限制:block:127.0.0.1
  先连接Redis吧:
local red = redis:new()  
function M:redis()
  red:set_timeout(1000)
  local ok, err = red:connect("127.0.0.1", 6379)
  if not ok then
  ngx.exit(ngx.HTTP_INTERNAL_SERVER_ERROR)
  end
  
end
  按照我们的逻辑方案,第二步是,检测是否forbidden,下面我们就检测block:127.0.0.1,如果搜索到数据,检测时间是否过期,未过期返回403,否则直接返回200:
function M:check1()  local time=os.time()--system time
  local res, err = red:get("block:"..ngx.var.remote_addr)
  if not res then-- redis error
  ngx.exit(ngx.HTTP_INTERNAL_SERVER_ERROR) --redis get data error end
  if type(res) == "string" then --if red not null then type(red)==string
  if tonumber(res) >= tonumber(time) then  --check if forbidden expired
  ngx.exit(ngx.HTTP_FORBIDDEN)
  --ngx.say("forbidden")
  end
  end
  
}
  接下来会做检测,是否访问频率过高,如果过高,要拉到黑名单的,
  实现的方法是,检测user:127.0.0.1:time的值是否超标:
function M:check2()  local time=os.time()--system time
  local res, err = red:get("user:"..ngx.var.remote_addr..":"..time)
  if not res then-- redis error
  ngx.exit(ngx.HTTP_INTERNAL_SERVER_ERROR) --redis get data error
  end
  

  if type(res) == "string" then
  if tonumber(res) >= 10 then -- attack, 10 times request/s
  red:del("block:"..self.ip)
  red:set("block:"..self.ip, tonumber(time)+5*60 ) --set block time
  ngx.exit(ngx.HTTP_FORBIDDEN)
  end
  end
  
end
  最后呢,还要记得,把每次访问时间做一个自增长,user:127.0.0.1:time:
function M:add()  local time=os.time()--system time
  ok, err = red:incr("user:"..ngx.var.remote_addr..":"..time)
  if not ok then
  ngx.exit(ngx.HTTP_INTERNAL_SERVER_ERROR) --redis get data error
  end
  
end
  那么,测试,强刷几次浏览器,发现过一会,返回了403,ok,搞定。
  本文原创地址:http://www.iyunv.com/lua-access-control-redis.html



运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-630117-1-1.html 上篇帖子: scrapy-redis插件爬取示例 下篇帖子: Redis中Key相关的常用指令详解
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表