mirror of
https://gitcode.com/JianFeeeee/HomeAgent.git
synced 2026-09-26 12:23:23 +00:00
★ 这是在生产上亲手踩出来的:上一提交加了按 IP 限流后,我用 8 次错误登录 做验证,结果**把管理员自己锁在外面 10 分钟**。 ## 现场证据 [webui] POST /api/v1/login from=127.0.0.1 auth=none status=429 webui 经 frp/nginx 穿透到公网时,**所有外部请求的 RemoteAddr 都是 127.0.0.1**。于是所有人共用一个桶:任何人爆破 5 次,就把**所有人** (含管理员)一起锁死。限流从防护变成了 DoS。 ## 我第一版还犯了个方向的错 当时我刻意**不采信** X-Forwarded-For,理由是「该头可伪造,换个头就能 绕过限流」。这个理由本身对,但结论下反了:完全不采信,在穿透部署下 **必然退化成全局限流** —— 而全局限流正是我试图避免的那个后果。 ## 正确做法:中间路线 **只信任受信反代发来的 XFF**。判定「是否来自受信反代」不能靠 内网/回环 IP 猜 —— 穿透部署下反代恰恰就在本机 127.0.0.1,与直连请求 完全同源,猜不出来。所以由部署方**显式声明**(新设置项 `webui.trusted_proxies`,逗号分隔 CIDR 或裸 IP)。 权衡写明:未声明时穿透明场景下限流退化为「全局」。这是**刻意的保守 默认** —— 宁可限流偏保守,也不能因为采信伪造头而形同虚设。 ## 判据(+4) - TestLoginRateLimitUsesForwardedForFromTrustedProxy:受信反代下按真实 客户端 IP 隔离(否则就是全局锁) - TestLoginRateLimitIgnoresUntrustedForwardedFor:换 XFF 头不得绕过限流 - TestLoginRateLimitNeedsExplicitTrustedProxyConfig:未配置 = 不采信 - TestParseTrustedProxies:合法项接受、非法项丢弃、空 = nil 全量:35 包全绿。 ★ 附带教训(也记在判据注释里):**用失败注入做验证时要意识到副作用 范围**。我那次「跑 8 次错误密码看看会不会限流」本身是合理的验证动作, 但它作用在**生产实例**上,且限流的作用域(全局化)正好覆盖了自己。 在带状态的安全机制上做破坏性验证,判据应该先证明作用域是对的。