
Numdrassl
Numdrassl 是一款用Java编写的高性能、可扩展的Hytale代理服务器,它提供服务器间传输、插件支持以及外部供应商集成功能。
Numdrassl - Hytale 代理服务器
一款用 Java 编写的高性能、可扩展的 Hytale 代理服务器,支持多服务器组网、玩家跨服传送、插件系统以及灵活的权限体系。
什么是 Numdrassl?
Numdrassl 是 Hytale 的 BungeeCord/Velocity 风格代理。它位于玩家和您的后端服务器之间,使您能够:
- 将多个 Hytale 服务器连接到一个网络中
- 在服务器之间无缝传送玩家
- 拦截并修改数据包
- 创建带有自定义指令和事件的插件
- 使用分组和通配符管理权限
功能特性
- 多服务器组网 - 关联多个后端 Hytale 服务器(如大厅、小游戏等)
- 玩家传送 - 使用
/server <名称>在服务器间无缝移动玩家 - 插件系统 - 通过自定义插件扩展功能
- 权限系统 - 内置基于 YAML 的权限系统,支持分组、通配符和外部提供者
- 事件系统 - 可挂钩玩家连接、聊天、指令等事件
- QUIC 协议 - 原生支持 Hytale 的 QUIC 传输,并采用 BBR 拥塞控制
- 安全认证 - 代理与后端之间使用 HMAC 签名的引荐机制
系统要求
- Java 25 或更高版本
- Hytale 服务器 作为后端使用
安装指南
步骤 1:下载
请下载最新版本:
proxy-*.jar- 代理服务器bridge-*.jar- 后端服务器用的插件
步骤 2:运行代理
java -jar proxy-1.0-SNAPSHOT.jar
首次运行时,代理将:
- 在
certs/目录下生成 TLS 证书 - 创建
config/proxy.yml配置文件 - 提示您使用 Hytale 进行身份认证
步骤 3:使用 Hytale 认证
在代理控制台中运行:
auth login
访问显示的网址并输入设备码以关联您的 Hytale 账号。
代理配置
编辑 config/proxy.yml:
# 网络设置
bindAddress: "0.0.0.0"
bindPort: 45585
# 公共地址(用于服务器传送)
publicAddress: "play.yourserver.com"
publicPort: 45585
# 共享密钥 - 必须与你的 Bridge 插件配置一致!
proxySecret: "change-this-to-a-secure-secret"
# 后端服务器
backends:
- name: "lobby"
host: "127.0.0.1"
port: 5520
defaultServer: true # 玩家优先加入此服务器
- name: "survival"
host: "127.0.0.1"
port: 5521
defaultServer: false
- name: "minigames"
host: "192.168.1.100"
port: 5520
defaultServer: false
配置选项
| 选项 | 描述 |
|---|---|
bindAddress |
监听 IP(0.0.0.0 表示所有接口) |
bindPort |
监听端口(默认:45585) |
publicAddress |
用于服务器传送的公共主机名/IP |
publicPort |
用于服务器传送的公共端口 |
proxySecret |
用于后端认证的共享密钥 |
backends |
后端服务器列表 |
debugMode |
启用详细日志(默认:false) |
后端服务器设置
每个后端服务器都需要 Bridge 插件 来认证来自代理的连接。
步骤 1:安装 Bridge 插件
将 bridge-1.0-SNAPSHOT.jar 复制到 Hytale 服务器的 plugins/ 文件夹。
步骤 2:以不安全模式启动服务器
java -jar HytaleServer.jar --auth-mode insecure --transport QUIC
重要:
--auth-mode insecure标志是必需的,因为代理负责处理 Hytale 认证,而非后端。
步骤 3:配置 Bridge
首次运行时,Bridge 会创建 plugins/Bridge/config.json:
{
"proxySecret": "change-this-to-a-secure-secret",
"serverName": "lobby"
}
| 选项 | 描述 |
|---|---|
proxySecret |
必须与代理配置文件中的 proxySecret 一致! |
serverName |
此服务器的名称(用于日志记录和标识) |
步骤 4:保护后端安全(重要!)
屏蔽对后端服务器的直接连接。仅允许代理的 IP 连接:
# 示例:仅允许代理(192.168.1.50)连接 5520 端口
iptables -A INPUT -p udp --dport 5520 -s 192.168.1.50 -j ACCEPT
iptables -A INPUT -p udp --dport 5520 -j DROP
若不设置,玩家可能绕过代理直接连接!
玩家指令
| 指令 | 别名 | 描述 |
|---|---|---|
/server |
/srv |
列出可用服务器 |
/server <名称> |
/srv <名称> |
传送到指定服务器 |
/numdrassl |
/nd, /proxy |
代理管理指令 |
/numdrassl version |
显示代理版本 | |
/numdrassl perm ... |
权限管理 |
权限系统
权限存储在 data/permissions/ 目录下的 YAML 文件中:
data/permissions/
├── players/
│ └── {uuid}.yml # 单个玩家权限
├── groups/
│ ├── default.yml # 默认组(所有玩家)
│ └── admin.yml # 自定义组
└── player-groups.yml # 玩家与组的对应关系
玩家权限(players/{uuid}.yml)
permissions:
- numdrassl.command.server
- numdrassl.command.help
- -numdrassl.command.stop # 拒绝(前缀加 -)
组权限(groups/admin.yml)
name: admin
default: false
permissions:
- numdrassl.command.* # 通配符
- numdrassl.admin
权限指令
| 指令 | 描述 |
|---|---|
/numdrassl perm user <玩家> info |
显示玩家的组别和权限 |
/numdrassl perm user <玩家> add <权限> |
授予权限 |
/numdrassl perm user <玩家> remove <权限> |
移除权限 |
/numdrassl perm user <玩家> addgroup <组> |
将玩家添加至组 |
/numdrassl perm user <玩家> removegroup <组> |
将玩家移出组 |
/numdrassl perm group <组> add <权限> |
为组添加权限 |
/numdrassl perm group <组> remove <权限> |
为组移除权限 |
/numdrassl perm reload |
从磁盘重新加载权限 |
控制台指令
| 指令 | 描述 |
|---|---|
auth login |
使用 Hytale 认证 |
auth status |
显示认证状态 |
auth logout |
清除已存储的凭据 |
sessions |
列出已连接的玩家 |
stop |
关闭代理 |
help |
显示可用的指令 |
插件开发
创建插件以扩展代理功能!插件可以:
- 监听事件(玩家加入、聊天、指令等)
- 注册自定义指令
- 修改数据包
- 与玩家和服务器互动
API 依赖:
dependencies {
compileOnly("me.internalizable.numdrassl:api:1.0-SNAPSHOT")
}
插件示例:
@Plugin(id = "my-plugin", name = "My Plugin", version = "1.0.0")
public class MyPlugin {
@Subscribe
public void onPlayerChat(PlayerChatEvent event) {
if (event.getMessage().contains("hello")) {
event.getPlayer().sendMessage("你好呀!");
}
}
}
更多详情请参阅完整的插件开发指南。
故障排除
"Proxy not authenticated"
在代理控制台中运行 auth login 并完成设备代码流程。
"Invalid player info message (is your proxy secret valid?)"
代理配置文件中的 proxySecret 与 Bridge 插件的 proxySecret 不一致。
"Connection timed out" 连接后端超时
- 检查后端服务器是否在运行
- 确认防火墙允许代理 IP 连接
- 确保配置文件中的地址和端口正确
"Cannot direct join numdrassl backend"
玩家尝试直接连接后端。请设置防火墙规则以阻止直接连接。
客户端显示 "unexpected packet"
后端服务器可能未安装 Bridge 插件,或未使用 --auth-mode insecure 启动。
Redis 连接失败(集群模式)
- 确认 Redis 服务器正在运行且可访问
- 检查配置文件中的
redis.host和redis.port - 如果使用了认证,确保
redis.password正确 - 确认防火墙允许连接 Redis 端口
多个代理间玩家未同步(集群模式)
- 确保所有代理的
cluster.enabled: true - 确认所有代理连接到同一个 Redis 实例
- 检查每个代理的
cluster.proxyId是否唯一
架构概览
单代理模式
┌─────────────┐ ┌─────────────┐ ┌─────────────┐
│ 玩家 │ ──── QUIC/TLS ──── │ 代理 │ ──── QUIC/TLS ──── │ 后端 │
│ 客户端 │ │ Numdrassl │ │ 服务器 │
└─────────────┘ └─────────────┘ └─────────────┘
│
├── lobby(默认)
├── survival
└── minigames
集群模式(多代理)
┌──────────────────────────────────┐
│ Redis │
│ ┌────────────────────────┐ │
│ │ Pub/Sub 频道 │ │
│ │ • numdrassl:heartbeat │ │
│ │ • numdrassl:chat │ │
│ │ • numdrassl:transfer │ │
│ │ • numdrassl:broadcast │ │
│ └────────────────────────┘ │
│ ┌────────────────────────┐ │
│ │ 共享状态 │ │
│ │ • 玩家位置 │ │
│ │ • 代理注册表 │ │
│ │ • 玩家数量 │ │
│ └────────────────────────┘ │
└──────────────┬───────────────────┘
│
┌─────────────────────────────────┼─────────────────────────────────┐
│ │ │
┌──────▼──────┐ ┌──────▼──────┐ ┌──────▼──────┐
│ 代理(EU) │ │ 代理(US) │ │ 代理(Asia)│
│ proxy-eu-1 │◄─── 传送 ───────►│ proxy-us-1 │◄─── 传送 ───────►│ proxy-as-1 │
└──────┬──────┘ └──────┬──────┘ └──────┬──────┘
│ │ │
┌──────▼──────┐ ┌──────▼──────┐ ┌──────▼──────┐
│ 后端 │ │ 后端 │ │ 后端 │
│ • lobby │ │ • lobby │ │ • lobby │
│ • games │ │ • games │ │ • games │
└─────────────┘ └─────────────┘ └─────────────┘
认证流程
┌────────┐ ┌───────────┐ ┌─────────────┐ ┌─────────┐
│ 玩家 │ │ 代理 │ │ Hytale │ │ 后端 │
└───┬────┘ └─────┬─────┘ │ Sessions │ └────┬────┘
│ │ └──────┬──────┘ │
│ 1. 连接 │ │ │
│ (identity_token) │ │ │
│────────────────────►│ │ │
│ │ 2. 请求认证授权 │ │
│ │──────────────────────►│ │
│ │ │ │
│ │ 3. auth_grant │ │
│ │◄──────────────────────│ │
│ 4. AuthGrant │ │ │
│◄────────────────────│ │ │
│ │ │ │
│ 5. AuthToken │ │ │
│────────────────────►│ 6. 交换令牌 │ │
│ │──────────────────────►│ │
│ │◄──────────────────────│ │
│ 7. ServerAuthToken │ │ │
│◄────────────────────│ │ │
│ │ │ │
│ │ 8. 连接 + HMAC 签名引荐 │
│ │─────────────────────────────────────────────►│
│ │ │ │
│ │ 9. ConnectAccept(密钥已验证) │
│ │◄─────────────────────────────────────────────│
│ │ │ │
跨代理传送流程
┌────────┐ ┌──────────┐ ┌──────────┐ ┌─────────┐
│ 玩家 │ │ 代理 A │ │ 代理 B │ │ 后端 │
│ │ │ (源) │ Redis │ (目标) │ │ 服务器 │
└───┬────┘ └────┬─────┘ │ └────┬─────┘ └────┬────┘
│ │ │ │ │
│ /server hub │ │ │ │
│──────────────►│ │ │ │
│ │ │ │ │
│ │ 1. 发布 │ │ │
│ │ TransferMsg │ │ │
│ │─────────────►│ │ │
│ │ │ │ │
│ │ │ 2. 订阅 │ │
│ │ │ 接收消息 │ │
│ │ │───────────────►│ │
│ │ │ │ │
│ 3. ClientReferral │ │ │
│ (重新连接到代理 B) │ │ │
│◄──────────────│ │ │ │
│ │ │ │ │
│ 4. 新连接 │ │ │
│─────────────────────────────────────────────►│ │
│ │ │ │ │
│ │ │ │ 5. 转发 │
│ │ │ │ 至后端 │
│ │ │ │───────────────►│
- 玩家连接至代理,提供其 Hytale 凭据
- 代理向 Hytale 会话服务认证玩家
- 代理使用签名引荐将连接转发至默认后端
- 后端使用共享密钥验证引荐
- 数据包通过代理双向传输
- 在集群模式下,玩家状态和消息通过 Redis 的发布/订阅同步
集群模式(多代理网络)
对于大型网络,您可以在不同区域运行多个 Numdrassl 代理,并使用 Redis 共享状态。
概述
┌─────────────────┐
│ Redis │
│ 发布/订阅中心 │
└────────┬────────┘
┌───────────────────────┼───────────────────────┐
│ │ │
┌───────▼───────┐ ┌───────▼───────┐ ┌───────▼───────┐
│ 代理(EU) │ │ 代理(US) │ │ 代理(亚洲) │
│ 区域: eu │ │ 区域: us │ │ 区域: asia │
└───────┬───────┘ └───────┬───────┘ └───────┬───────┘
│ │ │
┌───────▼───────┐ ┌───────▼───────┐ ┌───────▼───────┐
│ 后端 │ │ 后端 │ │ 后端 │
└───────────────┘ └───────────────┘ └───────────────┘
集群功能
- 跨代理玩家追踪 - 知晓所有代理上的在线玩家
- 跨代理消息 - 向其他代理上的玩家发送消息
- 跨代理传送 - 在不同代理上的服务器间传送玩家
- 负载均衡 - 将玩家路由至其所在区域负载最低的代理
- 健康监控 - 自动心跳和失效代理检测
Redis 配置
添加至 config/proxy.yml:
# 集群设置
cluster:
enabled: true
# 此代理实例的唯一 ID(未设置时自动生成)
proxyId: "proxy-eu-1"
# 用于地理负载均衡的区域标识符
region: "eu"
# Redis 连接设置
redis:
host: "redis.yourserver.com"
port: 6379
password: "your-redis-password" # 可选
database: 0
# 连接池设置
poolSize: 10
timeout: 5000 # 毫秒
集群配置选项
| 选项 | 描述 |
|---|---|
cluster.enabled |
启用集群模式(true/false) |
cluster.proxyId |
此代理实例的唯一标识符 |
cluster.region |
地理区域(例如 eu, us, asia) |
redis.host |
Redis 服务器主机名 |
redis.port |
Redis 服务器端口(默认:6379) |
redis.password |
Redis 认证密码(可选) |
redis.database |
Redis 数据库编号(默认:0) |
redis.poolSize |
连接池大小(默认:10) |
redis.timeout |
连接超时时间(毫秒,默认:5000) |
跨代理指令
集群模式启用时:
| 指令 | 描述 |
|---|---|
/server <名称> |
传送到服务器(跨代理工作) |
/numdrassl cluster info |
显示集群状态和已连接的代理 |
/numdrassl cluster players |
列出所有代理上的玩家 |
插件消息 API
插件可跨集群发送消息:
@Plugin(id = "my-plugin", name = "My Plugin", version = "1.0.0")
public class MyPlugin {
@Inject
private MessagingService messaging;
// 订阅自定义消息
@Subscribe(channel = "my-channel")
public void onCustomMessage(MyCustomData data) {
// 处理来自任何代理的消息
}
// 向所有代理发布消息
public void broadcastToCluster(String message) {
messaging.publish("my-channel", new MyCustomData(message));
}
}
系统频道
集群使用以下内部频道(插件可订阅):
| 频道 | 用途 |
|---|---|
numdrassl:heartbeat |
代理健康监控 |
numdrassl:player_count |
玩家数量同步 |
numdrassl:chat |
跨代理聊天消息 |
numdrassl:transfer |
跨代理玩家传送 |
numdrassl:broadcast |
全服通告 |
社区
相关链接
许可证
专有 - 保留所有权利。
正在加载版本记录…
正在加载评论…
评论在新手盒子客户端中发表,这里同步展示。