Skip to content

REALITY — sing-box

sing-box 实现 REALITY 两端。入站(内嵌 tls: 块中的 reality: 子块)在 TLS 握手期间冒充第三方站点;出站(同样嵌于 tls: 内部) 只承载公钥与 short ID。

入站 reality

位于 tls.reality。入站需同时设置 tls.enabledtls.reality.enabled 为 true。

字段类型默认值允许值描述
enabledboolfalsetrue | false启用该入站的 REALITY。为 true 时,普通 TLS 握手被 REALITY 握手取代。
handshakeInboundRealityHandshakeOptions(required)InboundRealityHandshakeOptions伪装目标。未授权连接(SNI / short_id 错误)会被透明代理到该地址,使观察者看到流量流向合法站点。
private_keystring(required)<base64 X25519 private key>服务端 X25519 私钥。可用 `sing-box generate reality-keypair` 生成。
short_idbadoption.Listable[string][][<hex string>]允许的 short ID 列表(hex,偶长度,≤ 16 字符)。含 `""` 项允许不声明 short ID 的客户端。
max_time_differencebadoption.Duration0 (no limit)<duration>客户端与服务端之间容忍的最大时钟偏移。超出该窗口的连接被拒绝。0 关闭检查。

源码: option/tls.go:193-199 · 锚定版本 v1.13.11 (553cfa1)

handshake

handshake 子块为伪装上游内嵌 ServerOptionsserverserver_port)与 DialerOptions

json
"handshake": {
  "server": "www.cloudflare.com",
  "server_port": 443,
  "bind_interface": "eth0"
}

出站 reality

位于出站内嵌 tls: 块的 tls.reality

字段类型默认值允许值描述
enabledboolfalsetrue | false启用该出站的 REALITY。
public_keystring(required)<base64 X25519 public key>服务端 X25519 公钥。与服务端 `private_key` 配套。
short_idstring""<hex string>向服务端声明的 short ID。必须命中服务端 `short_id` 之一(或服务端允许时为空)。

源码: option/tls.go:234-238 · 锚定版本 v1.13.11 (553cfa1)

生成密钥

sh
$ sing-box generate reality-keypair
PrivateKey: <base64-private-key>
PublicKey:  <base64-public-key>

私钥用于服务端 private_key,公钥用于客户端 public_key。 short ID 是任意 hex 字符串,按客户端分配。

示例

服务端 —— 冒充 www.cloudflare.com 的 VLESS over REALITY:

json
{
  "inbounds": [{
    "type": "vless",
    "tag": "vless-reality",
    "listen": "::",
    "listen_port": 443,
    "users": [{ "uuid": "...", "flow": "xtls-rprx-vision" }],
    "tls": {
      "enabled": true,
      "server_name": "www.cloudflare.com",
      "reality": {
        "enabled": true,
        "handshake": {
          "server": "www.cloudflare.com",
          "server_port": 443
        },
        "private_key": "<base64-private-key>",
        "short_id": ["", "0123456789abcdef"]
      }
    }
  }]
}

客户端:

json
{
  "outbounds": [{
    "type": "vless",
    "server": "your.server.example",
    "server_port": 443,
    "uuid": "...",
    "flow": "xtls-rprx-vision",
    "tls": {
      "enabled": true,
      "server_name": "www.cloudflare.com",
      "utls": { "enabled": true, "fingerprint": "chrome" },
      "reality": {
        "enabled": true,
        "public_key": "<base64-public-key>",
        "short_id": "0123456789abcdef"
      }
    }
  }]
}

说明

  • handshake.serverhandshake.server_port 共同构成 伪装目 标 —— Xray 中称为 dest。未授权连接被透明代理到此地址,使线 路上的形态看起来是与该站点通信。
  • 出站故意保持最小 —— 只有 public_keyshort_id。其余 (SNI、ALPN、指纹)由外层 tls 块提供。
  • 出站使用 tls.reality 时几乎总要同时设置 tls.utls。没有 uTLS 时 ClientHello 会带有 Go 标准库指纹,与浏览器不匹配,破坏伪装。
  • max_time_difference 是时钟偏移拒绝窗口。服务端与客户端不共享 NTP 时建议设宽(如 1 分钟)。

跨内核说明

  • Xray-core 把 REALITY 字段全放在单一 REALITYConfig 结构体里 (服务端与客户端字段同处一处)。伪装目标即 dest 字段。参见 REALITY — Xray-core
  • mihomo 把结构按入站 / 出站拆分,并使用 kebab-case 字段名 (public-keyprivate-keyshort-idserver-names)。参见 REALITY — mihomo

源码: option/tls.go:193-238 · v1.13.11 (553cfa1)

由 Argsment 出品的 Core Tutorial