fix(conf): 配置键名容错 + 未知键告警 + 蜜罐保留期缺省值修正
现场故障:配置写 `honeypot_retention_days <= 30`,日志却报
「蜜罐自动清理未启用:honeypot_retention_days <= 0」。
根因(实测 ini v1.67.0 行为确认):
1. 键名多一个 t(retention vs retain)→ ini 对未知键**静默忽略**,保留期成 0;
2. `<= 30` 这种写法让 ini 把键名解析成 "honeypot_retention_days <"
(带尾随比较符),更加匹配不上;
3. 警告文案里写的也是错键名,等于在误导运维往错的键上配。
修复(三层):
- 键名归一化(internal/conf/keynorm.go):修剪首尾空白、剥掉尾随 `<` `>`
`=` 等比较符残留,并按别名表纠正常见误拼。归一化结果必须命中该段
合法键名白名单才会被采用 —— 不认识的键不猜,交给未知键告警。
- 未知键告警(internal/conf/unknown.go):启动时逐段比对键名,无法识别的
键 WARN 出来并给出最接近的合法键名建议。合法键名由反射从结构体 ini tag
得出(单一事实来源,新增配置项自动纳入,不会脱节)。
- 缺省值语义修正(internal/conf/honeypot_defaults.go):
* 保留期缺省 30 天(原先零值 0 = 永不清理);显式 <= 0 也回退 30。
要关闭自动清理请用 honeypot_auto_clean = false。
* honeypot_auto_clean 缺省 true。原先靠 bool 零值,ini 的 bool 解析是
「有键才赋值」,未配置与显式关闭无法区分 → 老配置升级上来自动清理
实际是关着的。现改用 HasKey 判定。
* honeypot_max_rows 缺省 200000;显式 0 = 不限(会告警提醒只增不减)。
* honeypot_threshold 缺省 1。
实测 ini 行为(探针程序,已删):
- 键缺失或值非法时 MapTo **不覆盖**预置默认值 → 可安全预置缺省值;
- 键名大小写敏感(Honeypot_Auto_Clean 不生效);
- HasKey 能区分「缺失」与「显式 0」;
- 段不存在时 MapTo 返回 nil 且不修改目标。
顺带清理 app.sample.ini 里的两条死配置(app.title / server.xsrf_expire):
代码中从未读取(站点标题走 i18n),留着会让新检测对官方模板误报。
验证:
- 用现场原始配置端到端复现 → 归一化后保留期 30 天、自动清理开启、上限 20 万,
日志明确说明「配置键名已自动纠正」;
- 误拼键(honeypot_autoclean / honeypot_max_row)自动纠正;未知键(totally_bogus)
WARN 告警;
- 显式 honeypot_auto_clean = false 被尊重为关闭;完全未配置时缺省开启;
- 新增 TestSampleIniHasNoUnknownKeys 回归检测:官方样例配置零误报;
- go build ./... + go test -timeout 600s ./... 全绿,go vet 无输出。
This commit is contained in:
+11
-4
@@ -85,20 +85,27 @@ var (
|
||||
EnableHoneypot bool `ini:"enable_honeypot"`
|
||||
// HoneypotPaths 追加自定义诱饵路径(逗号分隔),与内置清单并集。
|
||||
HoneypotPaths string `ini:"honeypot_paths"`
|
||||
// HoneypotRetainDays 蜜罐命中记录的保留天数,到期由 CLI 清理。
|
||||
// HoneypotRetainDays 蜜罐命中记录的保留天数,到期自动清理。
|
||||
// ⚠️ 键名是 honeypot_retain_days(没有 tion)。写成 honeypot_retention_days
|
||||
// 会被 ini 静默忽略 —— 现场踩过这个坑,表现为「自动清理未启用」。
|
||||
// 缺省 30 天(见 sanitizeHoneypot);显式 <= 0 也回退 30。
|
||||
// 要关闭自动清理请用 honeypot_auto_clean = false。
|
||||
HoneypotRetainDays int `ini:"honeypot_retain_days"`
|
||||
// HoneypotAutoClean 是否启用蜜罐记录的后台自动保留期清理。
|
||||
// 默认 true:honeypot_hits 是只追加的审计表,写入完全由外部扫描流量驱动,
|
||||
// 缺省 true:honeypot_hits 是只追加的审计表,写入完全由外部扫描流量驱动,
|
||||
// 没有自动清理的话表体积只增不减(这是「数据库被扫描撑爆」的真实路径)。
|
||||
// 关闭后仍可手动执行 TamaBox honeypot prune。
|
||||
// ⚠️ 缺省值靠 HasKey 判定(见 sanitizeHoneypot):ini 的 bool 解析是
|
||||
// 「有键才赋值」,若只看零值就无法区分「未配置」与「显式关闭」。
|
||||
HoneypotAutoClean bool `ini:"honeypot_auto_clean"`
|
||||
// HoneypotMaxRows 蜜罐命中记录的行数上限。留空或 <=0 表示不设上限。
|
||||
// HoneypotMaxRows 蜜罐命中记录的行数上限。缺省 200000(约 53 MB)。
|
||||
// 显式写 0 表示不设上限(逃生口,会告警提醒表只增不减)。
|
||||
// 保留期是时间维度的上界,但攻击者可以用海量源 IP 在保留期内把表撑爆,
|
||||
// 这是第二道闸。实测单行约 281 字节(含索引,常规 UA),20 万行约 53 MB。
|
||||
HoneypotMaxRows int `ini:"honeypot_max_rows"`
|
||||
// HoneypotThreshold 窗口内蜜罐命中多少次即封禁。默认 1(一次即封):
|
||||
// 蜜罐路径与真实业务路由零交集,正常访客不可能命中,一次即足以判定扫描器。
|
||||
// 留空回退 1。
|
||||
// 缺省回退 1(见 sanitizeHoneypot)。
|
||||
HoneypotThreshold int `ini:"honeypot_threshold"`
|
||||
// HoneypotBanMinutes 蜜罐封禁时长(分钟)。留空则复用 ban_duration_minutes。
|
||||
HoneypotBanMinutes int `ini:"honeypot_ban_minutes"`
|
||||
|
||||
Reference in New Issue
Block a user