From b9cde88bf63a9f232c15b179061702532e078b26 Mon Sep 17 00:00:00 2001 From: ryan Date: Sat, 30 May 2026 16:19:55 +0800 Subject: [PATCH] =?UTF-8?q?[=E4=BC=98=E5=8C=96]=20=E9=87=8D=E6=9E=84=20WAF?= =?UTF-8?q?=20=E5=92=8C=20PoW=20=E5=A4=84=E7=90=86=E9=80=BB=E8=BE=91?= =?UTF-8?q?=EF=BC=8C=E4=BD=BF=E7=94=A8=20require=20=E5=8A=A0=E8=BD=BD?= =?UTF-8?q?=E8=BF=90=E8=A1=8C=E6=97=B6=E6=A8=A1=E5=9D=97=EF=BC=8C=E6=9B=B4?= =?UTF-8?q?=E6=96=B0=E7=9B=B8=E5=85=B3=E6=B5=8B=E8=AF=95=E4=BB=A5=E9=AA=8C?= =?UTF-8?q?=E8=AF=81=E6=96=B0=E8=A1=8C=E4=B8=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../internal/nginx/manager_test.go | 18 +++++++-------- openflare_agent/internal/nginx/pow_assets.go | 21 ++++++++++++++++- openflare_agent/internal/nginx/waf_assets.go | 23 ++++++++++++++++++- openflare_server/service/config_version.go | 5 ++-- openflare_server/service/https_phase1_test.go | 4 ++-- 5 files changed, 56 insertions(+), 15 deletions(-) diff --git a/openflare_agent/internal/nginx/manager_test.go b/openflare_agent/internal/nginx/manager_test.go index d7dabb6f..4fe025ae 100644 --- a/openflare_agent/internal/nginx/manager_test.go +++ b/openflare_agent/internal/nginx/manager_test.go @@ -545,7 +545,7 @@ func TestManagerEnsureLuaAssetsWritesReadableFiles(t *testing.T) { if _, err := os.Stat(filepath.Join(manager.LuaDir, "pow", "check.lua")); err != nil { t.Fatalf("failed to stat pow lua file: %v", err) } - data, err := os.ReadFile(filepath.Join(manager.LuaDir, "pow", "check.lua")) + data, err := os.ReadFile(filepath.Join(manager.LuaDir, "pow", "runtime.lua")) if err != nil { t.Fatalf("failed to read pow lua file: %v", err) } @@ -667,11 +667,11 @@ func TestManagerCurrentChecksumIncludesPowConfig(t *testing.T) { } func TestManagedPowLuaFilesUseInternalChallengeFlow(t *testing.T) { - if !strings.Contains(openRestyPowCheckLua, `return ngx.exec("/.within.website/x/cmd/anubis/api/make-challenge")`) { - t.Fatal("expected check.lua to internally execute make-challenge instead of issuing a 302 redirect") + if !strings.Contains(openRestyPowRuntimeLua, `return ngx.exec("/.within.website/x/cmd/anubis/api/make-challenge")`) { + t.Fatal("expected pow runtime lua to internally execute make-challenge instead of issuing a 302 redirect") } - if strings.Contains(openRestyPowCheckLua, "ngx.redirect(") { - t.Fatal("expected check.lua to avoid external redirects for challenge rendering") + if strings.Contains(openRestyPowRuntimeLua, "ngx.redirect(") { + t.Fatal("expected pow runtime lua to avoid external redirects for challenge rendering") } if !strings.Contains(openRestyPowChallengeLua, `

`) { t.Fatal("expected challenge html to include Anubis-compatible title node") @@ -682,11 +682,11 @@ func TestManagedPowLuaFilesUseInternalChallengeFlow(t *testing.T) { if !strings.Contains(openRestyPowChallengeLua, ``) { t.Fatal("expected challenge html to force Anubis frontend to reuse the current URL as redir target") } - if !strings.Contains(openRestyPowCheckLua, `pow_sessions:set(session_key, "1", session_ttl)`) { - t.Fatal("expected check.lua to refresh the PoW session TTL on each valid request") + if !strings.Contains(openRestyPowRuntimeLua, `pow_sessions:set(session_key, "1", session_ttl)`) { + t.Fatal("expected pow runtime lua to refresh the PoW session TTL on each valid request") } - if !strings.Contains(openRestyPowCheckLua, `ngx.header["Set-Cookie"] = session_cookie(cookie_val, session_ttl)`) { - t.Fatal("expected check.lua to refresh the browser session cookie on each valid request") + if !strings.Contains(openRestyPowRuntimeLua, `ngx.header["Set-Cookie"] = session_cookie(cookie_val, session_ttl)`) { + t.Fatal("expected pow runtime lua to refresh the browser session cookie on each valid request") } if !strings.Contains(openRestyPowChallengeLua, `local session_ttl = config.session_ttl or 600`) { t.Fatal("expected challenge.lua to default session TTL to 10 minutes") diff --git a/openflare_agent/internal/nginx/pow_assets.go b/openflare_agent/internal/nginx/pow_assets.go index 1da242aa..31d2eeda 100644 --- a/openflare_agent/internal/nginx/pow_assets.go +++ b/openflare_agent/internal/nginx/pow_assets.go @@ -10,7 +10,10 @@ import ( //go:embed pow_static var powStaticFS embed.FS -const openRestyPowCheckLua = `local source = debug.getinfo(1, "S").source or "" +const openRestyPowRuntimeLua = `local _M = {} + +function _M.check() +local source = debug.getinfo(1, "S").source or "" if string.sub(source, 1, 1) == "@" then local script_path = string.sub(source, 2) local base_dir = string.match(script_path, "^(.*)/pow/[^/]+%.lua$") @@ -158,6 +161,21 @@ ngx.req.set_uri_args({ host = host }) return ngx.exec("/.within.website/x/cmd/anubis/api/make-challenge") +end + +return _M +` + +const openRestyPowCheckLua = `local source = debug.getinfo(1, "S").source or "" +if string.sub(source, 1, 1) == "@" then + local script_path = string.sub(source, 2) + local base_dir = string.match(script_path, "^(.*)/pow/[^/]+%.lua$") + if base_dir and base_dir ~= "" then + package.path = base_dir .. "/?.lua;" .. base_dir .. "/?/init.lua;" .. package.path + end +end + +return require("pow.runtime").check() ` const openRestyPowChallengeLua = `local cjson = require "cjson.safe" @@ -473,6 +491,7 @@ return M func ManagedPowLuaFiles() []protocol.SupportFile { return []protocol.SupportFile{ + {Path: "pow/runtime.lua", Content: openRestyPowRuntimeLua}, {Path: "pow/check.lua", Content: openRestyPowCheckLua}, {Path: "pow/challenge.lua", Content: openRestyPowChallengeLua}, {Path: "pow/verify.lua", Content: openRestyPowVerifyLua}, diff --git a/openflare_agent/internal/nginx/waf_assets.go b/openflare_agent/internal/nginx/waf_assets.go index e43306d7..6f909629 100644 --- a/openflare_agent/internal/nginx/waf_assets.go +++ b/openflare_agent/internal/nginx/waf_assets.go @@ -2,7 +2,10 @@ package nginx import "openflare-agent/internal/protocol" -const openRestyWAFCheckLua = `local cjson = require "cjson.safe" +const openRestyWAFRuntimeLua = `local _M = {} + +function _M.check() +local cjson = require "cjson.safe" local config_dict = ngx.shared.openflare_waf_config @@ -215,10 +218,28 @@ for _, group in ipairs(groups) do end end end + +return "ok" +end + +return _M +` + +const openRestyWAFCheckLua = `local source = debug.getinfo(1, "S").source or "" +if string.sub(source, 1, 1) == "@" then + local script_path = string.sub(source, 2) + local base_dir = string.match(script_path, "^(.*)/waf/[^/]+%.lua$") + if base_dir and base_dir ~= "" then + package.path = base_dir .. "/?.lua;" .. base_dir .. "/?/init.lua;" .. package.path + end +end + +return require("waf.runtime").check() ` func ManagedWAFLuaFiles() []protocol.SupportFile { return []protocol.SupportFile{ + {Path: "waf/runtime.lua", Content: openRestyWAFRuntimeLua}, {Path: "waf/check.lua", Content: openRestyWAFCheckLua}, } } diff --git a/openflare_server/service/config_version.go b/openflare_server/service/config_version.go index c1ebf91f..fe4eb5d9 100644 --- a/openflare_server/service/config_version.go +++ b/openflare_server/service/config_version.go @@ -1264,11 +1264,12 @@ func renderAccessBlock(siteName string, powEnabled bool) string { } return fmt.Sprintf(` set $openflare_waf_site "%s"; access_by_lua_block { - dofile("%s/waf/check.lua") + package.path = "%s/?.lua;%s/?/init.lua;" .. package.path + require("waf.runtime").check() if ngx.ctx.openflare_waf_blocked then return end - dofile("%s/pow/check.lua") + require("pow.runtime").check() } `, escapedSiteName, nginxLuaDirPlaceholder, nginxLuaDirPlaceholder) } diff --git a/openflare_server/service/https_phase1_test.go b/openflare_server/service/https_phase1_test.go index 7de98a9b..598bca07 100644 --- a/openflare_server/service/https_phase1_test.go +++ b/openflare_server/service/https_phase1_test.go @@ -1025,7 +1025,7 @@ func TestPublishConfigVersionDetectsPoWChanges(t *testing.T) { if !strings.Contains(secondRelease.Version.RenderedConfig, "application/javascript js mjs;") { t.Fatal("expected rendered config to serve Anubis module scripts with a JavaScript MIME type") } - if !strings.Contains(secondRelease.Version.RenderedConfig, " dofile(\"__OPENFLARE_LUA_DIR__/waf/check.lua\")\n if ngx.ctx.openflare_waf_blocked then\n return\n end\n dofile(\"__OPENFLARE_LUA_DIR__/pow/check.lua\")") { + if !strings.Contains(secondRelease.Version.RenderedConfig, " package.path = \"__OPENFLARE_LUA_DIR__/?.lua;__OPENFLARE_LUA_DIR__/?/init.lua;\" .. package.path\n require(\"waf.runtime\").check()\n if ngx.ctx.openflare_waf_blocked then\n return\n end\n require(\"pow.runtime\").check()") { t.Fatal("expected combined WAF and PoW access handler to short-circuit before PoW") } locationStart := strings.Index(secondRelease.Version.RenderedConfig, " location / {\n") @@ -1102,7 +1102,7 @@ func TestPublishConfigVersionRendersBasicAuthWithPoW(t *testing.T) { if !strings.Contains(result.Version.RenderedConfig, " return ngx.exit(401)\n end\n }\n") { t.Fatal("expected rendered basic auth Lua block to close the if statement before the nginx block") } - if !strings.Contains(result.Version.RenderedConfig, " dofile(\"__OPENFLARE_LUA_DIR__/pow/check.lua\")") { + if !strings.Contains(result.Version.RenderedConfig, `require("pow.runtime").check()`) { t.Fatal("expected PoW access handler to remain at server scope") } if !strings.Contains(result.Version.RenderedConfig, "proxy_pass http://backend_xbot_example_com_1;") {