Skip to content

Snell — mihomo

Snell is Surge's lightweight proxy protocol. mihomo implements both a Snell outbound (to connect to a Snell server) and, more recently, a Snell inbound listener (to act as one). Both sides support the simple-obfs obfuscation layer with http or tls modes; the outbound's obfs-opts.mode additionally accepts the shadow-tls, restls, and jls TLS-camouflage layers, whose inbound counterparts are the dedicated shadow-tls / res-tls / jls-config listener blocks.

Outbound

Entry under proxies: with type: snell. Embeds BasicOption (common outbound fields).

FieldTypeDefaultAllowed valuesDescription
namestring(required)<string>Unique proxy name.
serverstring(required)<host>Upstream server hostname or IP.
portint(required)<port>Upstream server port.
pskstring(required)<string>Pre-shared key (password).
udpboolfalsetrue | falseEnable UDP relaying (Snell v2+).
versionint11 | 2 | 3 | 4 | 5Snell protocol version. v5 servers are backward-compatible with v4 clients, so mihomo dials them as v4.
reuseboolfalsetrue | falseReuse underlying connections.
obfs-optsmap[string]any(disabled){ mode, ... }Obfuscation options. `mode` selects `http` / `tls` (simple-obfs, with `host`), or `shadow-tls` / `restls` / `jls`; the remaining keys follow the matching Shadowsocks plugin schema.
client-fingerprintstring(global)chrome | firefox | safari | ios | edge | random | randomizeduTLS client-hello fingerprint used by the `shadow-tls` / `restls` / `jls` obfs modes.

Source: adapter/outbound/snell.go:32-43 · pinned at v1.19.29 (e26714a)

Inbound

Entry under listeners: with type: snell. Embeds BaseOption (listen, port).

FieldTypeDefaultAllowed valuesDescription
pskstring(required)<string>Pre-shared key (password).
versionint41 | 2 | 3 | 4 | 5Snell protocol version.
udpboolfalsetrue | falseEnable UDP relaying (Snell v2+).
obfs-optsSnellObfsOption(disabled)SnellObfsOptionsimple-obfs options (`{ mode, host }`).
shadow-tlsShadowTLS(disabled)ShadowTLSServer-side Shadow-TLS camouflage block (`{ enable, version, password, users, handshake, ... }`).
res-tlsResTLS(disabled)ResTLSServer-side Restls camouflage block (`{ enable, dest, password, ... }`); unauthenticated clients are relayed to `dest`.
jls-configJLSConfig(disabled)JLSConfigServer-side JLS camouflage block (`{ enable, users, sni, dest, ... }`); unauthenticated clients are relayed to `dest`.

Source: listener/inbound/snell.go:13-22 · pinned at v1.19.29 (e26714a)

obfs-opts

FieldTypeDefaultAllowed valuesDescription
modestring(unset)http | tlsObfuscation mode.
hoststring(unset)<host>Obfuscation host header.

Source: listener/inbound/snell.go:28-31 · pinned at v1.19.29 (e26714a)

Examples

Outbound — plain Snell:

yaml
proxies:
  - name: snell-srv
    type: snell
    server: example.com
    port: 44046
    psk: <pre-shared-key>
    version: 3
    udp: true

Outbound — Snell with HTTP obfuscation:

yaml
proxies:
  - name: snell-obfs
    type: snell
    server: example.com
    port: 44046
    psk: <pre-shared-key>
    version: 3
    obfs-opts:
      mode: http
      host: bing.com

Inbound under listeners:

yaml
listeners:
  - name: snell-in
    type: snell
    listen: 0.0.0.0
    port: 44046
    psk: <pre-shared-key>
    version: 3
    udp: true
    obfs-opts:
      mode: tls
      host: bing.com

Notes

  • psk is the shared secret; the outbound and inbound must use the same value.
  • UDP relaying requires Snell v2 or newer — enabling udp on a v1 peer is rejected.
  • reuse (outbound only) reuses the underlying connection. It is implied for Snell v2; for v4 it is opt-in via this field.
  • obfs-opts.mode selects the obfuscation layer: http wraps the stream in a fake HTTP request, tls in a fake TLS record (the host sets the obfuscation host header), and shadow-tls / restls / jls run the corresponding TLS-camouflage handshake — the remaining obfs-opts keys then follow the same schema as the matching Shadowsocks plugin-opts block (see Shadowsocks). Leave obfs-opts unset for no obfuscation. Both sides must agree on the mode and its settings.
  • The outbound's client-fingerprint only matters for the shadow-tls / restls / jls obfs modes, where it picks the uTLS client-hello mimicked during the camouflage handshake.
  • The inbound accepts only http / tls in obfs-opts; its TLS-camouflage layers are configured through the dedicated shadow-tls / res-tls / jls-config blocks instead, which are mutually exclusive.

Cross-core notes

  • Snell is Surge-specific. Neither Xray-core nor sing-box supports it — there is no equivalent outbound or inbound in either core.

Source: adapter/outbound/snell.go:32-43 · v1.19.29 (e26714a)

Core Tutorial by Argsment