OpenResty + Lua + Redis 实现 客户端ip防刷

一、环境说明:

在Centos7上安装openresty
此次安装采用的是下载openresty的yum源来安装

[root@kusou-es11 conf]# sudo  yum-config-manager --add-repo https://openresty.org/yum/cn/centos/OpenResty.repo
  • 1.

sudo:yum-config-manager:找不到命令
解决办法:

[root@kusou-es11 conf]# yum -y install yum-utils

下载Openresty的yum源:

[root@kusou-es11 conf]# sudo yum-config-manager --add-repo https://openresty.org/yum/cn/centos/OpenResty.repo
已加载插件:fastestmirror
Repository epel is listed more than once in the configuration
Repository epel-debuginfo is listed more than once in the configuration
Repository epel-source is listed more than once in the configuration
adding repo from: https://openresty.org/yum/cn/centos/OpenResty.repo
grabbing file https://openresty.org/yum/cn/centos/OpenResty.repo to /etc/yum.repos.d/OpenResty.repo
repo saved to /etc/yum.repos.d/OpenResty.repo
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.

安装命令:


 yum install openresty openresty-resty openresty-opm  
[root@kusou-es11 conf]#  yum install openresty openresty-resty openresty-opm

Running transaction
  正在安装    : openresty-zlib-1.2.11-3.el7.centos.x86_64                                                                                                                                  1/7 
  正在安装    : openresty-openssl-1.1.0h-3.el7.centos.x86_64                                                                                                                               2/7 
  正在安装    : openresty-pcre-8.42-1.el7.centos.x86_64                                                                                                                                    3/7 
  正在安装    : openresty-1.15.8.1-1.el7.x86_64                                                                                                                                            4/7 
  正在安装    : openresty-resty-1.15.8.1-1.el7.noarch                                                                                                                                      5/7 
  正在安装    : openresty-doc-1.15.8.1-1.el7.noarch                                                                                                                                        6/7 
  正在安装    : openresty-opm-1.15.8.1-1.el7.noarch            
[root@kusou-es11 openresty]# which openresty
/usr/bin/openresty
[root@kusou-es11 openresty]# openresty -v
nginx version: openresty/1.15.8.1

  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.

到此处安装完成

[root@kusou-es11 openresty]# ls
bin  COPYRIGHT  luajit  lualib  nginx  openssl  pcre  pod  resty.index  site  zlib
[root@kusou-es11 openresty]# pwd
/usr/local/openresty
  • 1.
  • 2.
  • 3.
  • 4.

二、防刷和限流概念介绍:

防刷的概念:
防刷的目的是为了防止有些IP来爬去我们的网页,获取我们的价格等信息。不像普通的搜索引擎,这种爬去行为我们经过统计最高每秒300次访问,平均每秒266次访问。
由于我们的网站的页面都在CDN上,导致我们的CDN流量会定时冒尖。为了防止这种情况,打算将网页页面的访问从CDN切回主站。同时开启防刷功能,目前设置一秒200次访问即视为非法,会阻止10分钟的访问。

限流的概念
限流的目的是在大促或者流量突增期间,我们的后端服务假设某个接口能够扛住的的QPS为10000,这时候同时有20000个请求进来,经过限流模块,会先放10000个请求,其余的请求会阻塞一段时间。不简单粗暴的返回404,让客户端重试,同时又能起到流量销峰的作用。

原文出处: https://blog.csdn.net/fenglvming/article/details/51996406 此处简单引用,入涉及侵权,及时通知删除

三、客户端ip防刷具体实现


[root@VM_82_178_centos redislua]# cat /usr/local/openresty/nginx/conf/redislua/ipblack.lua 
--Lua
--定义关闭redis函数:
local function close_redis(red)
    if not red then
        return
    end
    -- 释放连接(连接池实现),毫秒
    local pool_max_idle_time = 10000 
    -- 连接池大小
    local pool_size = 100 
    local ok, err = red:set_keepalive(pool_max_idle_time, pool_size)
    local log = ngx_log
    if not ok then
        log(ngx_ERR, "set redis keepalive error : ", err)
    end
end

-- 连接redis
local redis = require('resty.redis')
local red = redis.new()
      red:set_timeout(1000)
local ok, err = red:connect("127.0.0.1", 20108)
    if not ok then
        ngx.say("failed to connect: ", err)
        return
    end

    local res, err = red:auth("123456")
    if not res then
        ngx.say("failed to authenticate: ", err)
        return
    end


--获取客户端真实的ip:
local clientIP = ngx.req.get_headers()["X-Real-IP"]
if clientIP == nil then
   clientIP = ngx.req.get_headers()["x_forwarded_for"]
end
if clientIP == nil then
   clientIP = ngx.var.remote_addr
end

--定义redis key值格式,incrkey 请求的频率,blockKey被阻塞的key,后面会存入redis:

local incrKey = "user:"..clientIP..":freq"
local blockKey = "user:"..clientIP..":block"

local is_block,err = red:get(blockKey) -- check if ip is blocked
if tonumber(is_block) == 1 then
    ngx.exit(403)
    close_redis(red)
end

--incr redis操作 默认是从0开始,执行一次会累加1
inc  = red:incr(incrKey)

if inc < 10 then
   inc = red:expire(incrKey,1)
end
-- 每秒10次以上访问即视为非法,会阻止1分钟的访问
if inc > 10 then
    --设置block 为 True 为1
    red:set(blockKey,1) 
    red:expire(blockKey,60)
end

close_redis(red)
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.
  • 26.
  • 27.
  • 28.
  • 29.
  • 30.
  • 31.
  • 32.
  • 33.
  • 34.
  • 35.
  • 36.
  • 37.
  • 38.
  • 39.
  • 40.
  • 41.
  • 42.
  • 43.
  • 44.
  • 45.
  • 46.
  • 47.
  • 48.
  • 49.
  • 50.
  • 51.
  • 52.
  • 53.
  • 54.
  • 55.
  • 56.
  • 57.
  • 58.
  • 59.
  • 60.
  • 61.
  • 62.
  • 63.
  • 64.
  • 65.
  • 66.
  • 67.
  • 68.
  • 69.
  • 70.

nginx配置文件如下:

[root@VM_82_178_centos redislua]# less /usr/local/openresty/nginx/conf/vhost/01ip-blacklist.conf
server {
     listen       80;
     server_name  01ip-blacklist.com;
      index index.html index.htm index.php;
        root /data/www/test;
     location  / {
     access_by_lua_file   /usr/local/openresty/nginx/conf/redislua/ipblack.lua;
     default_type 'text/html';
     #content_by_lua 'ngx.say("hello world")';
     access_log  /data/wwwlog/01ip_access.log ;
    }  
}

  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.

四、测试演示:

ab软件压测:
-c10表示并发用户数为10
-n10表示请求总数为10

[root@VM_82_178_centos ~]# ab -c 10 -n 10 ‘ http://01ip-blacklist.com/1.html

压测后登录redis查看redis key值

127.0.0.1:20108> keys *
1) "dog1"
2) "user:119.29.97.131:block"

[root@VM_82_178_centos ~]# curl http://01ip-blacklist.com/1.html
<html>
<head><title>403 Forbidden</title></head>
<body>
<center>403 Forbidden</center>
<hr><center>openresty</center>
</body>
</html>
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.

过一分钟恢复,可以正常的请求
[root@VM_82_178_centos limit]# curl  http://01ip-blacklist.com/1.html
1234

posted @ 2019-08-04 16:53  勤奋的蓝猫  阅读(9)  评论(0编辑  收藏  举报  来源