Skip to content

Shadowsocks — mihomo

mihomo speaks Shadowsocks on both sides, with a rich plugin ecosystem that wraps the wire format inside obfs, WebSocket (v2ray-plugin / gost-plugin), Shadow-TLS, REALTLS, or KCP. Plugin configuration goes under the typed plugin-opts YAML map.

Outbound

Entry under proxies: with type: ss. Embeds BasicOption.

FieldTypeDefaultAllowed valuesDescription
namestring(required)<string>Unique proxy name.
serverstring(required)<host>Upstream server hostname or IP.
portint(required)<port>Upstream server port.
passwordstring(required)<string> | <base64 key>Server password (AEAD) or EIH key (SS-2022).
cipherstring(required)aes-128-gcm | aes-256-gcm | chacha20-ietf-poly1305 | xchacha20-ietf-poly1305 | 2022-blake3-aes-128-gcm | 2022-blake3-aes-256-gcm | 2022-blake3-chacha20-poly1305 | nonemihomo's name for the Shadowsocks cipher / key-derivation scheme.
udpboolfalsetrue | falseAllow UDP packets to be relayed through this outbound.
pluginstring(unset)obfs | v2ray-plugin | gost-plugin | shadow-tls | restls | kcptunObfuscation / transport plugin to wrap the stream. Each plugin has its own `plugin-opts` schema (documented below).
plugin-optsmap[string]any{}<plugin-specific YAML map>Plugin-specific configuration. Schema depends on `plugin` — see the sub-sections below.
udp-over-tcpboolfalsetrue | falseWrap UDP inside the TCP stream.
udp-over-tcp-versionint21 | 2UoT framing version.
client-fingerprintstring(global)chrome | firefox | safari | ios | edge | random | randomizeduTLS client-hello fingerprint applied when the plugin uses TLS.

Source: adapter/outbound/shadowsocks.go:41-54 · pinned at v1.19.27 (5184081)

plugin-opts — when plugin: obfs

Wraps the stream in simple-obfs (TLS-shaped or HTTP-shaped).

FieldTypeDefaultAllowed valuesDescription
modestringtlstls | httpObfs mode. `tls` mimics a TLS Client Hello; `http` mimics a plain HTTP request.
hoststring(unset)<host>Cover hostname used in the obfs payload.

Source: adapter/outbound/shadowsocks.go:56-59 · pinned at v1.19.27 (5184081)

plugin-opts — when plugin: v2ray-plugin

Wraps the stream in a WebSocket handshake. Optional TLS.

FieldTypeDefaultAllowed valuesDescription
modestring(required)websocketCurrently only `websocket` is supported.
hoststring(unset)<host>Host header sent on the WS handshake.
pathstring//<path>WebSocket path.
tlsboolfalsetrue | falseWrap the WS handshake in TLS.
ech-optsECHOptions
fingerprintstring(unset)<SHA256 hex>Pin the server's TLS certificate fingerprint.
certificatestring(unset)<PEM file path>Client certificate (mTLS).
private-keystring(unset)<key file path>Private key matching `certificate`.
headersmap[string]string{}{<header>: <value>}Extra HTTP headers on the upgrade request.
skip-cert-verifyboolfalsetrue | falseDisable TLS verification.
muxboolfalsetrue | falseEnable smux on top of the WS stream.
v2ray-http-upgradeboolfalsetrue | falseUse V2Ray HTTP-upgrade instead of standard WebSocket.
v2ray-http-upgrade-fast-openboolfalsetrue | falsePiggyback the payload on the HTTP-upgrade request.

Source: adapter/outbound/shadowsocks.go:61-75 · pinned at v1.19.27 (5184081)

plugin-opts — when plugin: shadow-tls

Adds a Shadow-TLS handshake in front of the Shadowsocks stream.

FieldTypeDefaultAllowed valuesDescription
passwordstring(unset)<string>Shadow-TLS v2/v3 password.
hoststring(required)<host>Cover hostname for the TLS handshake.
fingerprintstring(unset)<SHA256 hex>Pin the cover server's TLS certificate.
certificatestring(unset)<PEM file path>Client certificate.
private-keystring(unset)<key file path>Private key.
skip-cert-verifyboolfalsetrue | falseDisable cert verification (test only).
versionint31 | 2 | 3Shadow-TLS protocol version. v3 is the current production version.
alpn[]string[]h2 | http/1.1ALPN list offered during the cover-TLS handshake.

Source: adapter/outbound/shadowsocks.go:91-100 · pinned at v1.19.27 (5184081)

Other plugin variants (gost-plugin, restls, kcptun) carry their own schema under plugin-opts. Their structs (gostObfsOption, restlsOption, kcpTunOption) live in the same source file; see the extracted data for the full field list.

Inbound

Entry under listeners: with type: ss. Embeds BaseOption.

FieldTypeDefaultAllowed valuesDescription
passwordstring(required)<string> | <base64 key>Server password or SS-2022 key.
cipherstring(required)<cipher>Same cipher set as the outbound.
udpboolfalsetrue | falseAccept UDP packets.
mux-optionMuxOption(disabled)MuxOptionsing-style multiplex.
shadow-tlsShadowTLS(disabled)ShadowTLSOptional inbound Shadow-TLS wrap.
kcp-tunKcpTun(disabled)KcpTunOptional inbound KCP transport.
simple-obfsSimpleObfs(disabled)SimpleObfssimple-obfs (obfs-local) settings: `{ enable, mode }` where `mode` is `http` or `tls`.

Source: listener/inbound/shadowsocks.go:12-21 · pinned at v1.19.27 (5184081)

simple-obfs

Built-in simple-obfs wrap on the listener — no external plugin binary.

FieldTypeDefaultAllowed valuesDescription
enableboolfalsetrue | falseEnable simple-obfs on the listener.
modestringtlshttp | tlsObfs mode. `tls` mimics a TLS Client Hello; `http` mimics a plain HTTP request.

Source: listener/inbound/shadowsocks.go:23-26 · pinned at v1.19.27 (5184081)

Examples

Plain SS outbound:

yaml
proxies:
  - name: ss-aead
    type: ss
    server: example.com
    port: 8388
    password: <password>
    cipher: aes-256-gcm
    udp: true

SS-2022 outbound with UDP-over-TCP:

yaml
proxies:
  - name: ss22
    type: ss
    server: example.com
    port: 8388
    password: <base64 16-byte key>
    cipher: 2022-blake3-aes-128-gcm
    udp-over-tcp: true
    udp-over-tcp-version: 2

SS over v2ray-plugin (WebSocket + TLS):

yaml
proxies:
  - name: ss-v2ray
    type: ss
    server: example.com
    port: 443
    password: <password>
    cipher: aes-256-gcm
    udp: true
    plugin: v2ray-plugin
    plugin-opts:
      mode: websocket
      tls: true
      host: example.com
      path: /ss

SS in front of Shadow-TLS v3:

yaml
proxies:
  - name: ss-stls
    type: ss
    server: example.com
    port: 443
    password: <ss password>
    cipher: aes-256-gcm
    plugin: shadow-tls
    plugin-opts:
      password: <stls password>
      host: www.cloudflare.com
      version: 3

Inbound under listeners:

yaml
listeners:
  - name: ss-in
    type: ss
    listen: 0.0.0.0
    port: 8388
    password: <password>
    cipher: aes-256-gcm
    udp: true

Notes

  • mihomo's outbound takes plugin-opts as a typed YAML map decoded into one of the per-plugin structs. Tag values on those structs use obfs: instead of proxy: — this is a mihomo-internal convention, not user-facing — see for example simpleObfsOption at adapter/outbound/shadowsocks.go:56-59.
  • The plugin: obfs option is mihomo's name for simple-obfs; pass mode: tls for the TLS-shaped form and mode: http for the HTTP-shaped one.
  • mihomo's listener inbound does not currently support users[] multi-user — for multiple SS-2022 users on the same port, define one listener per user.

Cross-core notes

  • Xray uses method (not cipher) and uot/uotVersion. It has no plugin system — wrap the Shadowsocks payload in another streamSettings transport instead. See Shadowsocks — Xray-core.
  • sing-box uses method, supports the destinations[] relay shape for SS-2022, and represents UoT as the object form udp_over_tcp: {enabled, version}. It also accepts external plugin binaries via plugin / plugin_opts. See Shadowsocks — sing-box.

Source: adapter/outbound/shadowsocks.go:41-100 · v1.19.27 (5184081)

Core Tutorial by Argsment