最近在折腾服务器监控面板的时候,发现 Beszel 这个工具界面挺干净,功能也够用,于是顺手就在我的机器上部署了一套。

为了安全起见,遵循最小权限原则,我并不想直接把服务端口暴露在公网上。我的部署方案是用 Docker 跑起来,仅监听本地回环地址,然后再套一层 Cloudflare 的 Zero Trust(也就是 Cloudflare Tunnel)来做内网穿透和访问控制。

本以为是一套非常成熟且标准的“安全运维组合拳”,结果安装完傻眼了——账号注册倒是顺顺利利,但只要一登录,输入密码点击登录后,大概也就 1 秒钟,页面直接刷新,又给你弹回了登录界面。这就陷入了一个无限死循环,根本进不去后台。

排查思路:从 F12 开始

遇到这种 Web 端的问题,第一时间肯定是打开开发者工具(F12)看网络请求。果不其然,控制台里飘红了一个请求。

报错的接口是 POST /api/collections/users/auth-refresh,状态码是 400 Bad Request

这里有个特别奇怪的细节引起了我的注意:查看报错请求的远程地址,显示的是 127.0.0.1:9909。这就很迷了,因为我在 Docker Compose 配置文件里明明写的是端口 12345 映射到容器的 8090,我自己在服务器本地 curl 也没问题。这个 9909 端口是从哪儿冒出来的?

为了搞清楚这个端口问题,我甚至一度怀疑是不是容器内部配置冲突,或者 Cloudflare 的代理层解析出了什么幺蛾子。

常见的解决方案(并不奏效)

看到 400 错误,我第一反应就是反向代理的经典坑——Host 头部丢失或篡改

通常情况下,应用在后端判断请求来源时,会校验 Host 字段。如果经过 Cloudflare 转发,Host 变成了 Cloudflare 的节点域名,后端应用就会报错。常规解法是在 Cloudflare 的 Zero Trust 配置里,找到 Host Header 设置,将其修改为源站 IP 或原始域名。

我兴冲冲地去配置了 HTTP Host 头,保存,刷新页面,重新登录……

Beszel 登录闪退修复的配置代码片段

Beszel 登录闪退修复的配置代码片段

失败了。依然是 1 秒闪退。

这时候心态已经开始崩了,问了一圈 AI,AI 也是在那儿车轱辘话来回说,让我检查 SSL、检查防火墙、检查反向代理配置,折腾了半天毫无进展。我都准备把这套方案废弃,老老实实开端口用 Nginx 转发了。

终极解法:禁用分块编码

就在死马当活马医的时候,我注意到 Cloudflare Zero Trust 配置面板里还有个不起眼的选项:Websocket 设置旁边(或者在网络相关的设置里),有一个名为 “禁用分块编码” 的开关。

这个选项在很多反向代理场景下是用来解决某些老式服务器或特定应用对 HTTP 传输编码不兼容的问题。虽然 Beszel 是个比较新的项目,但考虑到它对 API 的交互要求极其严格,也许问题就出在这个传输编码的协商上。

我带着“试一试又不亏”的心态,打开了这个开关。至于之前折腾的 HTTP Host 头,我都懒得管它了。

再次回到登录页面,输入密码,回车。

进去了! 页面正常跳转,Dashboard 数据加载正常,那个烦人的 400 错误彻底消失了。

总结与建议

如果你在部署 Beszel 或者类似的后端管理面板时,使用了 Cloudflare Tunnel 进行代理,并且遇到了登录死循环、授权刷新返回 400 错误的问题,可以按照以下顺序排查:

  1. 确认端口映射:虽然我这里看到了奇怪的 9909 端口日志,但这似乎是 Cloudflare 转发层的一种内部表现,只要 Docker 端口映射正确,不要在这个端口上死磕。
  2. Host 头配置:这是最常见的坑,但在 Beszel 这个案例中,大概率不需要配置,配置了反而可能引起混淆。
  3. 关键一招:请务必检查 Cloudflare 设置,开启 “禁用分块编码”。这大概率是解决此类问题的一剂特效药。

技术踩坑是常有的事,看似复杂的网络错误,有时候解决方法就在一个不起眼的复选框里。希望这篇复盘能帮到同样被 Beszel 登录问题折磨的朋友,让大家少走弯路,把精力花在更重要的监控指标上。

标签: none

评论已关闭