docs: 说明封禁响应的图片体与替换方式

This commit is contained in:
tamakyi
2026-10-23 15:04:14 +08:00
parent 0318ba81b4
commit 6fad0cbe50
2 changed files with 42 additions and 0 deletions
+26
View File
@@ -153,3 +153,29 @@ Tomcat 的 skin 忘了 css(按钮白字无底色)、WP 登录页底部挂着
- 性能:RenderFamily 3.7µs→4.18µs、2→3 allocs(多的一次是 hex 编码),可接受。 - 性能:RenderFamily 3.7µs→4.18µs、2→3 allocs(多的一次是 hex 编码),可接受。
四处变异验证有效(固定 token / xmlrpc 分支失效 / Pingback 相对路径 / .php 兜底失效)。 四处变异验证有效(固定 token / xmlrpc 分支失效 / Pingback 相对路径 / .php 兜底失效)。
### 测试环境验收:XML-RPC 端点(部署 9d3f5a7 后)
- `GET /xmlrpc.php` → **405 + text/xml**(与真实 WP 一致,XML-RPC 只接受 POST),
用户误以为这是报错;405 的 body 是 `<fault>XML-RPC services are disabled…`。
- `POST system.listMethods` → 200 + 方法列表 ✓。
- `POST wp.getUsersBlogs`(伪造 `CF-Connecting-IP: 2001:db8:beef::7`)→ 凭据落文件:
`username=xruser / password=xrpass`、`fields.xmlrpc.0/1`、`xmlrpc.method`、`banned:true` ✓。
- 紧接的下一次请求 `403 Forbidden` = 已封禁(第一次 POST 就封了该 /64),属预期。
- 动态 token 两次不同(`d85a8c…` / `76a404…`)✓。
**再次出现的 `"path":" /xmlrpc.php"` 已判定为粘贴/终端产物**:`IsXMLRPCPath` 不做 trim,
若 `path` 真带前导空格根本进不了 XML-RPC 分支,而记录里有 `xmlrpc.*` 字段 ⇒ 落盘值必是
`/xmlrpc.php`。这类"看不见的字符"结论一律靠 `od -c`,别靠终端回显。
### 403 响应体换成图片
用户给了 R2 预签名链接(`X-Amz-Expires=604800`,7 天后失效)——**不能直接热链**。
下载后(256×256 webp,8.6 KB)用 `//go:embed` 编进二进制:
`internal/route/assets/403.webp` + `internal/route/banned.go: writeBanned()`。
- 状态码仍是 403(语义不变),只换 body;`Content-Type: image/webp` + 显式 `Content-Length`
(8 KB 超过 Go 的 2 KB 缓冲,不设会退回 chunked)+ `no-store`;HEAD 不写 body。
- 放在 `internal/route/assets/` 而不是 `static/`:static 会多出一个可公开访问的 URL。
- 换图方式:覆盖同目录 403.webp → 重新编译,无配置项。
- 体积代价:每封禁请求 8.6 KB(原 13 字节)。被封来源重试频繁时要留意带宽,
已压到 256×256;别塞几百 KB 原图。
+16
View File
@@ -110,6 +110,22 @@ honeypot_cred_dir = data/honeypot-creds
纯探测也不会被刷爆:元数据落库按「每 IP 每分钟一条」采样,凭据则是「有就存」——那才是要保的东西。 纯探测也不会被刷爆:元数据落库按「每 IP 每分钟一条」采样,凭据则是「有就存」——那才是要保的东西。
### 被封之后会看到什么
状态码 `403`,body 是一张 256×256 的 webp(约 8.6 KB,画面写着 403 Forbidden),不再是那行 13 字节的明文:
```
$ curl -si https://你的站点/anything | head -4
HTTP/2 403
content-type: image/webp
content-length: 8608
cache-control: no-store, no-cache, must-revalidate
```
这样做有两个目的:爆破脚本常靠读响应体里的 `403 Forbidden` 确认自己已被拦,换掉 body 让这类判断失效;人肉访问(尤其是被共享出口连累的误封)时,看到一张明确的图比白屏好判断。
图片用 `go:embed` 编进二进制(`internal/route/assets/403.webp`),不占任何可公开访问的 URL。想换成自己的图:覆盖同目录文件后重新编译、重启即可。注意体积——被封的来源会反复重试,8.6 KB 是刻意压过的(原图别直接塞几百 KB 的)。
### 封的是一把「键」,不是一个人 ### 封的是一把「键」,不是一个人
`autoban` 的表就是内存里的 `map[键]到期时间`,键由 `shared.LimitKey` 生成: `autoban` 的表就是内存里的 `map[键]到期时间`,键由 `shared.LimitKey` 生成: