# 2026-10-30 ## 蜜罐周期安全汇总(周报/月报 + 地图 + 邮件) 用户需求:以周/月为单位汇总安全状况,把嗅探 IP 通过**公共服务**查地理位置,汇总到**地图**, 发到邮箱。起因是他发现线上有人隔一段时间换不同 IP 探测蜜罐。 ### 关键认知:ipinfo 与 geoip 是两个维度(用户亲自纠正) 用户反馈「ipinfo 只能查机房,肉鸡全显示『未识别(普通网络)』」。原因是 `internal/security/ipinfo` 走 `projectdiscovery/cdncheck` 的离线 ASN 指纹,只认云厂商/CDN/WAF。 它答的是「**是不是代理**」,不是「**在哪儿**」。肉鸡(家宽、企业宽带、移动网络)必然是后者, 所以安全汇总必须另建一套真正的 IP 地理库 → 新包 `internal/security/geoip`。 ### 新增文件 - `internal/security/geoip/geoip.go` — ip-api 批量打底(100/批、1.4s 节流)+ 腾讯精修国内 (只精修前 200 个,一 IP 一请求)。`Result{Geo, Unresolved, Requests, Failures}` 三态。 - `internal/security/report/{period,aggregate,mapdraw,html,geo,countryname}.go` - `internal/db/{ipgeo,security_report}.go` — `ip_geo_cache`(主键 = `LimitKey`)、 `security_report_logs`(`period_key` 唯一索引保证幂等) - `internal/cmd/report.go` — `honeypot report --period week|month` + 30 分钟一轮的调度器 - `templates/mail/security-report.html` ### 踩过的坑(都要记住) 1. **ip-api 免费版很慢**:22 个 IP 实测 4–10 秒,且同一批重复请求更慢。最初设 15s 超时 → 第一次真实数据就整批超时、定位率 0%。现在 `defaultTimeout = 45s` + 重试一次。 2. **缓存毒化**:早先把所有 miss 都写缓存并 `Failed=true`(TTL 3 天)→ 一次网络抖动 等于把整批 IP 钉成「查不到」三天,报告定位率莫名变 0 且无任何线索。 现在只有服务**明确回答**没数据才允许写失败缓存;请求失败绝不写。 3. **`addrs` 不能从 map 取顺序**:腾讯精修只取前 N 个,若按 map 迭代(随机)取, 每次运行精修到的 IP 都不同,配额花在长尾上。必须按 `keys` 原始顺序(= 命中数降序)建。 4. **地图标签会叠出假数字**:同一都市圈两个城市坐标只差 0.01°,标签精确重叠, 「AU 55」+「AU 30」叠成了看起来像 **AU 305** 的字符串 —— 读图的人会当结论。 已加 `labelPacker`(不重叠才画,右侧放不下换左侧)。 5. **不能无脑把腾讯结果的国家码写成 CN**:`provider=tencent` 时海外 IP 也走这条路。 现在从 `ad_info.nation` 精确判「中国」才给 CN。 ### 合规(地图) 自绘底图**零国界**,只画经纬网 + 气泡 + 度数刻度;真实底图交给腾讯地图(配 key 才有, 未配给申请指引)。代码里不预置任何 key,测试里有禁词断言(googleapis/mapbox/osm/bing)。 报告里 HK/MO/TW 统一显示为「中国香港 / 中国澳门 / 中国台湾」(`countryname.go`), 且常见国家改用中文名(报告是给中文读者看的)。 ### 端到端验证(WSL Debian + PG 17.11) 854 条仿真数据 / 22 个来源:首跑 36s(真实 ip-api)、次跑 1.3s(缓存命中), 定位覆盖 22/22、14 个国家/地区、未能定位 0 次。 ### 顺手修的(别人改动留下的) - `internal/route/honeypot_test.go` 的 `captureStore` 缺 3 个新方法 → 整个 route 包编译不过 - `templates/render_test.go` 的 `mockLoggedUser` 缺 `TelegramChatID` → 3 个渲染测试失败