diff --git a/src/plugins/third_party/auth-plugin.lua b/src/plugins/third_party/auth-plugin.lua
new file mode 100644
index 0000000..3fd305c
--- /dev/null
+++ b/src/plugins/third_party/auth-plugin.lua
@@ -0,0 +1,150 @@
+---
+--- 作者: MCQSJ(https://github.com/MCQSJ)
+--- 更新日期: 2024/12/21
+---
+
+local ngx = ngx
+local ngx_log = ngx.log
+local ngx_ERR = ngx.ERR
+local ngx_print = ngx.print
+local ngx_exit = ngx.exit
+local ngx_today = ngx.today
+local ngx_kv = ngx.shared
+
+local _M = {
+ version = 0.1,
+ name = "auth-plugin" -- 插件名称
+}
+
+-- 配置
+local valid_domains = {
+ "test.com", -- 需要保护的域名列表
+ "test1.cn"
+}
+
+local valid_username = "admin"
+local valid_password = "password123" -- 强密码建议修改
+local session_duration = 7200 -- 2小时,以秒为单位
+local max_login_attempts = 5 -- 最大登录失败次数
+
+local function escape_html(str)
+ if not str then return "" end
+ local replacements = {
+ ["&"] = "&",
+ ["<"] = "<",
+ [">"] = ">",
+ ['"'] = """,
+ ["'"] = "'",
+ }
+ return (str:gsub("[&<>'\"]", function(c) return replacements[c] end))
+end
+
+local function get_login_page(req_uri, error_message)
+ local escaped_error_message = escape_html(error_message or "")
+ local form_action = escape_html(req_uri or "/")
+
+ return [[
+
+
+
+
+
+ 身份验证
+
+
+
+
+
身份验证
+ ]] .. (escaped_error_message ~= "" and '
' .. escaped_error_message .. '
' or "") .. [[
+
+
您的访问受保护,请输入正确的账号密码。
+
+
+
+ ]]
+end
+
+local function validate_login(waf)
+ local form = waf.form["FORM"]
+ if form then
+ local username = form["username"]
+ local password = form["password"]
+ if username == valid_username and password == valid_password then
+ return true
+ end
+ end
+ return false
+end
+
+function _M.req_post_filter(waf)
+ local host = waf.host
+ local req_uri = waf.reqUri
+ local method = waf.method
+
+ local is_protected = false
+ for _, domain in ipairs(valid_domains) do
+ if string.lower(host) == string.lower(domain) then
+ is_protected = true
+ break
+ end
+ end
+
+ if not is_protected then
+ return
+ end
+
+ local login_attempts_key = "login_attempts:" .. waf.ip .. ":" .. host
+ local login_attempts = ngx_kv.ipCache and ngx_kv.ipCache:get(login_attempts_key) or 0
+
+ if login_attempts >= max_login_attempts then
+ ngx_kv.ipBlock:incr(waf.ip, 1, 0)
+ waf.msg = "IP因登录失败次数过多已被拦截"
+ waf.rule_id = 10001
+ waf.deny = true
+ return ngx_exit(403)
+ end
+
+ local session_key = "auth:" .. waf.ip .. ":" .. host
+ local is_authenticated = ngx_kv.ipCache and ngx_kv.ipCache:get(session_key)
+
+ if not is_authenticated then
+ if method == "POST" then
+ if validate_login(waf) then
+ ngx_kv.ipCache:set(session_key, true, session_duration)
+ ngx_kv.ipCache:delete(login_attempts_key)
+ return
+ else
+ login_attempts = login_attempts + 1
+ ngx_kv.ipCache:set(login_attempts_key, login_attempts, 3600)
+
+ local error_message = "用户名或密码错误,请重试。"
+ ngx.header.content_type = "text/html; charset=utf-8"
+ return ngx.print(get_login_page(req_uri, error_message))
+ end
+ else
+ ngx.header.content_type = "text/html; charset=utf-8"
+ return ngx.print(get_login_page(req_uri, nil))
+ end
+ end
+
+end
+
+return _M
diff --git a/src/rules/third_party/brute-force-login-prevention.lua b/src/rules/third_party/brute-force-login-prevention.lua
new file mode 100644
index 0000000..770f1ba
--- /dev/null
+++ b/src/rules/third_party/brute-force-login-prevention.lua
@@ -0,0 +1,40 @@
+--[[
+规则名称: 登录爆破防护
+过滤阶段: 请求阶段
+危险等级: 高危
+规则描述: 针对路径中包含登录、注册等关键词的URL进行防护
+作者: MCQSJ(https://github.com/MCQSJ)
+更新日期: 2024/12/21
+--]]
+
+-- 配置参数
+local threshold = 30 -- 错误次数阈值
+local timeWindow = 180 -- 时间窗口,单位为秒
+local banDuration = 1440 * 60 -- 封禁时间,单位为秒
+
+local sh = waf.ipCache
+local bruteForceKey = 'brute-force-login:' .. waf.ip
+
+-- 定义特征路径关键词列表
+local targetPaths = { "login", "signin", "signup", "register", "reset", "passwd", "account", "user" }
+
+if not waf.pmMatch(waf.toLower(waf.uri), targetPaths) then
+ return false
+end
+
+local requestCount, flag = sh:get(bruteForceKey)
+if not requestCount then
+ sh:set(bruteForceKey, 1, timeWindow, 1)
+else
+ if flag == 2 then
+ return waf.block(true)
+ end
+
+ sh:incr(bruteForceKey, 1)
+ if requestCount + 1 > threshold then
+ sh:set(bruteForceKey, requestCount + 1, banDuration, 2)
+ return true, "检测到登录接口发生爆破攻击,已封禁IP", true
+ end
+end
+
+return false
diff --git a/src/rules/third_party/frequent-block-detection.lua b/src/rules/third_party/frequent-block-detection.lua
new file mode 100644
index 0000000..a3a7007
--- /dev/null
+++ b/src/rules/third_party/frequent-block-detection.lua
@@ -0,0 +1,31 @@
+--[[
+规则名称: 高频攻击防护
+过滤阶段: 请求阶段
+危险等级: 高危
+规则描述: 针对发起高频率攻击的行为进行防护
+作者: MCQSJ(https://github.com/MCQSJ)
+更新日期: 2024/12/21
+!!!注意: 因为南墙WAF特性,此规则生效对规则ID有要求,需要将此规则与南墙自带规则的第一个规则交换位置才能生效!!!
+]]
+
+-- 配置参数
+local threshold = 60 -- 错误次数阈值
+local banDuration = 1440 * 60 -- 封禁时间,单位为秒
+
+local sh = waf.ipCache
+local ip_stats = waf.ipBlock
+local ip = waf.ip
+local block_key = "blocked-" .. ip
+
+local c, f = sh:get(block_key)
+if c and f == 2 then
+ return waf.block(true)
+end
+
+local recent_count = ip_stats:get(ip)
+if recent_count and recent_count > threshold then
+ sh:set(block_key, 1, banDuration, 2)
+ return true, "IP频繁触发拦截,已被拉黑", true
+end
+
+return false
diff --git a/src/rules/third_party/high-frequency-error-protection.lua b/src/rules/third_party/high-frequency-error-protection.lua
new file mode 100644
index 0000000..b0a162f
--- /dev/null
+++ b/src/rules/third_party/high-frequency-error-protection.lua
@@ -0,0 +1,47 @@
+--[[
+规则名称: 高频错误防护
+过滤阶段: 返回HTTP头阶段
+危险等级: 中危
+规则描述: 针对频繁触发错误的请求的行为进行防护
+作者: MCQSJ(https://github.com/MCQSJ)
+更新日期: 2024/12/21
+--]]
+
+local function isSpecifiedError(status)
+ local allowed_errors = {400, 401, 403, 404, 405, 429, 444}
+ return waf.inArray(status, allowed_errors)
+end
+
+-- 配置参数
+local threshold = 10 -- 错误次数阈值
+local timeWindow = 60 -- 时间窗口,单位为秒
+local banDuration = 1440 * 60 -- 封禁时间,1440分钟 = 86400秒
+
+local ip = waf.ip
+
+local status = waf.status
+
+if not isSpecifiedError(status) then
+ return false
+end
+
+local errorCache = waf.ipCache
+local errorKey = "error:" .. ip
+
+local errorCount, flag = errorCache:get(errorKey)
+
+if not errorCount then
+ errorCache:set(errorKey, 1, timeWindow)
+else
+ if flag == 2 then
+ return waf.block(true)
+ end
+
+ errorCache:incr(errorKey, 1)
+ if errorCount + 1 >= threshold then
+ errorCache:set(errorKey, errorCount + 1, banDuration, 2)
+ return true, "高频错误触发,IP已被封禁", true
+ end
+end
+
+return false