openresty加lua脚本实现在nginx层的ip拦截
问题描述:
在项目中碰到用户刷注册接口,骗取注册成功后的一些列奖励。
达到的要求:
于是安全这边想要对用户的IP做一个过滤,做一套黑名单与白名单过滤,同时限制用户在1分钟内注册的次数。
使用的方案:
决定采用openresty加lua脚本,在nginx层面对用户ip做拦截过滤。
具体实施方案:
原理图:
黑白名单查询逻辑:
环境搭建:
总述 |
操作名称 |
具体操作 |
搭建openresty |
1、下载openresty |
下载地址:http://openresty.org/cn/download.html (这里使用openresty-1.13.6.2.tar.gz) |
2、解压openresty |
将下载的openresty-1.13.6.2.tar.gz包上传到服务器的/apps/svr路径下,并解压tar –xzvf openresty-1.13.6.2.tar.gz |
|
3、修改openresty的默认配置信息 |
cd /apps/svr/openresty-1.13.6.2目录下,输入命令: ./configure --prefix=/apps/svr/openresty (这里只简单改了下路径) |
|
4、编译 |
gmake (有的服务器命令是make) |
|
5、安装 |
gmake install (/apps/svr/目录下出现openresty文件夹即表示安装成功) |
|
6、修改nginx.conf配置文件 |
cd /apps/svr/openresty/nginx/conf目录下,rm –rf nginx.conf删除原有的nginx.conf配置文件。接着将已有的配置文件复制过来。 cp /apps/svr/nginx-1.9.12/conf/nginx.conf /apps/svr/openresty/nginx/conf/ |
|
7、新建lua脚本文件 |
在/apps/svr/openresty/nginx/目录下输入命令mkdir thirdlua新建thirdlua,并在thirdlua中新建lua文件operateip.lua文件。 |
|
8、编写operateip.lua脚本 |
local REDIS_HOST = "127.0.0.1" local REDIS_PORT = "6379"
local REDIS_CONN_TIMEOUT = 3 local WHITEIPS_KEY = "ip_white" local BLACKIPS_KEY = "ip_black" local LIMITIPS_KEY = "ip_limit"
local ip = ngx.var.remote_addr local redis = require "resty.redis"; local red=redis:new();
function ignoreWhitelist(ip) local exists = red:exists(WHITEIPS_KEY); if tonumber(exists) == 1 then exists = red:sismember(WHITEIPS_KEY,ip); if tonumber(exists) == 1 then ngx.log(ngx.INFO," this is white ip "); return true; end end return false; end
function checkBlacklist(ip) local exists = red:exists(BLACKIPS_KEY); if tonumber(exists) == 1 then exists = red:sismember(BLACKIPS_KEY,ip); if tonumber(exists) == 1 then ngx.log(ngx.INFO," this is black ip "); return true; end end return false; end
function limitIpFrequency(ip, times) local exists = red:exists(LIMITIPS_KEY..ip); ngx.log(ngx.INFO," exists ",exists); if tonumber(exists) == 0 then red:zincrby(LIMITIPS_KEY..ip,1,ip); red:expire(LIMITIPS_KEY..ip,60); else local count = red:zscore(LIMITIPS_KEY..ip,ip); ngx.log(ngx.INFO,count); if count then if tonumber(count) > times then return true; end end red:zincrby(LIMITIPS_KEY..ip, 1,ip); end return false; end
ngx.log(ngx.DEBUG,"remote_addr is ",ip); red:set_timeout(REDIS_CONN_TIMEOUT); local ok,err = red:connect(REDIS_HOST,REDIS_PORT); if not ok then ngx.log(ngx.INFO,"redis connection error "); else local hit = false; flg = ignoreWhitelist(ip); if flg==false then flg = checkBlacklist(ip); if flg==true then return ngx.exit(ngx.HTTP_NOT_FOUND); else flg = limitIpFrequency(ip,5); if flg==true then return ngx.exit(ngx.HTTP_NOT_FOUND); end end end end
ok, err = red:set_keepalive(1000,100); if not ok then red:close(); end
|
|
9、上传lua脚本 |
在/apps/svr/openresty/nginx/目录下输入命令mkdir thirdlua新建thirdlua |
|
10、配置lua脚本 |
在/apps/svr/openresty/nginx/conf/nginx.conf文件中添加如下配置信息 location /login/login.do { proxy_pass http://ip/login/login.do; access_by_lua_file thirdlua/operateip.lua; } |
|
|
||
搭建redis |
1、下载redis |
下载地址:https://redis.io/download (这里用redis-3.2.12.tar.gz) |
2、解压redis包 |
将下载的redis-3.2.12.tar.gz 包上传到服务器的/apps/svr路径下,并解压tar –xzvf redis-3.2.12.tar.gz |
|
3、编译 |
cd /apps/svr/redis-3.2.12 输入编译命令:make |
|
4、启动redis |
cd /apps/svr/redis-3.2.12/src 输入./redis-server启动redis服务 |
|
|
||
运营维护 |
1、添加白名单集合 |
在redis中新建set集合ip_white用于存储白名单 |
2、添加黑名单集合 |
在redis中新建set集合ip_black用于存储黑名单 |