nginx+lua+redis实现ip黑名单
1.安装LuaJIT
LuaJIT LuaJIT即采用C语言写的Lua代码的解释器
http://luajit.org/download/LuaJIT-2.0.5.tar.gz
tar -zxf LuaJIT-2.0.5.tar.gz
cd LuaJIT-2.0.5
make && make install PREFIX=/usr/local/data/lua
vim /etc/ld.so.conf
/usr/local/data/lua/lib #添加
ldconfig #运行命令使其生效
2.安装Ngx_lua模块
https://codeload.github.com/simpl/ngx_devel_kit/zip/master #zip格式
https://codeload.github.com/openresty/lua-nginx-module/zip/master #zip格式
ngx_devele_kit 一个拓展nginx服务器核心功能的模块,第三方模块开发可以基于它来快速实现 lua-nginx-module lua的nginx模块
export LUAJIT_LIB=/usr/local/data/lua/lib/
export LUAJIT_INC=/usr/local/data/lua/include/luajit-2.0/
需要重新编译nginx
./configure --prefix=/usr/local/data/nginx --user=goforit --group=goforit --prefix=/usr/local/data/nginx --with-http_stub_status_module --with-http_ssl_module --add-module=../ngx_devel_kit --add-module=../lua-nginx-module && make
mv /usr/local/data/nginx/sbin/nginx /usr/local/data/nginx/sbin/nginx.old
cp objs/nginx /usr/local/data/nginx/sbin/nginx
/usr/local/data/nginx/sbin/nginx -t /usr/local/data/nginx/conf/nginx.conf
kill -USR2 `cat /usr/local/data/nginx/logs/nginx.pid`
kill -WINCH `cat /usr/local/data/nginx/logs/nginx.pid.oldbin`
kill -HUP `cat /usr/local/data/nginx/logs/nginx.pid.oldbin`
kill -QUIT `cat /usr/local/data/nginx/logs/nginx.pid.oldbin`
3.测试lua是否生效 修改nginx配置
location ~ /lua {
default_type 'text/plain';
content_by_lua 'ngx.say("hello, lua!")';
}
测试访问 http://192.169.100.105/lua 输出,hello,lua!即可
4.安装redis服务启动
yum -y install redis
/etc/init.d/redis start
5.安装lua redis库
下载
https://codeload.github.com/openresty/lua-resty-redis/zip/master
放到/usr/local/nginx/lua下即可 nginx.conf添加
lua_package_path "/usr/local/data/nginx/lua/lua-resty-redis/lib/?.lua;;";
重载nginx即可
6.配置nginx限制IP地址 nginx.conf添加
lua_shared_dict ip_blacklist 1m;
server{}中添加
locaiont ~ \.php {
...
...
...
access_by_lua_file /usr/local/data/nginx/conf/lua/ip_blacklist.lua; #配置文件在下面
default_type 'text/html';
#content_by_lua 'ngx.say("hello,lua!")';
}
vim ip_blacklist.lua
-- a quick LUA access script for nginx to check IP addresses against an
-- `ip_blacklist` set in Redis, and if a match is found send a HTTP 403.
--
-- allows for a common blacklist to be shared between a bunch of nginx
-- web servers using a remote redis instance. lookups are cached for a
-- configurable period of time.
--
-- block an ip:
-- redis-cli SADD ip_blacklist 10.1.1.1
-- remove an ip:
-- redis-cli SREM ip_blacklist 10.1.1.1
--
-- also requires lua-resty-redis from:
-- https://github.com/agentzh/lua-resty-redis
--
-- your nginx http context should contain something similar to the
-- below: (assumes resty/redis.lua exists in /etc/nginx/lua/)
--
-- lua_package_path "/etc/nginx/lua/?.lua;;";
-- lua_shared_dict ip_blacklist 1m;
--
-- you can then use the below (adjust path where necessary) to check
-- against the blacklist in a http, server, location, if context:
--
-- access_by_lua_file /etc/nginx/lua/ip_blacklist.lua;
--
-- from https://gist.github.com/chrisboulton/6043871
-- modify by Ceelog
local redis_host = "192.169.100."
local redis_port = 6379
local redis_pass = "Redis2016"
-- connection timeout for redis in ms. don't set this too high!
local redis_connection_timeout = 100
-- check a set with this key for blacklist entries
local redis_key = "ip_blacklist"
-- cache lookups for this many seconds
local cache_ttl = 60
-- end configuration
local ip = ngx.var.remote_addr
local ip_blacklist = ngx.shared.ip_blacklist
local last_update_time = ip_blacklist:get("last_update_time");
-- only update ip_blacklist from Redis once every cache_ttl seconds:
if last_update_time == nil or last_update_time < ( ngx.now() - cache_ttl ) then
local redis = require "resty.redis";
local red = redis:new();
red:set_timeout(redis_connection_timeout);
local ok, err = red:connect(redis_host, redis_port);
local ok2, err2 = red:auth(redis_pass)
red:select(1)
if not ok then
ngx.log(ngx.DEBUG, "Redis connection error while retrieving ip_blacklist: " .. err);
else
local new_ip_blacklist, err = red:smembers(redis_key);
if err then
ngx.log(ngx.DEBUG, "Redis read error while retrieving ip_blacklist: " .. err);
else
-- replace the locally stored ip_blacklist with the updated values:
ip_blacklist:flush_all();
for index, banned_ip in ipairs(new_ip_blacklist) do
ip_blacklist:set(banned_ip, true);
end
-- update time
ip_blacklist:set("last_update_time", ngx.now());
end
end
end
if ip_blacklist:get(ip) then
ngx.log(ngx.DEBUG, "Banned IP detected and refused access: " .. ip);
return ngx.exit(ngx.HTTP_FORBIDDEN);
end
在redis里添加IP地址测试
SADD ip_blacklist 192.168.100.1 #添加地址
SREM ip_blacklist 192.168.100.1 #删除地址
SMEMBERS ip_blacklist #查看所有地址
reload nginx 测试即可 会发现访问状态是403
参考文章:
http://www.cnblogs.com/tinywan/p/6534151.html
http://blog.csdn.net/hj7jay/article/details/62037065
https://my.oschina.net/sakmon/blog/393917
遇到错误: 1.错误
/usr/local/data/nginx/sbin/nginx -t
/usr/local/nginx/sbin/nginx: error while loading shared libraries: libluajit-5.1.so.2: cannot open shared object file: No such file or directory
解决:
vim /etc/ld.so.conf
/usr/local/data/lua/lib #添加
ldconfig #即可
2.报错
2017/08/16 17:00:25 [error] 3795#0: *64 lua entry thread aborted: runtime error: /usr/local/nginx/conf/lua/ip_blacklist.lua:51: module 'resty.redis' not found:
no field package.preload['resty.redis']
no file '/usr/local/nginx/lua/lua-resty-redis/lib/resty/redis.lua'
no file './resty/redis.lua'
no file '/usr/local/share/luajit-2.0.5/resty/redis.lua'
no file '/usr/local/share/lua/5.1/resty/redis.lua'
no file '/usr/local/share/lua/5.1/resty/redis/init.lua'
no file './resty/redis.so'
no file '/usr/local/lib/lua/5.1/resty/redis.so'
no file '/usr/local/lib/lua/5.1/loadall.so'
no file './resty.so'
no file '/usr/local/lib/lua/5.1/resty.so'
no file '/usr/local/lib/lua/5.1/loadall.so'
stack traceback:
coroutine 0:
[C]: in function 'require'
/usr/local/nginx/conf/lua/ip_blacklist.lua:51: in function </usr/local/nginx/conf/lua/ip_blacklist.lua:1>, client: 192.169.100.1, server: mytest.com, request: "GET /ipblacklist HTTP/1.1", host: "192.169.100.105"
解决: 缺少相关库 下载
https://codeload.github.com/openresty/lua-resty-redis/zip/master
放到/usr/local/nginx/lua下即可
nginx.conf添加
lua_package_path "/usr/local/data/nginx/lua/lua-resty-redis/lib/?.lua;;";
重载nginx即可