lua_shared_dict blacklist 20m;
server {
...
access_by_lua_block {
local ip = ngx.var.remote_addr
local uri = string.lower(ngx.unescape_uri(ngx.var.request_uri))
local dict = ngx.shared.blacklist
-- 特殊放行规则:证书验证路径
if uri:find("^/%.well%-known") then
return
end
-- 使用 table 匹配更多信任 IP
local trusted_ips = {
["127.0.0.1"] = true,
["::1"] = true,
-- ["其他信任内网IP"] = true
}
if trusted_ips[ip] then
return
end
-- 已封禁直接丢弃
if dict:get(ip) then
return ngx.exit(444)
end
-- 深度检测敏感词
local forbidden_keywords = {
-- 【PHP 特征】
"%.php", "wp%-", "xmlrpc", "phpmyadmin", "pma", "thinkphp", "magento", "composer%.",
-- 【Python 特征】
"/flask/", "/django/", "/python/", "%.py", "wsgi",
-- 【Node.js 特征】
"node_modules", "package%.json", "package%-lock", "%.js.map", "pm2",
-- 【ASP.NET/C# 特征】
"%.aspx", "%.asp", "%.ashx", "%.asmx", "web%.config", "bin/",
-- 敏感文件与备份
"%.env", "%.bak", "%.sql", "%.old", "%.save", "%.swp", "%.git", "%.svn",
-- 框架指纹 (WordPress, Laravel, SpringBoot, ThinkPHP等)
"wp%-", "xmlrpc", "actuator", "swagger", "api%-docs", "_profiler", "think",
-- 常见扫描目标
"phpinfo", "phpmyadmin", "composer%.", "package%.json",
"magento", "solr", "nacos", "web%-inf",
"/flask/", "/django/", "/python/", "node_modules"
}
for _, keyword in ipairs(forbidden_keywords) do
if uri:match(keyword) then
dict:set(ip, true, 3600) -- 封1小时
ngx.log(ngx.WARN, "[SECURITY] 拦截到深度扫描: ", uri, " 来自: ", ip)
return ngx.exit(444)
end
end
}
#########################################
# 用法
# 域名访问(需要配置allow x.x.x.x)
# curl "https://portal.valuetodays.xyz/manage_blacklist?action=list&token=TOKEN"
# curl "https://portal.valuetodays.xyz/manage_blacklist?action=flush&token=TOKEN"
# 本机访问
# curl -k -H "Host: portal.valuetodays.xyz" "https://127.0.0.1/manage_blacklist?action=list&token=TOKEN"
# curl -k -H "Host: portal.valuetodays.xyz" "https://127.0.0.1/manage_blacklist?action=flush&token=TOKEN"
#
###########################
# 1. 黑名单管理接口 (带 Token 保护)
location ^~ /manage_blacklist {
# Nginx 指令写在外面
default_type text/plain;
# 如果需要 IP 限制,在这里放开
allow 127.0.0.1;
allow 115.190.13.122; # 机器所在公网ip
deny all;
content_by_lua_block {
-- 获取参数
local args = ngx.req.get_uri_args()
local token = args["token"]
local action = args["action"]
local ip = args["ip"]
-- 1. 安全校验:验证 Token
-- 这里的 token 值请确保与你 curl 时一致
if token ~= "111111" then
ngx.status = 403
ngx.say("Detected Your IP: ", ngx.var.remote_addr)
ngx.say("Forbidden: Invalid Token")
return ngx.exit(403)
end
local dict = ngx.shared.blacklist
-- 2. 逻辑分发
if action == "list" then
local keys = dict:get_keys(20)
ngx.say("Detected Your IP: " .. ngx.var.remote_addr)
ngx.say("--- Blacklisted IPs (First 20) ---")
for _, k in ipairs(keys) do
ngx.say(k)
end
elseif action == "delete" and ip then
dict:delete(ip)
ngx.say("Success: IP " .. tostring(ip) .. " removed.")
elseif action == "flush" then
dict:flush_all()
ngx.say("Success: Blacklist cleared.")
else
ngx.say("Detected Your IP: ", ngx.var.remote_addr)
ngx.say("Usage: ?action=list&token=YOUR_TOKEN")
end
}
}
...
}作者:张三 创建时间:2026-08-26 17:54
最后编辑:张三 更新时间:2026-08-26 17:56
最后编辑:张三 更新时间:2026-08-26 17:56