5.4 KiB
5.4 KiB
2026-10-21
扫描者处置方案设计(未实施,仅设计文档)
- 触发:线上频繁收到「疑似批量扫描已自动封禁」告警,命中路径以 wp 探测 +
/.ssh/**为主,来源多 Azure 云 IP 池。 - 实测纠正一处错误认知:
internal/route/route.go:432的注释称「flamego 的 NotFound 会先写 404 状态再 Redirect」—— 错的。flamego v1.9.4 的NotFound只执行 handler,不写状态码;ctx.Redirect("/")实测输出 **302 → "/"。 最小复现验证:/wp-admin/includes/...与/.ssh/id_rsa` 均得 302 + Location:/。 后果:扫描器跟随重定向 → 每个探测路径都触发一次首页渲染(1C1G 纯浪费),且被判为「站点有价值」。 同时告警邮件文案「产生大量 404」与实际 302 不符。 - 方案分五层(L0 CDN 路径/UA 规则 → L1 真 404 分流 → L2 蜜罐假文件/假凭据 → L3 tarpit + 递进封禁 → L4 上游 abuse 举报):
- 核心判断:对云厂商僵尸网络做 IP 封禁无效,有效的是按路径在 CDN 拦 + 蜜罐取证 + 上游举报。
- 明确排除反向攻击/DoS/回打(法律风险 + Azure 共享出口伤及无辜 + 招致 CDN 封站)。
- 蜜罐:命中
/.ssh/id_rsa、/.env、/wp-login.php等诱饵路径 → 短路返回假内容(含 canary 标记)+ 永久封禁 + 留证。 - 封禁需落库(当前内存 map,重启清零)+ 时长递进 15m→1h→6h→24h→7d→永久 + 多维(IP / IPv6 /64 / UA 家族)。
- tarpit 必须带全局并发上限 + 单连接超时,否则 1C1G 自身变 DoS 入口。
- 设计文档:
outputs/scanner-defense-design-2026-10-21.md(含分级变更清单、文件级改动点、验收指标)。 - 未动任何生产代码,等用户决定实施范围。
蜜罐(虚假后台登录界面 + 破解凭据记录)已实施
用户明确需求原文:「能不能把这些页面指向一个简单的虚假后台登录界面,然后记录这些破解的用户名密码等信息」。
落点决策(关键)
- 蜜罐不改写成新中间件,而是改写
internal/route/route.go的f.NotFound:- NotFound 只在「路由表完全落空」时触发 → 与
/login/register/_/{domain}/user/**/api/v1/**天然零交集; - 位于全局
f.Use链之后 →requestBodyLimitMiddleware已给 body 加 12 MiB 上限; - 组级中间件(含 CSRF)只挂具体路由,不作用于 NotFound → POST 表单可安全解析;
- flamego
context.run()在ResponseWriter().Written()为真时 return → 写完响应不调ctx.Next()即安全短路。
- NotFound 只在「路由表完全落空」时触发 → 与
- 双重计数坑:autoban 中间件对敏感路径已
Record一次,蜜罐再记一次会让阈值实际减半。 解决:autobanMiddleware(b, hp)传入蜜罐匹配器,蜜罐命中的路径由蜜罐自己计数。
新增文件
internal/security/honeypot/honeypot.go— 匹配器(段前缀 + 片段子串 + 双重保险forbiddenPrefixs排除业务路由)、 凭据提取(表单 / JSON / BasicAuth / 查询串)、CanaryToken = "tb-hp-7f3a1c9e"。internal/security/honeypot/page.go— 仿 WordPress 假登录页(经典字段log/pwd/redirect_to),内联 CSS 不依赖站点静态资源。internal/db/honeypot.go—HoneypotHit(不嵌 dbutil.Model,审计证据只追加)+HoneypotStore。internal/route/honeypot.go— 处理器:GET 假登录页 / POST 假失败响应 / 落库 / 复用 autoban 封禁 / 每 IP 告警一次。internal/cmd/honeypot.go—TamaBox honeypot hits|stats|prune,密码默认脱敏(--show-password显示明文)。templates/mail/honeypot-alert.html— 告警邮件模板(mail/已在 embed 清单,无需改 embed.go)。
改动文件
internal/route/route.go(CRLF):NotFound 分流 + 蜜罐实例装配 +hph.sendAlert。internal/route/autoban.go(LF):autobanMiddleware(b, hp),蜜罐路径跳过自身 Record。internal/db/db.go(LF):AllTables加&HoneypotHit{},Init()加Honeypots = NewHoneypotStore(db)。internal/conf/static.go(CRLF):enable_honeypot/honeypot_paths/honeypot_retain_days。conf/app.sample.ini(CRLF):对应说明段。internal/mail/mail.go(LF):SendHoneypotAlertMail+HoneypotAlert。cmd/tamabox.go+ 根tamabox.go:注册cmd.Honeypot(两处必须同步)。
踩坑
normalize()里for len(p)>1 { TrimSuffix(p,"/") }无限循环(路径不含尾斜杠时字符串不变)→ 改成HasSuffix判断。url.ParseQuery遇非法百分号编码返回 error 但仍给出部分字段 → 蜜罐要「尽可能多拿凭据」,忽略 error 继续用部分结果。- JSON 凭据提取:手写解析器又脏又易错 → 改用
jsonPairRe正则扫描扁平字段。 templates/mail/已在 embed 清单内 → 新增邮件模板不需要改templates/embed.go(顶层文件才需要)。
验证
go build ./...通过;go test ./...全绿(含 DB 测试,postgres 门控)。- 新增测试:
internal/security/honeypot/honeypot_test.go(匹配/业务路由零交集/编码绕过/凭据提取)、internal/route/honeypot_test.go(假页含 canary、业务路由不被劫持、关闭时回落 302、POST 返回失败页)、internal/db/honeypot_test.go(写入/倒序/三张聚合表/保留期清理)。