Skip to content

Hysteria realm — sing-box ​

hysteria-realm 是用于 Hysteria2 NAT 穿透的会合服务。位于 NAT 之后的 Hysteria2 服务端通过 STUN 探测自己的公网地址,并以某个 realm ID 注册到该服务;客户端向 realm 查询这些地址,双方进行 UDP 打洞,随后直接建立 QUIC 连接。realm 只承载控制面信令 —— 代理流量从不经过它。

选项 ​

services[] 下的 type: "hysteria-realm":

字段类型默认值允许值描述
users[]HysteriaRealmUser(required)[HysteriaRealmUser]允许使用该 realm 的账户。至少需要一个,否则启动失败。

源码: option/hysteria2.go:235-240 · 锚定版本 v1.14.2 (af6e64c)

该服务还嵌入了 ListenOptions(见入站)、入站 tls 块(见 TLS)以及下方的 HTTP/2 字段。配置 tls 时提供基于 TLS 的 HTTP/2(会自动把 h2 加入 ALPN 列表);否则提供明文 HTTP —— HTTP/1.1,同时也接受明文 HTTP/2。

users[] ​

字段类型默认值允许值描述
namestring(required)<string>账户名,用于日志,也是按用户计算 realm 配额的键。
tokenstring(required)<string>Hysteria2 入站和出站以 Authorization: Bearer <token> 出示的 Bearer 令牌(即它们的 realm.token)。
max_realmsint0<int>该账户可同时持有的 realm 槽位数量。0 表示不限;超出上限时注册会以 HTTP 429 被拒绝。

源码: option/hysteria2.go:229-233 · 锚定版本 v1.14.2 (af6e64c)

HTTP/2 字段 ​

这些字段调节服务的 HTTP/2 服务器,仅在客户端使用 HTTP/2 时有意义。

字段类型默认值允许值描述
idle_timeoutbadoption.Duration(Go default)<duration>关闭空闲达到该时长的 HTTP/2 连接。
keep_alive_periodbadoption.Duration(disabled)<duration>在该时长内未读到任何数据时发送 HTTP/2 PING,以检测失效连接。
stream_receive_window*byteformats.MemoryBytes(Go default)<size>每个流的上传缓冲区(流量控制窗口),以内存大小表示。
connection_receive_window*byteformats.MemoryBytes(Go default)<size>每个连接的上传缓冲区,以内存大小表示。
max_concurrent_streamsint(Go default)<int>每个连接允许的最大并发 HTTP/2 流数。

源码: option/http.go:14-20 · 锚定版本 v1.14.2 (af6e64c)

Hysteria2 如何使用 realm ​

  • 服务端:在 Hysteria2 入站上设置 realm,其中 server_url 指向本服务,token 取自 users[],并给出 realm_id 与 stun_servers。入站会把 STUN 探测到的地址注册到该 ID 下,并通过心跳保持注册有效。
  • 客户端:在 Hysteria2 出站上设置 realm(代替 server),使用相同的 server_url、有效的 token 和相同的 realm_id。出站查询地址、打洞,然后进行正常的 QUIC 握手。
  • 字段细节(ip_version、port_mapping、http_client、stun_domain_resolver)见 Hysteria2 页面。

最简示例 ​

realm 服务,部署在拥有稳定公网地址的主机上:

json
{
  "services": [
    {
      "type": "hysteria-realm",
      "tag": "realm",
      "listen": "::",
      "listen_port": 8443,
      "tls": {
        "enabled": true,
        "certificate_path": "/etc/ssl/realm.pem",
        "key_path": "/etc/ssl/realm.key"
      },
      "users": [
        { "name": "home", "token": "<token>", "max_realms": 2 }
      ]
    }
  ]
}

位于 NAT 之后的 Hysteria2 入站上对应的 realm 块(出站使用相同的 server_url、token 和 realm_id):

json
"realm": {
  "server_url": "https://realm.example.com:8443",
  "token": "<token>",
  "realm_id": "home-server",
  "stun_servers": ["stun.l.google.com:19302"]
}

说明 ​

  • 需要 with_quic 构建标签;缺少时该类型仍存在,但会在启动时失败。
  • users 不能为空,且每个条目都必须同时有 name 和 token。
  • 一个 realm ID 同一时间只能被一次注册持有:第二个服务端注册相同 ID 会得到 HTTP 409(realm_taken)。
  • API 位于 /v1/<realm_id> 之下 —— 若在前面放置反向代理,请保持该路径不变。
  • 只有 realm 需要能被公网访问;位于 NAT 之后的 Hysteria2 服务端无需端口转发。

跨内核说明 ​

  • mihomo 有等价的会合监听器 Hysteria2 realm,使用一个共享 token 加 max-realms / max-realms-per-ip 上限,而非按用户的令牌。
  • Xray-core 没有 realm 服务器;其 realm finalmask UDP 掩码是端点一侧的对应物。参见 Hysteria2 — Xray-core。

源码: option/hysteria2.go:229-240 · v1.14.2 (af6e64c)

由 Argsment 出品的 Core Tutorial