// Copyright 2026 tamakyi. All rights reserved. // Use of this source code is governed by a MIT-style // license that can be found in the LICENSE file. package route import ( "testing" "github.com/tamakyi/TamaBox/internal/conf" ) // 这组测试守的是「装配层」而不是「逻辑层」。 // // 背景:蜜罐的封禁通道参数(HoneypotEnabled / HoneypotThreshold / // HoneypotDuration)曾经在 route.New 里漏传,而 autoban.RecordHoneypot 第一行 // 就是 `if !b.honeypotEnabled { return false }` —— 表现为蜜罐命中永不封禁、 // 落库 banned 恒为 false,但所有测试全绿(它们都自建 Banner 并显式传了这些字段)。 // // 因此这里的每个用例都必须经由 newBanner()(生产唯一装配入口), // 绝不能自己构造 autoban.Options。 // swapSecurity 在测试期间覆盖 conf.Security,结束后恢复。 func swapSecurity(t *testing.T) { t.Helper() old := conf.Security t.Cleanup(func() { conf.Security = old }) } // TestNewBannerWiresHoneypotChannel 是这次漏接线的直接回归测试。 func TestNewBannerWiresHoneypotChannel(t *testing.T) { swapSecurity(t) conf.Security.EnableHoneypot = true conf.Security.HoneypotThreshold = 1 conf.Security.HoneypotBanMinutes = 1440 b := newBanner() if !b.RecordHoneypot("203.0.113.9", "/wp-login.php") { t.Fatal("蜜罐开启时 RecordHoneypot 应判定封禁:newBanner 很可能漏传了 HoneypotEnabled") } if !b.IsBanned("203.0.113.9") { t.Fatal("蜜罐命中后 IsBanned 应为 true") } } // TestNewBannerHonorsHoneypotThreshold 验证阈值真的传进去了。 // // 只断言「能封禁」是不够的:漏传 HoneypotThreshold 时 autoban 会兜底成 1, // 一次就封,看起来一切正常。设成 3 才能区分「传了」与「用了默认值」。 func TestNewBannerHonorsHoneypotThreshold(t *testing.T) { swapSecurity(t) conf.Security.EnableHoneypot = true conf.Security.HoneypotThreshold = 3 conf.Security.HoneypotBanMinutes = 60 b := newBanner() for i := 1; i <= 2; i++ { if b.RecordHoneypot("198.51.100.7", "/admin") { t.Fatalf("第 %d 次命中不应封禁(阈值 3)——阈值未接线时会退化为默认 1", i) } } if !b.RecordHoneypot("198.51.100.7", "/admin") { t.Fatal("第 3 次命中应封禁(阈值 3)") } } // TestNewBannerHoneypotIndependentOfAutoBan 守住「两个开关互不连坐」。 // // 线上触发过的组合:运维嫌自动封禁误伤多,关掉 enable_auto_ban; // 结果蜜罐跟着变成只记录不封禁的旁观者。 func TestNewBannerHoneypotIndependentOfAutoBan(t *testing.T) { swapSecurity(t) conf.Security.EnableAutoBan = false conf.Security.EnableHoneypot = true conf.Security.HoneypotThreshold = 1 conf.Security.HoneypotBanMinutes = 60 b := newBanner() if !b.RecordHoneypot("192.0.2.5", "/.env") { t.Fatal("enable_auto_ban=false 不应让蜜罐封禁失效") } if !b.IsBanned("192.0.2.5") { t.Fatal("蜜罐封禁应在 enable_auto_ban=false 时依然生效") } } // TestNewBannerHoneypotDisabled 守住反向:关掉蜜罐就不该凭空封人。 func TestNewBannerHoneypotDisabled(t *testing.T) { swapSecurity(t) conf.Security.EnableHoneypot = false conf.Security.HoneypotThreshold = 1 conf.Security.HoneypotBanMinutes = 1440 b := newBanner() if b.RecordHoneypot("192.0.2.9", "/wp-admin") { t.Fatal("enable_honeypot=false 时不应封禁") } if b.IsBanned("192.0.2.9") { t.Fatal("enable_honeypot=false 时不应产生封禁记录") } }