Skip to content

[Bug]: 等待区认证成功后连 Forge 服(corath) 稳定约 30s 超时 unable to connect(共存 Ambassador) #28

Description

@sipo610

提交前确认

  • 已阅读用户手册中与登录 / 等待区相关章节
  • 已确认 Velocity 与后端基础转发可用(非 outpre/Forge 路径可进服)
  • 已检索现有 Issue,未见完整的 outpre + Ambassador/Forge 联调说明

HyperZoneLogin 主插件版本

26.7.3-SNAPSHOT-bd98b152
(源码基线:upstream master @ bd98b152;本地为适配 Java 21 / Velocity 3.5 的构建产物)

说明:官方 26.7.3-RC 源码中 jvmToolchain(25)velocity = "4.1.0-SNAPSHOT"
我们线上代理仍为 Java 21 + Velocity 3.5.x,因此在 bd98b152 基础上将 toolchain/依赖改回 21 + 3.5 后构建上线。
希望作者确认:该组合是否在支持范围内,还是仅保证 Vel 4.1 + Java 25。

已安装模块及版本

单体 all-in-one:HyperZoneLogin-26.7.3-SNAPSHOT-bd98b152-...-all.jar
启用:auth-yggd、safe
禁用:auth-offline、auth-floodgate、profile-skin、data-merge

Velocity 版本

Velocity 3.5.x(与 HZL compileOnly velocity-api/proxy 3.5.0-SNAPSHOT 对齐)
代理 JVM:Java 21

后端服务端版本

Mohist 1.20.1(Forge 模组端,主城/游戏服)
认证等待:outpre 直连 127.0.0.1:25581(auth-label=verify)

代理转发模式

modern

当前数据库类型

MYSQL

已安装模块

  • auth-yggd
  • auth-offline(已关)
  • data-merge
  • profile-skin(已关)
  • 主插件 + safe

部署结构

- 1× Velocity 代理(Java 21)
- HZL v-server.mode=outpre
  - auth-label=verify,auth-host=127.0.0.1,auth-port=25581
  - post-auth-default-server=corath
  - struck-online-mode=true
- Forge/Mohist 游戏服:corath
- Mojang + 第三方 Yggdrasil Entry;auth-offline/floodgate/profile-skin 关
- 共存 Ambassador(Forge)+ TAB 等
- 数据库:MYSQL

问题类型

  • 跳服 / 认证等待区相关
  • (叠加)与第三方 Forge 代理插件 Ambassador 共存

复现步骤

  1. 启动 Velocity(HZL + Ambassador)与 Mohist/Forge 后端、认证等待服 verify。
  2. 使用 Forge 模组客户端 连接代理。
  3. 完成 Yggdrasil 认证(日志:认证成功 / 通过 Yggdrasil 验证)。
  4. 离开等待区后进入 Forge 服 corath。
  5. 失败时:corath has connected → 恰好约 30s → disconnected → unable to connect;Amb 向 LOGIN 客户端转发 Registry/ConfigData 失败刷屏。

预期结果

  • 认证成功后进入 Forge 后端应在合理时间内完成 FML 握手并进入游戏区。
  • 若失败,应有 明确、可操作 的失败原因(超时原因、握手阶段),而不是泛化 unable to connect

实际结果

  1. 主路径可用:大量玩家 Yggdrasil 认证成功并可游玩。
  2. 失败模式(可在日志中对齐时间戳)
    • HZL:认证成功(Yggdrasil / Entry)
    • 约 30s 后 Velocity:unable to connect to server corath
    • 同时 Ambassador 侧大量:failed forwarding backend forge packet (RegistryPacket/ConfigDataPacket/...) to clientclientState=LOGIN + StacklessClosedChannelException
    • 表现像:后端已向代理推 Forge 登录握手包,客户端停留 LOGIN、无有效应答,直到原版/后端登录超时。
  3. 源码层面 HZL 已对 Ambassador 做 soft-failregisterConnection 失败仅 debug:maybe using Ambassador),说明作者已知共存,但 缺少正式协作契约

相关日志(生产代理日志摘录;玩家名 / 公网 IP 已脱敏;本机回环地址保留)

启动与模块:

[06:23:49] [main/INFO] [com.velocitypowered.proxy.plugin.VelocityPluginManager]: Loaded plugin ambassador 1.5.3-beta by adde0109
[06:23:49] [main/INFO] [com.velocitypowered.proxy.plugin.VelocityPluginManager]: Loaded plugin hyperzonelogin 26.7.3-SNAPSHOT-bd98b152 by ksqeib
[06:23:50] [CMIV - Task Executor #0/INFO] [hyperzonelogin]: Using outpre waiting-area adapter on direct auth endpoint 'verify' (127.0.0.1/<unresolved>:25581)
[06:23:50] [CMIV - Task Executor #0/INFO] [hyperzonelogin]: 内置模块已禁用: Auth Offline (modules.conf -> authOffline=false)
[06:23:50] [CMIV - Task Executor #0/INFO] [hyperzonelogin]: 凭证渠道已注册: yggdrasil (模块: YggdrasilSubModule) [canRegister=true]
[06:23:50] [HyperZoneLogin - Task Executor #0/INFO] [hyperzonelogin]: 接收到 Entry 注册事件: Dream-WingSkin (ID: Dream-WingSkin)
[06:23:50] [HyperZoneLogin - Task Executor #0/INFO] [hyperzonelogin]: 接收到 Entry 注册事件: mojang (ID: mojang)
[06:23:50] [CMIV - Task Executor #0/INFO] [hyperzonelogin]: 成功加载 2 个 Entry 配置文件
[06:23:50] [CMIV - Task Executor #0/INFO] [hyperzonelogin]: 模块加载成功: icu.h2l.login.auth.online.main.YggdrasilSubModule
[06:23:51] [CMIV - Task Executor #0/WARN] [com.velocitypowered.proxy.network.ConnectionManager]: The server channel initializer has been replaced by org.adde0109.ambassador.Ambassador.inject(Ambassador.java:156)
[06:23:51] [CMIV - Task Executor #0/WARN] [com.velocitypowered.proxy.network.ConnectionManager]: The backend channel initializer has been replaced by org.adde0109.ambassador.Ambassador.inject(Ambassador.java:159)

案例 A(可精确复现的 30s 后端登录超时):玩家 PlayerA,Mojang Entry

[10:08:27] [Netty NIO Worker #3/INFO] [com.velocitypowered.proxy.connection.client.AuthSessionHandler]: [connected player] PlayerA (/x.x.x.x:xxxxx) entered outpre pre-registration flow
[10:08:29] [DefaultDispatcher-worker-3/INFO] [hyperzonelogin]: 条目 mojang: 玩家 PlayerA 认证成功
[10:08:29] [DefaultDispatcher-worker-1/INFO] [hyperzonelogin]: 玩家 PlayerA 通过 Yggdrasil 验证,Entry: mojang
[10:08:29] [Netty NIO Worker #3/INFO] [com.velocitypowered.proxy.connection.MinecraftConnection]: [server connection] PlayerA -> corath has connected
[10:08:59] [Netty NIO Worker #3/INFO] [com.velocitypowered.proxy.connection.MinecraftConnection]: [server connection] PlayerA -> corath has disconnected
[10:08:59] [Netty NIO Worker #3/ERROR] [com.velocitypowered.proxy.connection.client.ConnectedPlayer]: [connected player] PlayerA (/x.x.x.x:xxxxx): unable to connect to server corath
[10:08:59] [Netty NIO Worker #3/INFO] [com.velocitypowered.proxy.connection.client.ConnectedPlayer]: [connected player] PlayerA (/x.x.x.x:xxxxx) has disconnected: 无法将您连接到 corath,请稍后再试。

同一玩家同日多次重复同一模式(均为 connected → 恰好 30s → disconnected / unable to connect):

10:08:29 → 10:08:59  corath  (Δ30s)
10:10:36 → 10:11:06  corath  (Δ30s)
10:13:13 → 10:13:43  corath  (Δ30s)
10:23:25 → 10:23:55  corath  (Δ30s)
10:29:03 → 10:29:33  corath  (Δ30s)

案例 B(认证成功 + 30s 失败 + 随后 Amb 转发 Forge 包刷屏):玩家 PlayerB

[13:59:20] [Netty NIO Worker #7/INFO] [com.velocitypowered.proxy.connection.client.AuthSessionHandler]: [connected player] PlayerB (/x.x.x.x:xxxxx) entered outpre pre-registration flow
[13:59:21] [DefaultDispatcher-worker-3/INFO] [hyperzonelogin]: 条目 mojang: 玩家 PlayerB 认证成功
[13:59:21] [DefaultDispatcher-worker-1/INFO] [hyperzonelogin]: 玩家 PlayerB 通过 Yggdrasil 验证,Entry: mojang
[13:59:21] [Netty NIO Worker #7/INFO] [com.velocitypowered.proxy.connection.MinecraftConnection]: [server connection] PlayerB -> corath has connected
[13:59:51] [Netty NIO Worker #7/INFO] [com.velocitypowered.proxy.connection.MinecraftConnection]: [server connection] PlayerB -> corath has disconnected
[13:59:51] [Netty NIO Worker #7/ERROR] [com.velocitypowered.proxy.connection.client.ConnectedPlayer]: [connected player] PlayerB (/x.x.x.x:xxxxx): unable to connect to server corath
com.velocitypowered.proxy.util.except.QuietRuntimeException: The connection to the remote server was unexpectedly closed.
[13:59:51] [Netty NIO Worker #7/INFO] [com.velocitypowered.proxy.connection.client.ConnectedPlayer]: [connected player] PlayerB (/x.x.x.x:xxxxx) has disconnected: 无法将您连接到 corath,请稍后再试。
[14:01:20] [Netty NIO Worker #7/ERROR] [com.velocitypowered.proxy.connection.MinecraftConnection]: [connected player] PlayerB (/x.x.x.x:xxxxx): read timed out
[14:01:20] [Netty NIO Worker #7/WARN] [ambassador]: [HZL-OUTPRE] failed forwarding backend forge packet RegistryPacket to client player=PlayerB clientState=LOGIN
io.netty.channel.StacklessClosedChannelException
	at io.netty.channel.AbstractChannel.close(ChannelPromise)(Unknown Source)
[14:01:20] [Netty NIO Worker #7/WARN] [ambassador]: [HZL-OUTPRE] failed forwarding backend forge packet ConfigDataPacket to client player=PlayerB clientState=LOGIN
io.netty.channel.StacklessClosedChannelException
	at io.netty.channel.AbstractChannel.close(ChannelPromise)(Unknown Source)
# 同一秒内 RegistryPacket/ConfigDataPacket 同类 WARN 合计约 120+ 次(closed channel 后仍积压写)

同日统计:

unable to connect to server corath : 9 次
[HZL-OUTPRE] failed forwarding backend forge packet ... : 121 次

说明:

  • HZL 认证阶段成功,问题集中在 outpre 释放后连 Forge 后端 corath 的登录握手窗口(稳定约 30s)
  • Ambassador 日志显示向客户端转发后端 Forge 登录包时 clientState=LOGIN,通道已关仍刷屏(当前线上 Amb 尚未换看门狗/去重版)。
  • 部分玩家后续可成功进其它后端服,说明并非全局无法连后端。

相关配置片段(已脱敏)

start.conf

format=hocon
language="zh_cn"
ready=true

core.conf(关键段)

database {
    type=MYSQL
    table-prefix="hz_"
    # mysql host/port/user/password 已脱敏省略
}

modules {
    auth-floodgate=false
    auth-offline=false
    auth-yggd=true
    safe=true
    profile-skin=false
    data-merge=false
}

misc {
    kill-chat-session=true
}

debug {
    log {
        general=false
        out-pre-trace=false
        yggdrasil-auth=false
        network-rewrite=false
        backend-compat=false
        profile-skin=false
        floodgate=false
    }
}

v-server {
    mode=outpre
    post-auth-default-server=corath
    remember-requested-server-during-auth=true
    backend {
        fallback-auth-server=verify
        enable-player-info-compensation=true
        enable-profile-compensation=true
        enable-name-hot-change=true
        enable-uuid-hot-change=false
    }
    outpre {
        auth-label=verify
        auth-host="127.0.0.1"
        auth-port=25581
        presented-host=""
        presented-port=-1
        presented-player-ip=""
        # 在线模式玩家直通:认证通过后跳过等待区直接进游戏
        struck-online-mode=true
    }
}

auth {
    disable-registration=["<channel-id>"]
}

auth-yggd Entry

# mojang.conf
id=mojang
name="Mojang Official"
yggdrasil {
    pass-yggdrasil-uuid-to-profile-resolve=true
    retry=5
    retry-delay=5000
    timeout=10000
    url="https://sessionserver.mojang.com/session/minecraft/hasJoined?username={username}&serverId={serverId}{ip}"
    proxy { type=DIRECT }
}

# 第三方 Entry
id=Dream-WingSkin
name="<third-party-entry>"
yggdrasil {
    pass-yggdrasil-uuid-to-profile-resolve=true
    retry=5
    retry-delay=5000
    timeout=10000
    url="<third-party-hasJoined-url>"
    proxy { type=DIRECT }
}

与日志对齐的要点

  • mode=outpre + auth-host=127.0.0.1 + auth-port=25581 + auth-label=verify → 与日志 outpre adapter 一致
  • post-auth-default-server=corath → 与失败目标服一致
  • struck-online-mode=true → 在线玩家可能跳过等待区直进,与 Forge/Ambassador 握手时序可能相关

已尝试的排查

  • 确认 HZL 使用 outpre 而非 limboapi
  • 确认 Amb 与 HZL 同时注入 server/backend ChannelInitializer(Velocity 有 WARN 属预期)
  • 对照时间戳:失败发生在 认证成功之后的切 Forge 服,不是 Ygg 校验失败
  • 对照 HZL 源码:OutPreAuthSessionHandlerregisterConnection==false soft-fail(注释提及 Ambassador)
  • 对照 outpre 架构:OutPreBackendBridge 组合包装真实 VelocityServerConnection 写入 connectionInFlight
  • (可选)临时去掉 Ambassador 用原版客户端对照
  • 看门狗版 Amb 尚未部署

其他补充信息 / 希望作者协助的点

A. 本 Issue 主问题(outpre + Forge/Ambassador)

我们不是要求 Amb 成为 HZL 官方依赖,但希望在文档或 API 层明确 outpre 与会提前 registerConnection / 修改 LOGIN 状态机的第三方插件 如何共存:

  1. outpre × Forge 握手所有权

    • 认证成功后切 Forge 服时,FML LOGIN 握手由谁主导?
    • 客户端长时间停在 LOGIN 时,HZL 是否应有超时与可观测日志(而不是只暴露 Velocity 的 unable to connect)?
  2. registerConnection soft-fail 策略

    • 当前“失败就当 Ambassador、继续流程”在真·双连接撞名时可能误放行。
    • 是否考虑可配置 / 可观测区分「预期 Amb 已注册」vs「异常重复连接」。
  3. struck-online-mode=true 与 Forge 切服时序

    • 在线玩家直通是否更容易踩中「认证成功 → 立刻连 corath → 30s 登录超时」?

B. 本地侧其它改动(仅供参考,与本 Bug 无关)

为在 Java 21 + Velocity 3.5 上跑 26.7.3 线,以及服内安全加固,我们在 bd98b152 上有过本地修改。不作为对本 Issue 的诉求,也不默认会提 PR,仅供作者知晓:

类别 摘要
构建 toolchain 21 + velocity 3.5(官方 RC 为 25 + 4.1)
离线密码 PBKDF2+salt;拒绝 plain;旧格式登录后 rehash
logout detach Profile + 清 session
邮箱找回 默认关;LOG 模式不打印验证码
绑定码 先销毁 code 再 bind
其它 名称大小写、pending 注册 TTL 等
  • 上表 与 corath 30s 超时无直接关系
  • Amb 侧另有修改,看门狗版未上生产;本 Issue 仍以当前线上 Amb 为准。

C. 支持矩阵(可选)

  • 26.7.x 是否仅保证 Velocity 4.1 + Java 25?
  • 是否仍考虑 Vel 3.5 + Java 21?

如需可再补脱敏日志时间线。


我尊重你对于高版本的兼容,但是我个人觉得盲目的追新会导致某些插件组合无法使用,徒增维护成本,这是我降版本的初衷。

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions