日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > 数据库 >内容正文

数据库

openresty开发系列38--通过Lua+Redis 实现动态封禁IP

發布時間:2025/3/20 数据库 48 豆豆
生活随笔 收集整理的這篇文章主要介紹了 openresty开发系列38--通过Lua+Redis 实现动态封禁IP 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
openresty開發系列38--通過Lua+Redis 實現動態封禁IP

一)需求背景
為了封禁某些爬蟲或者惡意用戶對服務器的請求,我們需要建立一個動態的 IP 黑名單。
對于黑名單之內的 IP ,拒絕提供服務。

二)設計方案
實現 IP 黑名單的功能有很多途徑:
1、在操作系統層面,配置 iptables,拒絕指定 IP 的網絡請求;
2、在 Web Server 層面,通過 Nginx 自身的 deny 選項 或者 lua 插件 配置 IP 黑名單;
3、在應用層面,在請求服務之前檢查一遍客戶端 IP 是否在黑名單。

為了方便管理和共享,我們通過 Nginx+Lua+Redis 的架構實現 IP 黑名單的功能

如圖

配置nginx.conf
在http部分,配置本地緩存,來緩存redis中的數據,避免每次都請求redis

lua_shared_dict shared_ip_blacklist 8m; #定義ip_blacklist 本地緩存變量

location /ipblacklist {
?? ?access_by_lua_file /usr/local/lua/access_by_limit_ip.lua;
?? ?echo "ipblacklist";
}


# 編輯 /usr/local/lua/access_by_limit_ip.lualocal function close_redis(red)if not red then returnend --釋放連接(連接池實現) local pool_max_idle_time = 10000 --毫秒 local pool_size = 100 --連接池大小 local ok, err = red:set_keepalive(pool_max_idle_time, pool_size) if not ok then ngx.say("set keepalive error : ", err) end endlocal function errlog(...)ngx.log(ngx.ERR, "redis: ", ...) endlocal function duglog(...)ngx.log(ngx.DEBUG, "redis: ", ...) endlocal function getIp()local myIP = ngx.req.get_headers()["X-Real-IP"]if myIP == nil thenmyIP = ngx.req.get_headers()["x_forwarded_for"]endif myIP == nil thenmyIP = ngx.var.remote_addrendreturn myIP; endlocal key = "limit:ip:blacklist" local ip = getIp(); local shared_ip_blacklist = ngx.shared.shared_ip_blacklist--獲得本地緩存的最新刷新時間 local last_update_time = shared_ip_blacklist:get("last_update_time");if last_update_time ~= nil then local dif_time = ngx.now() - last_update_time if dif_time < 60 then --緩存1分鐘,沒有過期if shared_ip_blacklist:get(ip) thenreturn ngx.exit(ngx.HTTP_FORBIDDEN) --直接返回403endreturnend endlocal redis = require "resty.redis" --引入redis模塊 local red = redis:new() --創建一個對象,注意是用冒號調用的--設置超時(毫秒) red:set_timeout(1000) --建立連接 local ip = "10.11.0.215" local port = 6379 local ok, err = red:connect(ip, port) if not ok then close_redis(red)errlog("limit ip cannot connect redis"); elselocal ip_blacklist, err = red:smembers(key);if err thenerrlog("limit ip smembers");else--刷新本地緩存,重新設置 shared_ip_blacklist:flush_all();--同步redis黑名單 到 本地緩存for i,bip in ipairs(ip_blacklist) do--本地緩存redis中的黑名單shared_ip_blacklist:set(bip,true);end--設置本地緩存的最新更新時間shared_ip_blacklist:set("last_update_time",ngx.now());end end if shared_ip_blacklist:get(ip) thenreturn ngx.exit(ngx.HTTP_FORBIDDEN) --直接返回403 end

當redis設置了密碼時代碼如下:

[root@node5 lua]# cat /usr/local/lua/access_by_limit_ip.lua

local function close_reis(red)if not red thenreturnendlocal pool_max_idle_time = 10000local pool_size = 100local ok, err = red:set_keepalive(pool_max_idle_time, pool_size)if not ok thenngx.say("set keepalive error :", err)end endlocal function errlog(...)ngx.log(ngx.ERR, "redis: ", ...) endlocal function duglog(...)ngx.log(ngx.DEBUG, "redis: ",...) endlocal function getIp()local myip = ngx.req.get_headers()["X-Real-IP"]if myip == nil thenmyip = ngx.req.get_headers()["x_forwarded_for"]endif myip == nil thenmyip = ngx.var.remote_addrendreturn myip endlocal key = "limit:ip:blacklist" local ip = getIp(); local shared_ip_blacklist = ngx.shared.shared_ip_blacklistlocal last_update_time = shared_ip_blacklist:get("last_update_time");if last_update_time ~= nil thenlocal dif_time = ngx.now() - last_update_timeif dif_time < 60 thenif shared_ip_blacklist:get(ip) thenreturn ngx.exit(ngx.HTTP_FORBIDDEN)endreturnend endlocal redis = require "resty.redis" local red = redis:new()red:set_timeout(1000) local ip = "10.11.0.215" local port = 6379 local ok, err = red:connect(ip,port)local count, err = red:get_reused_times() if 0 == count then ----新建連接,需要認證密碼ok, err = red:auth("redis123")if not ok thenngx.say("failed to auth: ", err)returnend elseif err then ----從連接池中獲取連接,無需再次認證密碼ngx.say("failed to get reused times: ", err)return endif not ok thenclose_redis(red)errlog("limit ip cannot connect redis"); elselocal ip_blacklist, err = red:smembers(key)if err thenerrlog("limit ip smembers")elseshared_ip_blacklist:flush_all();for i,bip in ipairs(ip_blacklist) doshared_ip_blacklist:set(bip, true);endshared_ip_blacklist:set("last_update_time", ngx.now());end endif shared_ip_blacklist:get(ip) thenreturn ngx.exit(ngx.HTTP_FORBIDDEN) end

用戶redis客戶端設置:
添加黑名單IP:
sadd limit:ip:blacklist 10.11.0.148

獲取黑名單IP:
smembers limit:ip:blacklist


10.11.0.215:6379> sadd limit:ip:blacklist 10.11.0.148
10.11.0.215:6379> sadd limit:ip:blacklist 10.11.0.215

10.11.0.215:6379> smembers limit:ip:blacklist
1) "10.11.0.215"
2) "10.11.0.148"
10.11.0.215:6379> smembers limit:ip:blacklist
1) "10.11.0.215"
2) "10.11.0.148"


此方法目前只能實現手動添加黑名單IP進行IP封禁,在某些場景如:半夜如果有人惡意爬取網站服務器可能導致服務器資源耗盡崩潰或者影響業務


下面是改進后的代碼,可以實現自動將訪問頻次過高的IP地址加入黑名單封禁一段時間


nginx.conf配置部分:
location /goodslist {
?? ??? ?set $business "USER";
?? ??? ?access_by_lua_file /usr/local/lua/access_count_limit.lua;
?? ??? ?echo "get goods list success";
?? ?}


lua代碼:

[root@node5 lua]# cat /usr/local/luaaccess_count_limit.lua

local function close_redis(red)if not red thenreturnendlocal pool_max_idle_time = 10000local pool_size = 100local ok, err = red:set_keepalive(pool_max_idle_tme, pool_size)if not ok thenngx.say("set keepalive err : ", err)end endlocal ip_block_time=300 --封禁IP時間(秒) local ip_time_out=30 --指定ip訪問頻率時間段(秒) local ip_max_count=20 --指定ip訪問頻率計數最大值(秒) local BUSINESS = ngx.var.business --nginx的location中定義的業務標識符--連接redis local redis = require "resty.redis" local conn = redis:new() ok, err = conn:connect("10.11.0.215", 6379) conn:set_timeout(2000) --超時時間2秒--如果連接失敗,跳轉到腳本結尾 if not ok then--goto FLAG close_redis(conn) endlocal count, err = conn:get_reused_times() if 0 == count then ----新建連接,需要認證密碼ok, err = conn:auth("redis123")if not ok thenngx.say("failed to auth: ", err)returnend elseif err then ----從連接池中獲取連接,無需再次認證密碼ngx.say("failed to get reused times: ", err)return end--查詢ip是否被禁止訪問,如果存在則返回403錯誤代碼 is_block, err = conn:get(BUSINESS.."-BLOCK-"..ngx.var.remote_addr) if is_block == '1' thenngx.exit(403)close_redis(conn) end--查詢redis中保存的ip的計數器 ip_count, err = conn:get(BUSINESS.."-COUNT-"..ngx.var.remote_addr)if ip_count == ngx.null then --如果不存在,則將該IP存入redis,并將計數器設置為1、該KEY的超時時間為ip_time_outres, err = conn:set(BUSINESS.."-COUNT-"..ngx.var.remote_addr, 1)res, err = conn:expire(BUSINESS.."-COUNT-"..ngx.var.remote_addr, ip_time_out) elseip_count = ip_count + 1 --存在則將單位時間內的訪問次數加1if ip_count >= ip_max_count then --如果超過單位時間限制的訪問次數,則添加限制訪問標識,限制時間為ip_block_timeres, err = conn:set(BUSINESS.."-BLOCK-"..ngx.var.remote_addr, 1)res, err = conn:expire(BUSINESS.."-BLOCK-"..ngx.var.remote_addr, ip_block_time)elseres, err = conn:set(BUSINESS.."-COUNT-"..ngx.var.remote_addr,ip_count)res, err = conn:expire(BUSINESS.."-COUNT-"..ngx.var.remote_addr, ip_time_out)end end-- 結束標記 local ok, err = conn:close()


# redis的數據
10.11.0.215:6379> get USER-COUNT-10.11.0.148
"16"
10.11.0.215:6379> get USER-BLOCK-10.11.0.148
(nil)


四、總結

以上,便是 Nginx+Lua+Redis 實現的 IP 黑名單功能,具有如下優點:

1、配置簡單、輕量,幾乎對服務器性能不產生影響;

2、多臺服務器可以通過Redis實例共享黑名單;

3、動態配置,可以手工或者通過某種自動化的方式設置 Redis 中的黑名單。

轉載于:https://www.cnblogs.com/reblue520/p/11419918.html

總結

以上是生活随笔為你收集整理的openresty开发系列38--通过Lua+Redis 实现动态封禁IP的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。

主站蜘蛛池模板: 看免费一级片 | 黑人100部av解禁片 | 少妇太紧太爽又黄又硬又爽小说 | 在线观看黄色片 | 欧美大片在线播放 | 狠狠躁夜夜躁xxxxaaaa | 成片免费观看视频大全 | 深夜视频免费在线观看 | 欧美乱操| 在线亚洲+欧美+日本专区 | 欧美一区二区在线免费观看 | 天天综合天天 | 欧美资源 | 久久久久久无码午夜精品直播 | 国产精品第157页 | 99精品99 | 欧美成人国产va精品日本一级 | 五月婷婷开心中文字幕 | 美女网站一区 | 一区二区啪啪 | 四虎三级| 三级性生活视频 | 成年人免费视频观看 | 国产成人精品一区二区三区网站观看 | 日韩a级片在线观看 | 黄色免费成人 | 午夜网址| 开元在线观看视频国语 | 后入内射无码人妻一区 | 日本无遮羞调教打屁股网站 | 国产日韩欧美中文字幕 | 一区二区三区视频在线观看 | 国产三级理论 | 成人深夜电影 | 成人在线高清视频 | 亚洲视频在线免费观看 | 免费激情片 | 欧美夜夜骑 | 亚洲xx网| 国产又粗又黄又爽视频 | 在线精品视频免费观看 | 99亚洲天堂 | 青青草91久久久久久久久 | 男人懂得网站 | 久久精工是国产品牌吗 | 色综合99 | 欧洲亚洲自拍 | 日韩中文字幕一区二区三区 | 欧美一区二区三区四 | 成人免费毛片网站 | 国产精品亚洲а∨天堂免在线 | 91精品人妻互换一区二区 | 免费在线看黄网址 | 午夜视频免费在线 | 亚洲一区福利视频 | 国内偷拍久久 | 日韩a级在线观看 | 亚洲av久久久噜噜噜熟女软件 | 日韩在线精品 | 日韩高清毛片 | 亚洲一区观看 | 亚洲av片一区二区三区 | 四虎永久免费 | 亚洲看片网 | 一级片久久 | 国产午夜福利视频在线观看 | 久久久久久国产精品无码 | 国产精品伦理一区 | 亚洲国产福利视频 | 欧美啪啪网| 国产精品jizz在线观看软件 | 亚洲色图偷 | 欧美在线观看一区 | 亚洲丝袜视频 | 成人av一级 | 黄瓜视频在线播放 | 亚洲三级在线 | 国产黄色片在线观看 | 怒海潜沙秦岭神树 | 日韩日b视频| 欧美精品大片 | 日本三级一区二区 | 超碰久操 | av永久免费| 久久精品色| 少妇高潮久久久久久潘金莲 | 中文一区二区在线观看 | 两性免费视频 | 五月天激情在线 | 青草视屏 | 国产男女猛烈无遮挡 | 欧美日韩一区二区三区四区五区 | 午夜精品三级久久久有码 | 穿越异世荒淫h啪肉np文 | 中文字幕日韩精品在线 | 久热99 | 影音先锋 日韩 | 国产又粗又猛又爽69xx | 欧美精品在线视频观看 |