Transport — mihomo
mihomo distributes transport options across *-opts blocks on each proxy entry. There is no consolidated transport struct: the choice of transport is the proxy's network field, and the matching options block is read.
The network selector
Every TLS-capable mihomo proxy has a network: field. Values:
| Value | Meaning |
|---|---|
tcp (default) | Plain TCP; ignore all *-opts blocks. |
ws | WebSocket — read ws-opts. |
http | Plain HTTP disguise (no upgrade) — read http-opts. |
h2 | HTTP/2 — read h2-opts. |
grpc | gRPC over HTTP/2 — read grpc-opts. |
xhttp | XTLS HTTP framing (Xray-compatible) — read xhttp-opts. |
A few protocols add extras (e.g. Trojan supports ws and grpc only; VMess adds http and h2). The matrix is documented per protocol.
ws-opts
| Field | Type | Default | Allowed values | Description |
|---|---|---|---|---|
path | string | / | /<path> | WebSocket path. The `?ed=N` early-data query parameter is supported, matching Xray's convention. |
headers | map[string]string | {} | {<header>: <value>} | Extra HTTP headers on the upgrade request. |
max-early-data | int | 0 | <bytes> | Maximum bytes of 0-RTT early data buffered before the WS handshake completes. |
early-data-header-name | string | (unset) | <header name> | Header used to carry the base64-encoded early data when the server expects it under a custom name. |
v2ray-http-upgrade | bool | false | true | false | Use the V2Ray HTTP-upgrade transport instead of true WebSocket — saves the post-handshake framing overhead. |
v2ray-http-upgrade-fast-open | bool | false | true | false | Piggyback the client payload onto the HTTP-upgrade request itself to save one RTT. |
Source: adapter/outbound/vmess.go:94-101 · pinned at v1.19.27 (5184081)
http-opts — HTTP disguise
| Field | Type | Default | Allowed values | Description |
|---|---|---|---|---|
method | string | GET | <HTTP method> | HTTP method used by the disguise transport. |
path | []string | [/] | [/<path>] | List of paths to rotate across. Client picks one per request. |
headers | map[string][]string | {} | {<header>: [<value>]} | Map of header name to list of values. Client picks one value per request. |
Source: adapter/outbound/vmess.go:74-78 · pinned at v1.19.27 (5184081)
h2-opts — HTTP/2
| Field | Type | Default | Allowed values | Description |
|---|---|---|---|---|
host | []string | [] | [<hostname>] | List of Host header values. Client picks one randomly per request. |
path | string | / | /<path> | HTTP path. |
Source: adapter/outbound/vmess.go:80-83 · pinned at v1.19.27 (5184081)
grpc-opts
| Field | Type | Default | Allowed values | Description |
|---|---|---|---|---|
grpc-service-name | string | (required) | <service name> | gRPC service name path. |
grpc-user-agent | string | (unset) | <UA string> | Override the gRPC client User-Agent. |
ping-interval | int | 0 | <seconds> | HTTP/2 PING frame interval. 0 disables. |
max-connections | int | 0 | <int> | Max concurrent gRPC channels (mux fan-out). |
min-streams | int | 0 | <int> | Minimum streams per channel before allocating a new channel. |
max-streams | int | 0 | <int> | Maximum streams per channel. |
Source: adapter/outbound/vmess.go:85-92 · pinned at v1.19.27 (5184081)
xhttp-opts
The XHTTP block carries 23 fields matching Xray's SplitHTTP. The most-used ones are path, host, mode, plus the x-padding-* and session-related fields for traffic shaping. Reuse settings sit in the nested reuse-settings sub-block; asymmetric download configuration in download-settings. Refer to the VLESS — mihomo page for the full struct (it's shared between VLESS and other XHTTP-capable proxies).
Examples
WebSocket — common VMess shape:
proxies:
- name: vmess-ws
type: vmess
server: example.com
port: 443
uuid: <UUID>
cipher: auto
network: ws
tls: true
servername: example.com
ws-opts:
path: /vm
headers:
Host: example.com
max-early-data: 2048
early-data-header-name: Sec-WebSocket-ProtocolgRPC + REALITY (VLESS):
proxies:
- name: vless-grpc-reality
type: vless
server: example.com
port: 443
uuid: <UUID>
flow: xtls-rprx-vision
tls: true
servername: www.cloudflare.com
client-fingerprint: chrome
network: grpc
reality-opts:
public-key: <base64>
short-id: <hex>
grpc-opts:
grpc-service-name: GunServiceV2Ray HTTP-upgrade (alternative to WS, lower CPU):
proxies:
- name: vmess-httpupgrade
type: vmess
server: example.com
port: 443
uuid: <UUID>
cipher: auto
network: ws
tls: true
servername: example.com
ws-opts:
path: /up
v2ray-http-upgrade: true
v2ray-http-upgrade-fast-open: trueNotes
- mihomo's
network: wscovers both standard WebSocket and the V2Ray-style HTTP-upgrade transport (via thev2ray-http-upgradetoggle inws-opts). There is no separatenetwork: httpupgradevalue. network: httpis the legacy V2Ray HTTP disguise (plain HTTP/1.1 with fake methods). Don't confuse withnetwork: h2(real HTTP/2) ornetwork: xhttp(Xray's modern XTLS framing).http-opts.pathandhttp-opts.headersare randomized per request — mihomo picks one value from each list for each new connection.ws-opts.v2ray-http-upgrade-fast-opensaves one RTT by sending the client payload alongside the upgrade request. Servers that buffer the full upgrade before responding (some load balancers) will reject this; test both before deploying.xhttp-optsis the Xray-compat path for clients that need to talk to Xray'snetwork: splithttpservers. The field names match Xray's SplitHTTP exactly (kebab-cased).
Cross-core notes
- Xray-core uses
streamSettings.network+ a per-transport*Settingsblock. Has TCP-with-header-obfs, mKCP, and SplitHTTP variants that mihomo doesn't expose under those names. See Transport — Xray-core. - sing-box uses a polymorphic
transport: { type, ... }block embedded on every proxy. See Transport — sing-box.
Source: adapter/outbound/vmess.go:74-101 · v1.19.27 (5184081)
