mirror of
https://github.com/Rain-kl/OpenFlare.git
synced 2026-10-10 17:26:38 +08:00
[功能] POW 有效期优化
This commit is contained in:
@@ -1003,6 +1003,18 @@ func TestManagedPowLuaFilesUseInternalChallengeFlow(t *testing.T) {
|
|||||||
if !strings.Contains(openRestyPowChallengeLua, `<script id="anubis_public_url" type="application/json">"__openflare_internal__"</script>`) {
|
if !strings.Contains(openRestyPowChallengeLua, `<script id="anubis_public_url" type="application/json">"__openflare_internal__"</script>`) {
|
||||||
t.Fatal("expected challenge html to force Anubis frontend to reuse the current URL as redir target")
|
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(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(openRestyPowChallengeLua, `local session_ttl = config.session_ttl or 600`) {
|
||||||
|
t.Fatal("expected challenge.lua to default session TTL to 10 minutes")
|
||||||
|
}
|
||||||
|
if !strings.Contains(openRestyPowVerifyLua, `local session_ttl = challenge_info.session_ttl or 600`) {
|
||||||
|
t.Fatal("expected verify.lua to default session TTL to 10 minutes")
|
||||||
|
}
|
||||||
if !strings.Contains(openRestyPowVerifyLua, `if ngx.var.scheme == "https" then`) {
|
if !strings.Contains(openRestyPowVerifyLua, `if ngx.var.scheme == "https" then`) {
|
||||||
t.Fatal("expected verify.lua to only mark the session cookie as Secure for HTTPS requests")
|
t.Fatal("expected verify.lua to only mark the session cookie as Secure for HTTPS requests")
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -25,6 +25,14 @@ local policy = require "pow.policy"
|
|||||||
local pow_config_dict = ngx.shared.openflare_pow_config
|
local pow_config_dict = ngx.shared.openflare_pow_config
|
||||||
local pow_sessions = ngx.shared.openflare_pow_sessions
|
local pow_sessions = ngx.shared.openflare_pow_sessions
|
||||||
|
|
||||||
|
local function session_cookie(value, ttl)
|
||||||
|
local cookie = "__openflare_pow=" .. value .. "; Path=/; HttpOnly; SameSite=Lax; Max-Age=" .. tostring(ttl)
|
||||||
|
if ngx.var.scheme == "https" then
|
||||||
|
cookie = cookie .. "; Secure"
|
||||||
|
end
|
||||||
|
return cookie
|
||||||
|
end
|
||||||
|
|
||||||
-- Lazy-load pow_config from file; reload when content changes
|
-- Lazy-load pow_config from file; reload when content changes
|
||||||
local function load_pow_config()
|
local function load_pow_config()
|
||||||
local config_paths = {
|
local config_paths = {
|
||||||
@@ -95,6 +103,7 @@ if not route_config.enabled then
|
|||||||
end
|
end
|
||||||
|
|
||||||
local config = route_config.config or {}
|
local config = route_config.config or {}
|
||||||
|
local session_ttl = config.session_ttl or 600
|
||||||
local uri = ngx.var.uri or ""
|
local uri = ngx.var.uri or ""
|
||||||
local ua = ngx.var.http_user_agent or ""
|
local ua = ngx.var.http_user_agent or ""
|
||||||
local remote_ip = ngx.var.remote_addr or ""
|
local remote_ip = ngx.var.remote_addr or ""
|
||||||
@@ -123,8 +132,11 @@ end
|
|||||||
-- Check valid session cookie
|
-- Check valid session cookie
|
||||||
local cookie_val = ngx.var["cookie___openflare_pow"]
|
local cookie_val = ngx.var["cookie___openflare_pow"]
|
||||||
if cookie_val and cookie_val ~= "" then
|
if cookie_val and cookie_val ~= "" then
|
||||||
local session_data = pow_sessions:get(host .. ":" .. cookie_val)
|
local session_key = host .. ":" .. cookie_val
|
||||||
|
local session_data = pow_sessions:get(session_key)
|
||||||
if session_data then
|
if session_data then
|
||||||
|
pow_sessions:set(session_key, "1", session_ttl)
|
||||||
|
ngx.header["Set-Cookie"] = session_cookie(cookie_val, session_ttl)
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@@ -187,7 +199,7 @@ local config = route_config.config or {}
|
|||||||
local difficulty = config.difficulty or 4
|
local difficulty = config.difficulty or 4
|
||||||
local algorithm = config.algorithm or "fast"
|
local algorithm = config.algorithm or "fast"
|
||||||
local challenge_ttl = config.challenge_ttl or 300
|
local challenge_ttl = config.challenge_ttl or 300
|
||||||
local session_ttl = config.session_ttl or 86400
|
local session_ttl = config.session_ttl or 600
|
||||||
|
|
||||||
-- Generate challenge data without depending on ngx.random_bytes, which is not
|
-- Generate challenge data without depending on ngx.random_bytes, which is not
|
||||||
-- available in every OpenResty runtime build.
|
-- available in every OpenResty runtime build.
|
||||||
@@ -307,7 +319,7 @@ end
|
|||||||
local challenge_data = challenge_info.data or ""
|
local challenge_data = challenge_info.data or ""
|
||||||
local difficulty = challenge_info.difficulty or 4
|
local difficulty = challenge_info.difficulty or 4
|
||||||
local host = challenge_info.host or ngx.var.host or ""
|
local host = challenge_info.host or ngx.var.host or ""
|
||||||
local session_ttl = challenge_info.session_ttl or 86400
|
local session_ttl = challenge_info.session_ttl or 600
|
||||||
|
|
||||||
-- Compute SHA-256(challenge_data + nonce)
|
-- Compute SHA-256(challenge_data + nonce)
|
||||||
local calc_string = challenge_data .. tostring(math.floor(nonce))
|
local calc_string = challenge_data .. tostring(math.floor(nonce))
|
||||||
|
|||||||
@@ -1,6 +1,9 @@
|
|||||||
package service
|
package service
|
||||||
|
|
||||||
import "testing"
|
import (
|
||||||
|
"strings"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
func TestGetActiveConfigForAgentIncludesPoWConfig(t *testing.T) {
|
func TestGetActiveConfigForAgentIncludesPoWConfig(t *testing.T) {
|
||||||
setupServiceTestDB(t)
|
setupServiceTestDB(t)
|
||||||
@@ -39,3 +42,37 @@ func TestGetActiveConfigForAgentIncludesPoWConfig(t *testing.T) {
|
|||||||
t.Fatal("expected agent config to include pow_config.json support file")
|
t.Fatal("expected agent config to include pow_config.json support file")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestGetActiveConfigForAgentUsesTenMinutePoWSessionDefault(t *testing.T) {
|
||||||
|
setupServiceTestDB(t)
|
||||||
|
|
||||||
|
_, err := CreateProxyRoute(ProxyRouteInput{
|
||||||
|
Domain: "pow-default.example.com",
|
||||||
|
OriginURL: "https://origin.internal",
|
||||||
|
Enabled: true,
|
||||||
|
PoWEnabled: true,
|
||||||
|
PoWConfig: `{}`,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("CreateProxyRoute failed: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if _, err := PublishConfigVersion("root"); err != nil {
|
||||||
|
t.Fatalf("PublishConfigVersion failed: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
activeConfig, err := GetActiveConfigForAgent()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("GetActiveConfigForAgent failed: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, file := range activeConfig.SupportFiles {
|
||||||
|
if file.Path == "pow_config.json" {
|
||||||
|
if !strings.Contains(file.Content, `"session_ttl":600`) {
|
||||||
|
t.Fatalf("expected default PoW session TTL to be 600 seconds, got %s", file.Content)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
t.Fatal("expected agent config to include pow_config.json support file")
|
||||||
|
}
|
||||||
|
|||||||
@@ -1097,7 +1097,7 @@ func defaultPoWConfig() ProxyRoutePoWConfig {
|
|||||||
return ProxyRoutePoWConfig{
|
return ProxyRoutePoWConfig{
|
||||||
Difficulty: 4,
|
Difficulty: 4,
|
||||||
Algorithm: "fast",
|
Algorithm: "fast",
|
||||||
SessionTTL: 86400,
|
SessionTTL: 600,
|
||||||
ChallengeTTL: 300,
|
ChallengeTTL: 300,
|
||||||
Whitelist: ProxyRoutePoWListConfig{IPs: []string{}, IPCidrs: []string{}, Paths: []string{}, PathRegexes: []string{}, UserAgents: []string{}},
|
Whitelist: ProxyRoutePoWListConfig{IPs: []string{}, IPCidrs: []string{}, Paths: []string{}, PathRegexes: []string{}, UserAgents: []string{}},
|
||||||
Blacklist: ProxyRoutePoWListConfig{IPs: []string{}, IPCidrs: []string{}, Paths: []string{}, PathRegexes: []string{}, UserAgents: []string{}},
|
Blacklist: ProxyRoutePoWListConfig{IPs: []string{}, IPCidrs: []string{}, Paths: []string{}, PathRegexes: []string{}, UserAgents: []string{}},
|
||||||
|
|||||||
@@ -806,7 +806,7 @@ function PowSection({
|
|||||||
pow_enabled: route.pow_enabled,
|
pow_enabled: route.pow_enabled,
|
||||||
difficulty: powConfig?.difficulty ?? 4,
|
difficulty: powConfig?.difficulty ?? 4,
|
||||||
algorithm: powConfig?.algorithm ?? 'fast',
|
algorithm: powConfig?.algorithm ?? 'fast',
|
||||||
session_ttl: powConfig?.session_ttl ?? 86400,
|
session_ttl: powConfig?.session_ttl ?? 600,
|
||||||
challenge_ttl: powConfig?.challenge_ttl ?? 300,
|
challenge_ttl: powConfig?.challenge_ttl ?? 300,
|
||||||
whitelist: buildPowListFromConfig(powConfig?.whitelist),
|
whitelist: buildPowListFromConfig(powConfig?.whitelist),
|
||||||
blacklist: buildPowListFromConfig(powConfig?.blacklist),
|
blacklist: buildPowListFromConfig(powConfig?.blacklist),
|
||||||
@@ -818,7 +818,7 @@ function PowSection({
|
|||||||
pow_enabled: route.pow_enabled,
|
pow_enabled: route.pow_enabled,
|
||||||
difficulty: powConfig?.difficulty ?? 4,
|
difficulty: powConfig?.difficulty ?? 4,
|
||||||
algorithm: powConfig?.algorithm ?? 'fast',
|
algorithm: powConfig?.algorithm ?? 'fast',
|
||||||
session_ttl: powConfig?.session_ttl ?? 86400,
|
session_ttl: powConfig?.session_ttl ?? 600,
|
||||||
challenge_ttl: powConfig?.challenge_ttl ?? 300,
|
challenge_ttl: powConfig?.challenge_ttl ?? 300,
|
||||||
whitelist: buildPowListFromConfig(powConfig?.whitelist),
|
whitelist: buildPowListFromConfig(powConfig?.whitelist),
|
||||||
blacklist: buildPowListFromConfig(powConfig?.blacklist),
|
blacklist: buildPowListFromConfig(powConfig?.blacklist),
|
||||||
@@ -904,8 +904,8 @@ function PowSection({
|
|||||||
</ResourceField>
|
</ResourceField>
|
||||||
|
|
||||||
<ResourceField
|
<ResourceField
|
||||||
label="会话有效期(秒)"
|
label="会话空闲有效期(秒)"
|
||||||
hint="通过验证后 Cookie 的有效期。"
|
hint="通过验证后,若在此时间内没有新请求,Cookie 会失效;每次访问会自动续期。默认 600 秒。"
|
||||||
error={form.formState.errors.session_ttl?.message}
|
error={form.formState.errors.session_ttl?.message}
|
||||||
>
|
>
|
||||||
<ResourceInput
|
<ResourceInput
|
||||||
|
|||||||
Reference in New Issue
Block a user