Snell — sing-box
Snell is Surge's lightweight proxy protocol. sing-box implements both sides: a snell inbound (server) and a snell outbound (client). The implementation covers every Snell feature except the v5 QUIC proxy mode, so the versions differ per side — the inbound serves version 5 or 6, the outbound speaks version 4 or 6. No build tag is needed.
Inbound
type: "snell" under inbounds[], plus the usual listen fields (listen, listen_port, …):
| Field | Type | Default | Allowed values | Description |
|---|---|---|---|---|
version | int | (required) | 5 | 6 | Snell version this inbound serves. 5 accepts Surge v4 and v5 clients (the v5 QUIC proxy mode is not implemented, so the TCP wire format is the same as v4); 6 accepts v6 clients. A missing or other value fails at startup. |
Source: option/snell.go:12-17 · pinned at v1.14.2 (af6e64c)
| Field | Type | Default | Allowed values | Description |
|---|---|---|---|---|
psk | string | (required) | <string> | Server pre-shared key. Version 6 requires 12 to 255 bytes. |
users | []SnellUser | [] | [SnellUser] | Enables multi-user mode: each client authenticates with its own userkey, while psk stays the server key. |
Source: option/snell.go:19-23 · pinned at v1.14.2 (af6e64c)
users[]
| Field | Type | Default | Allowed values | Description |
|---|---|---|---|---|
name | string | (unset) | <string> | Optional label used in logs. |
userkey | string | (required) | <string> | The user's key. Clients send it as the outbound userkey. |
Source: option/snell.go:135-138 · pinned at v1.14.2 (af6e64c)
Outbound
type: "snell" under outbounds[], plus server / server_port and the dial fields:
| Field | Type | Default | Allowed values | Description |
|---|---|---|---|---|
version | int | (required) | 4 | 6 | Snell version to speak. 4 talks to v4 and v5 servers (v5 without its QUIC proxy mode is wire-compatible with v4); 6 talks to v6 servers. A missing or other value fails at startup. |
Source: option/snell.go:70-75 · pinned at v1.14.2 (af6e64c)
| Field | Type | Default | Allowed values | Description |
|---|---|---|---|---|
psk | string | (required) | <string> | Server pre-shared key; must match the server. |
userkey | string | (unset) | <string> | User key for a multi-user server. Leave empty for a single-user server. Version 6 rejects keys longer than 255 bytes. |
reuse | bool | false | true | false | Reuse server connections through the Snell v2 CONNECT command instead of opening a new TCP connection per request. |
network | NetworkList | (tcp and udp) | tcp | udp | Networks this outbound handles. UDP is carried inside a TCP connection to the server. |
Source: option/snell.go:77-84 · pinned at v1.14.2 (af6e64c)
Version-specific fields
These keys sit at the top level of the inbound or outbound object, next to version. sing-box reads only the keys that belong to the selected version; a key from another version is rejected as unknown at startup.
Obfuscation — inbound version 5
| Field | Type | Default | Allowed values | Description |
|---|---|---|---|---|
obfs_mode | string | none | none | http | tls | Version 5 only. Obfuscation the server expects: none, an HTTP-request disguise, or a TLS-record disguise. Must match the clients. |
Source: option/snell.go:131-133 · pinned at v1.14.2 (af6e64c)
Obfuscation — outbound version 4
| Field | Type | Default | Allowed values | Description |
|---|---|---|---|---|
obfs_mode | string | none | none | http | tls | Version 4 only. Obfuscation wrapped around the connection; must match the server. |
obfs_host | string | bing.com (http) / cloudfront.net (tls) | <hostname> | Version 4 only. Host shown by the obfuscation: the HTTP Host header in http mode, the server name of the fake ClientHello in tls mode. |
Source: option/snell.go:140-143 · pinned at v1.14.2 (af6e64c)
Traffic shaping — version 6 (both sides)
| Field | Type | Default | Allowed values | Description |
|---|---|---|---|---|
mode | string | default | default | unshaped | unsafe-raw | Version 6 only. default shapes traffic with a PSK-derived record and padding profile; unshaped keeps the AEAD encryption but drops the shaping; unsafe-raw sends records without encryption. Use the same mode on both sides. |
Source: option/snell.go:145-147 · pinned at v1.14.2 (af6e64c)
Examples
Version 6 server with two users:
{
"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>" }
]
}
]
}Version 6 client for that server:
{
"outbounds": [
{
"type": "snell",
"tag": "snell-out",
"server": "snell.example.com",
"server_port": 8443,
"version": 6,
"psk": "<at-least-12-byte-psk>",
"userkey": "<alice-key>"
}
]
}Version 4 client with HTTP obfuscation (works against v4 and v5 servers):
{
"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"
}
]
}Notes
- The version pairs are deliberate: without the v5 QUIC proxy mode, the v5 TCP wire protocol is identical to v4, so sing-box ships a v5 server (which v4 and v5 clients reach) and a v4 client (which reaches v4 and v5 servers), but no v4 server or v5 client.
obfs_mode: "tls"is accepted by the parser and implemented by the Snell library, although the upstream option reference only listsnoneandhttp.- The inbound listens on TCP only. UDP from clients is relayed inside the TCP stream, and the outbound does the same, so no UDP port has to be opened on the server.
unsafe-rawremoves the encryption layer entirely. Only use it where the path is already protected (for example inside another tunnel).- In multi-user mode the top-level
pskis still required and shared by all users; each user is identified by itsuserkey.
Cross-core notes
- mihomo has Snell on both sides as well, with kebab-case keys: the outbound accepts
version1–5 (it dials v5 servers as v4) and nests obfuscation underobfs-opts(http/tls, plus theshadow-tls/restls/jlscamouflage layers); the inbound usesobfs-optswithhttp/tls. mihomo has no Snell v6. See Snell — mihomo. - Xray-core does not support Snell.
Source: option/snell.go:12-147 · v1.14.2 (af6e64c)
