Ngx_lua
ngx_cache_purge 缓存使用,(如果不会lua开发,不需要安装)
nginx_upstream_check_module 流量分发使用,(如果不会lua开发,不需要安装)
部署 openresty
mkdir -p /usr/servers
cd /usr/servers/
# 安装依赖
yum install -y readline-devel pcre-devel openssl-devel gcc
# 可能需要翻墙才能下载,所以可以离线下载好
wget http://openresty.org/download/ngx_openresty-1.7.7.2.tar.gz
tar -xzvf ngx_openresty-1.7.7.2.tar.gz
rm -rf ngx_openresty-1.7.7.2.tar.gz
# 安装 lua 等相关组件
cd /usr/servers/ngx_openresty-1.7.7.2/
cd bundle/LuaJIT-2.1-20150120/
make clean && make && make install
ln -sf luajit-2.1.0-alpha /usr/local/bin/luajit
cd ../
wget https://github.com/FRiCKLE/ngx_cache_purge/archive/2.3.tar.gz
tar -xvf 2.3.tar.gz
wget https://github.com/yaoweibin/nginx_upstream_check_module/archive/v0.3.0.tar.gz
tar -xvf v0.3.0.tar.gz
#
cd /usr/servers/ngx_openresty-1.7.7.2
./configure --prefix=/usr/servers --with-http_realip_module --with-pcre --with-luajit --add-module=./bundle/ngx_cache_purge-2.3/ --add-module=./bundle/nginx_upstream_check_module-0.3.0/ -j2
make && make install
# 会发现多了好多目录
[root@eshop-cache01 servers]# ll
total 3316
drwxr-xr-x 2 root root 4096 Apr 1 23:38 bin
drwxr-xr-x 6 root root 4096 Apr 1 23:38 luajit
drwxr-xr-x 5 root root 4096 Apr 1 23:38 lualib
drwxr-xr-x 6 root root 4096 Apr 1 23:38 nginx
drwxrwxr-x 4 1000 1000 4096 Apr 1 23:35 ngx_openresty-1.7.7.2
# 启动nginx:
/usr/servers/nginx/sbin/nginx
添加 lua 模块到 nginx 中
vi /usr/servers/nginx/conf/nginx.conf
# 在 http 部分添加如下内容
如下位置
http {
# 添加模块
lua_package_path "/usr/servers/lualib/?.lua;;";
lua_package_cpath "/usr/servers/lualib/?.so;;";
include mime.types;
default_type application/octet-stream;
。。。。。。
}
结合 redis 防 CC 设置
[root@k3s-master conf]# cat waf/LimitRate.lua
--加载 REDIS 模块
local r_md = require "resty.redis"
--获取当前请求的 HEADER
local headers = ngx.req.get_headers()
--指定 REDIS 的地址、端口、密码、连接的空闲超时时间、接池大小
local redis_ip = "127.0.0.1"
local redis_port = "6379"
local redis_pass = "123456"
local redis_timeout = 1000
local redis_pool_max_idle_time = 1000
local redis_pool_size = 100
--建立 redis 实例
local redis = r_md:new()
--指定IP存储超时时间
local qtrange = 60
--允许在IP存储时间内访问的次数
local qcount = 10
--尝试根据 HTTP 头遂级获取 IP
local clientip = headers["X-Real-IP"]
if clientip == nil then
clientip = headers["x_forwarded_for"]
end
if clientip == nil then
clientip = ngx.var.remote_addr
end
--释放 redis 连接的函数
local function redis_close(red)
--释放连接,使用 set_keepalive 指令将当前连接放入当前进程的连接池中待用,需要指定连接池的大小及其中各个连接的空闲超时时间;
local pool_max_idle_time = redis_pool_max_idle_time --毫秒
local pool_size = redis_pool_size --连接池大小
local ok, err = red:set_keepalive(pool_max_idle_time, pool_size)
if not ok then
ngx_log(ngx_ERR, "set redis keepalive error : ", err)
end
end
--选择的桶
--red:select(18)
--建立连接,若异常则释放连接;
local ok, wrong = redis:connect(redis_ip,redis_port)
if not ok then
redis_close(redis)
end
--指定所有 REDIS 操作的超时时间,其中包含了连接超时
redis:set_timeout(redis_timeout)
redis:auth(redis_pass)
--建立限速类
LimitIpRate = {}
--限速方法,令牌桶限速逻辑实现
function LimitIpRate:is_limited()
--尝试获取当前 IP 的令牌桶,令牌桶命名为“ x.x.x.x|pool ”
local res, err = redis:get(clientip.."|pool")
if not res then
ngx.log(ngx.ERR,"lua error: ",err)
end
--如果 res 不为空并且类型为 string,则代表获取到了对应的令牌桶
if type(res) == "string" then
--可用令牌数量为 0 则拦截
if tonumber(res) == 0 then
ngx.exit(ngx.HTTP_FORBIDDEN)
--反之放行并让令牌数量减少 1
else
add,err = redis:decr(clientip.."|pool")
if not add then
ngx.log(ngx.ERR,"lua error: ",err)
end
end
--如果 res 不为空并且类型为 userdata,则代表 redis 中没有对应令牌桶
elseif type(res) == "userdata" then
--往 redis 中放入指定名称、过期时间、值的键值对
ini, err = redis:setex(clientip.."|pool", qtrange, (qcount-1))
if not ini then
ngx.log(ngx.ERR,"lua error: ",err)
end
end
end
--调用限速方法
LimitIpRate.is_limited()
location / {
root html;
index index.html index.htm;
access_by_lua_file "conf/waf/LimitRate.lua"; # 添加如下
}
测试效果
[root@localhost ~]# for i in {1..12}; do curl -s 10.11.9.246 -o /dev/null -w %{http_code};echo ;done
200
200
200
200
200
403
403
403
403
403
403
403
参考: https://zq99299.github.io/note-book/cache-pdp/052.html#%E9%83%A8%E7%BD%B2-openresty
Last updated