使用 Nginx、Lua 脚本和 Redis 可以实现一个自动封禁访问频率过高 IP 的功能。这种架构非常适合处理高并发场景下的访问控制。以下是一个简单的实现步骤:
1. 环境准备
- Nginx:安装并配置 Nginx。
- LuaJIT:安装 LuaJIT,因为 Nginx 的 Lua 模块需要 LuaJIT。
- Nginx Lua 模块:安装
lua-nginx-module
和ngx_devel_kit
。 - Redis:安装并配置 Redis,用于存储访问频率数据。
2. 安装 Nginx 和 Lua 模块
你可以通过源码编译 Nginx 并添加 Lua 模块。以下是一个简单的编译步骤:
# 下载 Nginx 源码
wget http://nginx.org/download/nginx-1.21.3.tar.gz
tar -zxvf nginx-1.21.3.tar.gz
cd nginx-1.21.3/
# 下载 LuaJIT 和 Nginx Lua 模块
wget https://github.com/openresty/lua-nginx-module/archive/v0.10.20.tar.gz -O lua-nginx-module-0.10.20.tar.gz
wget https://github.com/simpl/ngx_devel_kit/archive/v0.3.1.tar.gz -O ngx_devel_kit-0.3.1.tar.gz
tar -zxvf lua-nginx-module-0.10.20.tar.gz
tar -zxvf ngx_devel_kit-0.3.1.tar.gz
# 下载 LuaJIT
wget https://github.com/LuaJIT/LuaJIT/archive/v2.1.0-beta3.tar.gz -O LuaJIT-2.1.0-beta3.tar.gz
tar -zxvf LuaJIT-2.1.0-beta3.tar.gz
cd LuaJIT-2.1.0-beta3
make PREFIX=/usr/local/luajit
make install PREFIX=/usr/local/luajit
export LUAJIT_LIB=/usr/local/luajit/lib
export LUAJIT_INC=/usr/local/luajit/include/luajit-2.1
# 编译 Nginx
cd ../nginx-1.21.3
./configure --prefix=/usr/local/nginx \
--add-module=../ngx_devel_kit-0.3.1 \
--add-module=../lua-nginx-module-0.10.20 \
--with-ld-opt="-Wl,-rpath,/usr/local/luajit/lib" \
--with-http_ssl_module
make
make install
3. 配置 Nginx 和 Lua 脚本
在 Nginx 配置文件中(通常是 /usr/local/nginx/conf/nginx.conf
),添加 Lua 脚本和访问控制逻辑。
http {
lua_shared_dict my_limit_store 10m;
lua_package_path "/path/to/lua/scripts/?.lua;;";
server {
listen 80;
location / {
access_by_lua_file /path/to/lua/scripts/rate_limit.lua;
proxy_pass http://your_backend; # 替换为你的后端地址
}
}
}
4. 编写 Lua 脚本
在 /path/to/lua/scripts/rate_limit.lua
中编写 Lua 脚本,用于访问控制和 Redis 交互。
local limit_req = require "resty.limit.req"
-- 初始化限制对象,参数为 Redis 实例、存储的 key 前缀、存储的桶大小(滑动窗口大小)、速率(每秒多少请求)
local lim, err = limit_req.new("my_limit_store", "zone_key", 10, 20)
if not lim then
ngx.log(ngx.ERR, "failed to instantiate a resty.limit.req object: ", err)
return ngx.exit(500)
end
local key = ngx.var.binary_remote_addr -- 使用客户端 IP 作为 key
local delay, err = lim:incoming(key, true)
if not delay then
if err == "rejected" then
ngx.log(ngx.ERR, "request got rejected due to rate limiting")
return ngx.exit(429) -- 返回 429 Too Many Requests
else
ngx.log(ngx.ERR, "failed to limit request: ", err)
return ngx.exit(500)
end
end
-- 如果请求被限速,delay 会返回需要延迟的时间(秒),可以将其转化为毫秒后 sleep
if delay >= 0.001 then
ngx.sleep(delay)
end
-- 可以在这里添加额外的逻辑,比如记录日志到 Redis 或其他系统
5. 启动和测试
- 启动 Nginx:
/usr/local/nginx/sbin/nginx
- 启动 Redis:
redis-server
现在,Nginx 将根据配置对访问频率进行限制,并自动封禁访问频率过高的 IP。你可以通过并发请求测试工具(如 ab
或 wrk
)来验证这一功能。
6. 进一步优化
- 动态配置:可以通过 Lua 脚本读取配置文件或环境变量来动态调整限速策略。
- 日志记录:可以将被限速的 IP 记录到 Redis 或其他日志系统中,以便后续分析。
- 白名单:添加白名单逻辑,允许特定 IP 不受限速策略的影响。
通过上述步骤,你可以使用 Nginx、Lua 脚本和 Redis 实现一个高效的访问频率限制系统。
© 版权声明
文中内容均来源于公开资料,受限于信息的时效性和复杂性,可能存在误差或遗漏。我们已尽力确保内容的准确性,但对于因信息变更或错误导致的任何后果,本站不承担任何责任。如需引用本文内容,请注明出处并尊重原作者的版权。
THE END
暂无评论内容