问题总结

背景

产生原理

核心链条是 「nezha v2 的会话 IP 绑定」×「你的出口 IP 频繁变化」

  1. nezha v2 登录时会在数据库创建 JWTSession 记录,绑定登录时刻的真实 IP(取自你配置的 web_real_ip_header: CF-Connecting-IP,即访客真实 IP)。之后每个请求都校验当前 IP 与绑定 IP 是否一致,不一致就把请求降级为未登录(jwt.go 源码if sess.IP != currentIP { return nil })。
  2. 失效时返回的是 HTTP 200 + {"error":"ApiErrorUnauthorized"},不是 401——所以日志里静悄悄,"无任何错误却频繁掉登录"的假象由此而来。
  3. 而你的网络环境 IP 极不稳定,日志实证:
  4. 于是:IP 每变一次 → 会话绑定校验失败 → 前端判定未登录 → 跳转重新 OAuth 登录 → 新会话绑定新 IP → 下次 IP 变化再次失效,循环往复。

可选解决方法

方案 做法 效果 代价
① 关闭 CF 的 IPv6 Compatibility(推荐) CF 后台 xxxxx.com → 网络 → IPv6 兼容性 → 关闭(或 API PATCH /zones/<id>/settings/ipv6)。CF 不再发布 AAAA 记录,客户端只能走 IPv4 根治:你的 IPv4 很稳定(7 天未变),会话吃满 72h zone 级生效;纯 IPv6 访客无法访问;宽带重拨换 IPv4 时仍会掉一次
② Worker 截取 IPv6 /64 前缀 挂免费 Worker:读 CF-Connecting-IP,IPv6 时只取前 64 位写入自定义头 X-NZ-IP;nezha 配置 web_real_ip_header: X-NZ-IP 免疫临时地址轮换(你的 /64 前缀稳定),但 v4↔v6 切换仍会掉登录,只算缓解 配置较繁琐;Worker 代码需自己维护
③ 静态假 IP 头 CF Transform Rule 给 nezha.xxxxx.com 固定注入一个合法 IP 格式的头(如 X-NZ-IP: 100.64.0.1),nezha 改读该头 彻底解除 IP 绑定 WAF 按 IP 封禁变成"全站共享一个 IP"(个人用基本无感)
④ 本机 hosts 强制 IPv4 C:\Windows\System32\drivers\etc\hosts104.21.92.245 nezha.xxxxx.com 本机连接恒走 IPv4,会话稳定 每台设备都要配;手机端无效
⑤ 上游改进(长期) 给 nezha 提 issue:建议 IP 绑定改为 IPv6 按 /64 前缀匹配,或提供关闭 IP 绑定的开关 治本但依赖作者 时间不可控

建议:直接用方案 ①——一个开关、零代码、对你这种"IPv4 稳定 + IPv6 乱跳"的双栈环境刚好对症。如果提供 CF API Token 和 Zone ID,我可以帮你调 API 关闭并验证;同时注意日常只通过 https://nezha.xxxxx.com/ 访问面板,直连 :8008 会被 real ip header not found 拦截(这是当前配置的预期行为)。