最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Nginx中Lua腳本實現動態(tài)黑名單自動封禁機制

 更新時間:2026年04月27日 08:59:36   作者:舞夢輝影  
本文主要介紹了Nginx中Lua腳本實現動態(tài)黑名單自動封禁機制,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧

為什么直接用 access_by_lua_block 寫封禁邏輯容易失效

因為 Nginx 的 Lua 模塊(OpenResty)中,access_by_lua_block 階段執(zhí)行時,請求尚未進入 upstream 或日志階段,但若后續(xù)有 rewrite_by_lua_block 或其他模塊重寫 URI、跳轉,可能繞過該階段;更關鍵的是,它不自動阻斷后續(xù)處理——你得顯式調用 ngx.exit(403),否則腳本跑完就繼續(xù)往下走。

常見錯誤現象:ngx.var.remote_addr 被封了,但請求仍能訪問后端;或日志里看到 IP 出現在黑名單里,HTTP 狀態(tài)碼卻是 200。

  • 務必在封禁分支末尾加 ngx.exit(403),不能只設變量或寫 Redis
  • 如果用了 try_files 或 error_page 重定向,要確認它們不會覆蓋或跳過 access_by_lua_block
  • 避免在 access_by_lua_block 中做耗時操作(如 HTTP 請求),會阻塞 worker 進程

如何用 Redis + Lua 做毫秒級黑名單匹配

本地內存(如 shared_dict)適合短時頻控,但跨 worker、跨實例的黑名單必須依賴外部存儲。Redis 是最常用選擇,關鍵是用原子操作避免并發(fā)查改導致漏放行。

推薦用 EVAL 執(zhí)行一段內聯(lián) Lua 腳本,一次性完成「查是否存在」+「若存在則返回 1」,不依賴兩次網絡往返:

local exists = redis.call("EXISTS", "blacklist:" .. KEYS[1])
if exists == 1 then
  return 1
else
  return 0
end

在 Nginx 配置中調用:

access_by_lua_block {
  local red = require "resty.redis"
  local r = red:new()
  r:set_timeout(100)
  local ok, err = r:connect("127.0.0.1", 6379)
  if not ok then
    ngx.log(ngx.ERR, "failed to connect to redis: ", err)
    return
  end
  local ip = ngx.var.remote_addr
  local res, err = r:eval(
    "return redis.call('EXISTS', 'blacklist:' .. ARGV[1])",
    0, ip
  )
  if res == 1 then
    ngx.exit(403)
  end
}
  • 不要用 GET + IF 兩步,競態(tài)下可能剛查完就被刪掉
  • Redis key 建議帶前綴(如 blacklist:)并設置 TTL,避免長期堆積
  • 連接池比每次新建連接更高效,可用 resty.redis.connect + set_keepalive

怎么讓封禁規(guī)則支持動態(tài)更新而不 reload Nginx

reload 會中斷連接、丟失共享字典狀態(tài),不適合高頻更新的黑名單。真正可行的方式是:把規(guī)則存 Redis,Nginx 每次請求都實時查——只要 Redis 響應夠快(通常如果你真想降低 Redis 查詢壓力,可以用雙層緩存:先查 shared_dict,未命中再查 Redis,并異步刷新本地緩存(用 lua-resty-lock 防穿透):

local dict = ngx.shared.blacklist_cache
local ip = ngx.var.remote_addr
local cached = dict:get(ip)
if cached == 1 then
  ngx.exit(403)
end
-- 加鎖后查 Redis 并回填
local lock = require "resty.lock":new("locks")
local elapsed, err = lock:lock(ip)
if not elapsed then
  ngx.log(ngx.ERR, "failed to acquire lock: ", err)
  return
end
local red = --[[...redis init...]]
local res, _ = red:eval("return redis.call('EXISTS', 'blacklist:' .. ARGV[1])", 0, ip)
if res == 1 then
  dict:set(ip, 1, 60) -- 緩存 60 秒
  ngx.exit(403)
end
lock:unlock()
  • 別用定時拉?。ㄈ?nbsp;timer.at)同步 Redis 到 shared_dict,worker 間不同步且易超時
  • shared_dict 的 TTL 必須比 Redis 的短,否則會出現“Redis 已解封,本地還攔著”的情況
  • 若業(yè)務對延遲極度敏感,考慮用 Redis 的 SCAN + 本地 Bloom Filter 預篩,但實現復雜度陡增

誤封怎么快速放行又不影響線上

最安全的做法是提供獨立管理接口(比如一個僅限內網訪問的 /api/unban),由運維或自動化腳本調用,而不是手動改 Redis 或 reload。

示例接口只需一行命令:

location /api/unban {
  allow 10.0.0.0/8;
  deny all;
  content_by_lua_block {
    local ip = ngx.var.arg_ip
    if not ip or #ip == 0 then
      ngx.status = 400
      ngx.say("missing ip")
      return
    end
    local red = require "resty.redis":new()
    red:set_timeout(100)
    red:connect("127.0.0.1", 6379)
    red:del("blacklist:" .. ip)
    red:del("blacklist_cache:" .. ip) -- 清本地緩存
    ngx.say("ok")
  }
}
  • 嚴禁開放 DEL * 或無白名單的批量操作接口
  • Redis 的 DEL 是原子的,但 shared_dict 清除需各 worker 協(xié)同,所以建議用 key 名一致的命名空間(如都加 blacklist: 前綴),便于腳本批量清理
  • 記錄所有封禁/解封操作到獨立日志文件(用 ngx.log(ngx.INFO, ...)),排查誤封時比翻 access.log 直觀得多

實際部署時最容易被忽略的是 Redis 連接失敗后的降級策略——默認行為是放行,但有些場景要求“寧可誤殺也不能漏封”,這時就得在 redis:connect 失敗時主動 ngx.exit(503),而不是靜默跳過。這個決策點不在代碼里,而在你的安全等級定義中。

到此這篇關于Nginx中Lua腳本實現動態(tài)黑名單自動封禁機制的文章就介紹到這了,更多相關Nginx Lua動態(tài)黑名單自動封禁內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!

相關文章

  • 對nginx-naxsi白名單規(guī)則詳解

    對nginx-naxsi白名單規(guī)則詳解

    今天小編就為大家分享一篇對nginx-naxsi白名單規(guī)則詳解,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2019-08-08
  • Nginx超時時間的配置說明

    Nginx超時時間的配置說明

    Nginx超時時間非常重要,因為它將直接影響網站的響應速度和用戶體驗,本文主要介紹了Nginx超時時間的配置說明,具有一定的參考價值,感興趣的可以了解一下
    2024-07-07
  • Nginx實現外網訪問內網的步驟詳解

    Nginx實現外網訪問內網的步驟詳解

    外網瀏覽器與內網是不通的,但是外網與中間過渡服務器是通的,中間過渡服務器與內網服務器是通的,這樣在外網訪問過渡服務器時,過渡服務器再跳轉到后臺服務器,本文給大家介紹了Nginx外網訪問內網如何實現步驟,需要的朋友可以參考下
    2023-10-10
  • nginx配置中$http_host、$host、$host:$proxy_port和$host:$server_port區(qū)別解析

    nginx配置中$http_host、$host、$host:$proxy_port和$host:$server_por

    nginx為了實現反向代理的需求而增加了一個ngx_http_proxy_module模塊,其中proxy_set_header指令就是該模塊需要讀取的配置文件,這篇文章主要介紹了nginx配置中$http_host、$host、$host:$proxy_port和$host:$server_port區(qū)別,需要的朋友可以參考下
    2024-03-03
  • nginx作為下載服務器配置過程

    nginx作為下載服務器配置過程

    本文詳細介紹了如何配置Nginx作為下載服務器,包括基本配置指令、location塊配置、Content-Disposition頭部信息、sendfile指令、文件系統(tǒng)權限設置以及訪問控制,通過實驗,驗證了Nginx在文件下載場景中的高效和安全性
    2025-12-12
  • nginx搭建高可用集群的實現方法

    nginx搭建高可用集群的實現方法

    本文主要介紹了nginx搭建高可用集群的實現方法,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2023-01-01
  • nginx處理http請求實現過程解析

    nginx處理http請求實現過程解析

    這篇文章主要介紹了nginx處理http請求實現過程解析,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下
    2020-11-11
  • nginx從編譯安裝到配置文件說明中文詳細介紹

    nginx從編譯安裝到配置文件說明中文詳細介紹

    Nginx配置文件主要分成四部分:main(全局設置)、server(主機設置)、upstream(上游服務器設置,主要為反向代理、負載均衡相關配置)和 location(URL匹配特定位置后的設置)
    2018-10-10
  • nginx proxy_cache批量清除緩存的腳本介紹

    nginx proxy_cache批量清除緩存的腳本介紹

    今天小編就為大家分享一篇關于nginx proxy_cache批量清除緩存的腳本介紹,小編覺得內容挺不錯的,現在分享給大家,具有很好的參考價值,需要的朋友一起跟隨小編來看看吧
    2019-02-02
  • 一句簡單命令重啟nginx

    一句簡單命令重啟nginx

    最近我的多個VPS經常出現502錯誤,經常需要重啟nginx,但網上的很多教程都需要繁瑣的啟動腳本,遠不如apache的重啟命令那么簡單。
    2010-03-03

最新評論

安远县| 凤阳县| 嘉定区| 丰镇市| 平安县| 马边| 延安市| 淅川县| 博湖县| 台南县| 三门县| 鄂托克旗| 进贤县| 桂平市| 兴隆县| 家居| 竹溪县| 九台市| 庆阳市| 汽车| 仙居县| 芒康县| 金乡县| 赣州市| 丹凤县| 通河县| 蚌埠市| 会泽县| 通海县| 简阳市| 宿松县| 青龙| 长阳| 湟源县| 奈曼旗| 武功县| 会宁县| 深州市| 和龙市| 府谷县| 响水县|