Lua URL地址混淆解密
Eave
2026.05.08
Nginx配置lua.gramess.com.conf
server
{
listen 80;
server_name lua.gramess.com;
lua_code_cache on;
access_log /var/log/nginx/lua.gramess.com.log access;
location ~* /gateway
{
set $target '';
access_by_lua_file '/usr/local/nginx/lua/gateway.lua';
proxy_pass http://$target;
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Real-Port $remote_port;
proxy_set_header X-Remote-Addr $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_http_version 1.1;
proxy_set_header Connection "";
}
}
Lua脚本文件gateway.lua
local redis = require("resty.redis")
-- 1. 设置响应头
ngx.header["Content-Type"] = "text/html;charset=UTF-8"
-- 2. 路径验证和参数提取
local action = ngx.var.uri
if #action <= 1 then -- 使用 # 替代 string.len,更高效
ngx.exit(ngx.HTTP_FORBIDDEN)
end
-- 3. 提取 key(复用一次即可)
local key = ngx.var.uri:gsub("^/[a-z]+/", "")
ngx.header["Key"] = key
-- 4. 配置参数(可以提取到文件头部或配置文件)
local config = {
redis_host = "127.0.0.1",
redis_port = 6379,
redis_timeout = 1000 -- ms
}
-- 5. Redis 操作函数(封装可复用)
local function get_from_redis(key)
local red = redis:new()
if not red then
return nil, "failed to create redis object"
end
red:set_timeout(config.redis_timeout)
local ok, err = red:connect(config.redis_host, config.redis_port)
if not ok then
return nil, "connect failed: " .. (err or "unknown")
end
-- 执行查询
local value, err = red:get(key)
-- 归还连接到池(无论成功与否)
local keepalive_ok, keepalive_err = red:set_keepalive(10000, 100)
if not keepalive_ok then
ngx.log(ngx.WARN, "failed to set keepalive: ", keepalive_err)
end
if err then
return nil, err
end
return value, nil
end
-- 6. 执行查询
local server, err = get_from_redis(key)
if err then
-- 记录错误日志
ngx.log(ngx.ERR, "Failed to get: ", key, ", error: ", err)
-- ngx.status = ngx.HTTP_NOT_FOUND
ngx.header["Content-Type"] = "application/json;charset=UTF-8"
ngx.say('{"code":500,"message":"Failed to get: ' .. err .. '"}')
ngx.exit(ngx.HTTP_NOT_FOUND)
end
-- 7. 处理空值和查询参数
if server == ngx.null or server == "" then
-- 记录错误日志
ngx.log(ngx.ERR, "Not Found: ", key)
-- ngx.status = ngx.HTTP_NOT_FOUND
ngx.header["Content-Type"] = "application/json;charset=UTF-8"
ngx.say('{"code":500,"message":"Not Found: ' .. key .. '"}')
ngx.exit(ngx.HTTP_NOT_FOUND)
end
-- 如果 key 包含 IP:Port 格式,提取纯 URI 路径
local function strip_ip_port(key_str)
if not key_str or key_str == "" then
return key_str
end
-- 匹配并移除 IP:Port 或 IP 格式
-- 支持格式: 10.10.10.110:80/path 或 10.10.10.110/path
local stripped = key_str:gsub("^%d+%.%d+%.%d+%.%d+:?%d*", "")
-- 如果移除后为空或只有斜杠,返回原值(避免丢失数据)
if stripped == "" or stripped == "/" then
return key_str
end
return stripped
end
ngx.header["Origin-Url"] = strip_ip_port(server)
-- 8. 拼接查询参数
local query_string = ngx.var.QUERY_STRING
if query_string and query_string ~= "" then
server = server .. "?" .. query_string
end
-- 9. 设置变量供后续代理使用
ngx.var.target = server
-- 10. 可选:记录访问日志
ngx.log(ngx.INFO, string.format("Redirect: key=%s, target=%s", key, server))