Skip to content

Snell — sing-box ​

Snell 是 Surge 的轻量代理协议。sing-box 实现了两端:snell 入站(服务端)与 snell 出站(客户端)。该实现涵盖除 v5 QUIC 代理模式外的全部 Snell 特性,因此两端的版本不同 —— 入站提供版本 5 或 6,出站使用版本 4 或 6。无需任何构建标签。

入站 ​

位于 inbounds[] 下的 type: "snell",外加常规监听字段(listen、listen_port 等):

字段类型默认值允许值描述
versionint(required)5 | 6该入站提供的 Snell 版本。5 接受 Surge v4 与 v5 客户端(未实现 v5 的 QUIC 代理模式,因此其 TCP 线上格式与 v4 相同);6 接受 v6 客户端。缺失或其他取值会在启动时报错。

源码: option/snell.go:12-17 · 锚定版本 v1.14.2 (af6e64c)

字段类型默认值允许值描述
pskstring(required)<string>服务端预共享密钥。版本 6 要求长度为 12 到 255 字节。
users[]SnellUser[][SnellUser]启用多用户模式:每个客户端用各自的 userkey 鉴权,psk 仍作为服务端密钥。

源码: option/snell.go:19-23 · 锚定版本 v1.14.2 (af6e64c)

users[] ​

字段类型默认值允许值描述
namestring(unset)<string>可选标签,用于日志。
userkeystring(required)<string>该用户的密钥。客户端将其作为出站的 userkey 发送。

源码: option/snell.go:135-138 · 锚定版本 v1.14.2 (af6e64c)

出站 ​

位于 outbounds[] 下的 type: "snell",外加 server / server_port 与拨号字段:

字段类型默认值允许值描述
versionint(required)4 | 6使用的 Snell 版本。4 可连接 v4 与 v5 服务端(去掉 QUIC 代理模式后的 v5 在线上与 v4 兼容);6 连接 v6 服务端。缺失或其他取值会在启动时报错。

源码: option/snell.go:70-75 · 锚定版本 v1.14.2 (af6e64c)

字段类型默认值允许值描述
pskstring(required)<string>服务端预共享密钥;必须与服务端一致。
userkeystring(unset)<string>多用户服务端的用户密钥。单用户服务端留空。版本 6 拒绝超过 255 字节的密钥。
reuseboolfalsetrue | false通过 Snell v2 的 CONNECT 命令复用到服务端的连接,而不是每个请求新建一条 TCP 连接。
networkNetworkList(tcp and udp)tcp | udp该出站处理的网络。UDP 承载在到服务端的 TCP 连接中。

源码: option/snell.go:77-84 · 锚定版本 v1.14.2 (af6e64c)

版本专属字段 ​

这些键与 version 并列,位于入站或出站对象的顶层。sing-box 只读取所选版本对应的键;属于其他版本的键会在启动时作为未知字段被拒绝。

混淆 —— 入站版本 5 ​

字段类型默认值允许值描述
obfs_modestringnonenone | http | tls仅版本 5。服务端期望的混淆:无、HTTP 请求伪装或 TLS 记录伪装。必须与客户端一致。

源码: option/snell.go:131-133 · 锚定版本 v1.14.2 (af6e64c)

混淆 —— 出站版本 4 ​

字段类型默认值允许值描述
obfs_modestringnonenone | http | tls仅版本 4。包裹在连接外的混淆;必须与服务端一致。
obfs_hoststringbing.com (http) / cloudfront.net (tls)<hostname>仅版本 4。混淆所展示的主机名:http 模式下为 HTTP Host 头,tls 模式下为伪造 ClientHello 的服务器名。

源码: option/snell.go:140-143 · 锚定版本 v1.14.2 (af6e64c)

流量整形 —— 版本 6(两端) ​

字段类型默认值允许值描述
modestringdefaultdefault | unshaped | unsafe-raw仅版本 6。default 使用由 PSK 派生的记录与填充配置对流量整形;unshaped 保留 AEAD 加密但不整形;unsafe-raw 发送不加密的记录。两端须使用相同模式。

源码: option/snell.go:145-147 · 锚定版本 v1.14.2 (af6e64c)

示例 ​

带两个用户的版本 6 服务端:

json
{
  "inbounds": [
    {
      "type": "snell",
      "tag": "snell-in",
      "listen": "::",
      "listen_port": 8443,
      "version": 6,
      "psk": "<at-least-12-byte-psk>",
      "users": [
        { "name": "alice", "userkey": "<alice-key>" },
        { "name": "bob", "userkey": "<bob-key>" }
      ]
    }
  ]
}

连接该服务端的版本 6 客户端:

json
{
  "outbounds": [
    {
      "type": "snell",
      "tag": "snell-out",
      "server": "snell.example.com",
      "server_port": 8443,
      "version": 6,
      "psk": "<at-least-12-byte-psk>",
      "userkey": "<alice-key>"
    }
  ]
}

带 HTTP 混淆的版本 4 客户端(可连接 v4 与 v5 服务端):

json
{
  "outbounds": [
    {
      "type": "snell",
      "tag": "snell-v4",
      "server": "snell.example.com",
      "server_port": 8388,
      "version": 4,
      "psk": "<psk>",
      "obfs_mode": "http",
      "obfs_host": "www.bing.com"
    }
  ]
}

说明 ​

  • 版本组合是有意为之:没有 v5 QUIC 代理模式时,v5 的 TCP 线上协议与 v4 完全相同,因此 sing-box 提供 v5 服务端(v4 与 v5 客户端均可连接)和 v4 客户端(可连接 v4 与 v5 服务端),而不提供 v4 服务端或 v5 客户端。
  • 解析器接受 obfs_mode: "tls",Snell 库也实现了它,尽管上游选项文档只列出了 none 与 http。
  • 入站只监听 TCP。客户端的 UDP 在 TCP 流内中继,出站也是如此,因此服务端无需开放 UDP 端口。
  • unsafe-raw 会完全去掉加密层。只应在路径本身已受保护的场景使用(例如位于另一条隧道内)。
  • 多用户模式下顶层 psk 仍为必填,由所有用户共用;每个用户通过其 userkey 识别。

跨内核说明 ​

  • mihomo 同样两端都支持 Snell,键名为 kebab-case:出站接受 version 1–5(以 v4 方式连接 v5 服务端),混淆放在 obfs-opts 下(http / tls,外加 shadow-tls / restls / jls 伪装层);入站的 obfs-opts 支持 http / tls。mihomo 没有 Snell v6。参见 Snell — mihomo。
  • Xray-core 不支持 Snell。

源码: option/snell.go:12-147 · v1.14.2 (af6e64c)

由 Argsment 出品的 Core Tutorial