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;") {