☰
Lunar Tear 安全设计清单:Admin Webhook、Bearer Token 与 fail-closed 机制详解
2026/10/15 11:10:23 网站建设 项目流程

【免费下载链接】lunar-tear

Private server research project for a certain discontinued mobile game

项目地址:https://gitcode.com/gh_mirrors/lu/lunar-tear
点击查看免费下载

Lunar Tear 是一个针对已停服手游的私服研究项目,由 gRPC 游戏服、HTTP 资源 CDN、auth-server 登录服务和 Admin Webhook 四部分组成。本文带你快速看懂它的完整安全设计:Admin Webhook 如何受 Bearer Token 保护、客户端登录 Token 采用什么签名方案,以及 fail-closed(默认关闭)机制如何保证"未配置就绝不暴露"。

项目架构速览:四服务各司其职

Lunar Tear 的每个服务都只开放必要的端口,管理端点更是被单独隔离:

服务二进制端口职责
游戏服lunar-tear8003gRPC 主服务,客户端登录、抽卡、任务等
资源 CDNocto-cdn8080资产包、master data、list.bin 下发
登录服务auth-server3000账号注册与登录,签发 Token
Admin Webhooklunar-tear8082热重载 master data,默认仅回环

服务入口见 server/cmd/lunar-tear/main.go,Admin Webhook 监听地址的默认值就写在命令行参数里——127.0.0.1:8082,只允许本机访问(main.go)。

Admin Webhook:如何安全地"不重启热更新"

私服运营者常需要修改游戏内数据(即 master data 文件assets/release/20240404193219.bin.e)。Lunar Tear 提供一个管理端点POST /api/admin/master-data/reload,让服务器在不重启的情况下重新读取该文件,原子替换全部内存目录,并让在线客户端自动拉取新版数据。

它的实现非常克制,整个逻辑只有几十行,位于 server/cmd/lunar-tear/admin.go。

触发方式:一条带 Bearer Token 的请求

在环境变量中设置LUNAR_ADMIN_TOKEN后,用如下命令即可触发热重载:

curl -X POST -H "Authorization: Bearer ${LUNAR_ADMIN_TOKEN}" \ http://127.0.0.1:8082/api/admin/master-data/reload

热重载由 server/internal/runtime/holder.go 中的Holder完成:每次重新加载都会从头构建一份全新的Catalogs快照,再通过原子指针一次性发布,所有 gRPC 请求在开始时调用Get(),因此永远看到一致的数据。

Bearer Token 认证的两层设计

Lunar Tear 中有两类 Bearer Token,分别保护管理面和客户端面。

管理端:LUNAR_ADMIN_TOKEN 与恒定时间比较

Admin Webhook 的鉴权逻辑在 admin.go:

  • 只接受POST,其他方法直接返回405;
  • 请求头必须是Authorization: Bearer <token>;
  • 比较使用subtle.ConstantTimeCompare(第 36 行),这是防计时侧信道攻击的标准做法——普通字符串比较会在第一个不匹配字节处提前返回,攻击者可据此逐字节猜测 Token,而恒定时间比较消除了这种信息泄露;
  • 校验失败统一返回401 unauthorized,不泄露"Token 是空、是格式错还是不匹配"等细节。

客户端:auth-server 签发的 HMAC-SHA256 Token

客户端的"Facebook 登录按钮"实际被重定向到 auth-server,输入用户名/密码后签发一个自定义格式 Token:Base64URL(payload).Base64URL(HMAC-SHA256签名),其中 payload 包含sub(用户 ID)、name、iat(签发时间)、exp(过期时间),有效期固定 24 小时,见 server/internal/auth/token.go。

验证流程在 Validate 函数 中按顺序执行:格式拆分 → Base64 解码 →hmac.Equal恒定时间校验签名 → 解析声明 → 检查过期,任何一步失败都拒绝(ErrTokenInvalid/ErrTokenExpired)。游戏服通过 auth-server 的/me端点换取用户身份,该端点同时兼容access_token查询参数与Authorization: Bearer头两种传法(handlers.go)。

密钥管理也很讲究:--secret省略时,auth-server 启动时用密码学安全随机数生成 32 字节密钥并打印到控制台,提示你在下次重启时通过--secret复用,保证已有 Token 不过期失效(server/cmd/auth-server/main.go)。

fail-closed:未配置就绝不监听

fail-closed 的核心思想是:出问题时宁可不可用,也绝不暴露。Lunar Tear 在 Admin Webhook 上贯彻了这一点,admin.go 的注释与代码明确写道:

如果LUNAR_ADMIN_TOKEN未设置或为空,监听器根本不会绑定——新部署永远不会暴露一个未认证的端点。

三层防线叠加:

  1. 🔒无 Token = 无端口:环境变量未设置时,8082 端口上什么都没有,连扫描器都找不到端点;
  2. 🛡️默认回环:--admin-listen默认127.0.0.1:8082,只有运维者显式改成0.0.0.0才会对外暴露;
  3. ⏱️恒定时间比较:即使端口暴露,Token 猜测也无法利用响应时间差异。

Docker 部署同样延续此默认:compose 文件将容器内0.0.0.0:8082仅映射到宿主机的127.0.0.1:8082,且LUNAR_ADMIN_TOKEN从.env注入(server/docker-compose.yaml)。

其他值得学习的安全细节 📝

  • bcrypt 存储密码:注册时密码经bcrypt.GenerateFromPassword加盐哈希后入库,绝不存明文(server/internal/auth/store.go);
  • 统一错误文案:登录失败一律返回 "Invalid username or password.",避免暴露"该用户不存在",防止账号枚举(handlers.go);
  • 注册开关--no-register:开放运营前可关闭自助注册,改用 server/cmd/register-account/ 工具受控建号,实现"白名单式开服";
  • 模板自动转义:登录页与 OAuth 重定向页均使用 Gohtml/template,自动防止 XSS(handlers.go)。

部署检查清单 ✅

#检查项预期状态
1LUNAR_ADMIN_TOKEN是否已设置未设置时 8082 端口不监听(fail-closed)
2--admin-listen绑定地址默认127.0.0.1:8082,公网部署勿改0.0.0.0
3auth-server 的--secret重启时复用同一密钥,否则存量 Token 全部失效
4注册策略稳定运营期建议开启--no-register
5Token 有效期客户端 Token 24 小时,到期需重新登录

更多端口、环境变量与命令行参数的完整对照,可查阅 README.md 的 "Live Master Data Reload" 一节。

小结:Lunar Tear 的安全设计体现了一套清晰的原则——最小暴露(无 Token 不监听、默认回环)、强认证(HMAC 签名 + 恒定时间比较)、弱默认(注册可一键关闭)。这些模式对任何需要暴露管理端点的自建服务项目,都值得借鉴。

【免费下载链接】lunar-tear

Private server research project for a certain discontinued mobile game

项目地址:https://gitcode.com/gh_mirrors/lu/lunar-tear
点击查看免费下载

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询