feat: brute-force protection with per-IP escalating lockout
- Failures counted per client IP (X-Forwarded-For last hop behind the proxy); after maxFailures within the window the IP is locked out, doubling per repeat up to lockoutMaxSeconds. - Locked IPs get 429 + Retry-After (login page / JSON for API), and the scrypt verification is skipped entirely while locked (no CPU burn). - Fixed failedLoginDelayMs delay on every bad credential attempt. - Basic-auth path counts and clears identically; success resets the IP. - All thresholds configurable; in-memory state only. - Tests: lockout, expiry restore, basic-path counting, XFF last-hop key.
This commit is contained in:
@@ -35,6 +35,34 @@
|
||||
> IP 说明:面板经 Caddy 反代时,直连 socket 是回环地址;插件在检测到回环
|
||||
> 来源时会取 `X-Forwarded-For` 的首个值作为真实 IP(Caddy 默认会带上该头)。
|
||||
|
||||
## 防爆破(默认开启)
|
||||
|
||||
- **按 IP 计数**:同一 IP 在 `failureWindowSeconds`(默认 300 秒)窗口内连续
|
||||
`maxFailures`(默认 5)次密码错误后进入锁定期。
|
||||
- **阶梯式锁定**:首次锁 `lockoutBaseSeconds`(默认 30 秒),再次触发翻倍,
|
||||
上限 `lockoutMaxSeconds`(默认 3600 秒)。
|
||||
- 锁定期内:登录页返回 `429 + Retry-After`("尝试次数过多"),API 返回
|
||||
`429 {"error":"too many attempts"}`,且**不再执行 scrypt 校验**(不消耗 CPU)。
|
||||
- **失败延迟**:每次密码错误额外等待 `failedLoginDelayMs`(默认 300ms),
|
||||
拖慢单连接暴力尝试。
|
||||
- **成功即清零**;锁定状态为进程内存态,面板重启后清空(重启面板需要
|
||||
root,攻击者无法自行重置)。
|
||||
- Basic 认证路径同样计入;IP 取自反代 `X-Forwarded-For` 的最后一跳
|
||||
(Caddy 会覆写伪造值,见下)。
|
||||
- 配置(`cordis.patch.yml` 的 `config` 中可调):
|
||||
```yaml
|
||||
bruteProtection: true # 关闭设为 false
|
||||
maxFailures: 5
|
||||
lockoutBaseSeconds: 30
|
||||
lockoutMaxSeconds: 3600
|
||||
failureWindowSeconds: 300
|
||||
failedLoginDelayMs: 300
|
||||
```
|
||||
|
||||
> 局限:分布式攻击(每尝试换一个 IP)不受单 IP 锁定约束;这由
|
||||
> 300ms 失败延迟 + scrypt 慢哈希兜底。公网反代场景建议再配合 Caddy
|
||||
> 层的 IP 白名单/云防火墙(如 Cloudflare)使用。
|
||||
|
||||
## 修改密码
|
||||
|
||||
```bash
|
||||
|
||||
Reference in New Issue
Block a user