ECH — mihomo
mihomo exposes ECH as the ech-opts block on every proxy adapter that speaks TLS. The same 3-field struct is used across VLESS, VMess, Trojan, Hysteria2, TUIC, AnyTLS, and the obfs-flavored Shadowsocks variants.
ech-opts
| Field | Type | Default | Allowed values | Description |
|---|---|---|---|---|
enable | bool | false | true | false | Turn ECH on for this proxy. When false, the rest of the block is ignored. |
config | string | (auto-discover) | <base64 ECHConfigList> | Pinned ECH config list (base64-encoded, standard padding). When unset, mihomo queries the HTTPS DNS record of the server name to auto-discover the config. |
query-server-name | string | (server name) | <hostname> | Override the domain used for the ECH HTTPS-record query. Defaults to the proxy's `sni` / `servername` / `server`. Useful when the cover hostname differs from the actual target. |
Source: adapter/outbound/ech.go:12-17 · pinned at v1.19.27 (5184081)
The same struct is reused as the obfuscation-plugin ECH block (under shadowsocks plugin-opts for v2ray-plugin and gost-plugin), which is why every field has both proxy: and obfs: tags.
Examples
Outbound — VLESS with opportunistic ECH:
yaml
proxies:
- name: vless-ech
type: vless
server: example.com
port: 443
uuid: <UUID>
tls: true
servername: example.com
network: tcp
ech-opts:
enable: trueOutbound — pinned ECH config (base64):
yaml
proxies:
- name: vless-ech-pinned
type: vless
server: example.com
port: 443
uuid: <UUID>
tls: true
servername: example.com
ech-opts:
enable: true
config: <base64 ECHConfigList>
query-server-name: cover.example.comNotes
- mihomo's
configvalue is standard base64 (with padding), not base64-url-safe. If you have a URL-safe-base64 value, convert it first. - Auto-discovery uses mihomo's
ProxyServerHostResolver— the resolver used for resolving proxy hostnames. That resolver in turn obeys the top-leveldns:block, including any DoH/DoT settings. - Inbound mihomo listeners that support ECH (VLESS / VMess / Trojan / Hysteria2 / TUIC / AnyTLS) accept the ECH key bundle in the
ech-keylistener field — see the respective inbound pages. There is no consolidatedech-configinbound block.
Cross-core notes
- Xray-core exposes ECH as fields directly on
tlsSettings(echServerKeys,echConfigList,echForceQuery,echSockopt). See ECH — Xray-core. - sing-box uses a nested
tls.echblock on inbounds and outbounds with snake_case names. See ECH — sing-box.
Source: adapter/outbound/ech.go:12-17 · v1.19.27 (5184081)
