Skip to content

VMess — mihomo

mihomo speaks VMess on both sides. The outbound shape carries every transport (ws, http, h2, grpc), TLS, REALITY, ECH, and the two authentication-extension toggles. The inbound is purposefully thinner — the user list lives directly on the listener.

Outbound

Entry under proxies: with type: vmess. The struct embeds BasicOption (common outbound fields: interface-name, routing-mark, ip-version, dialer-proxy, …) documented on the Proxies page (Phase 3 catch-up).

FieldTypeDefaultAllowed valuesDescription
namestring(required)<string>Unique proxy name.
serverstring(required)<host>Upstream server hostname or IP.
portint(required)<port>Upstream server port.
uuidstring(required)<UUID>User UUID accepted by the server.
alterIdint00 | <int>Legacy MD5-AEAD compatibility. Keep at 0 for the modern AEAD-only mode.
cipherstringautoauto | aes-128-gcm | chacha20-poly1305 | none | zeroSymmetric cipher. mihomo's name for `security`.
udpboolfalsetrue | falseAllow UDP packets to be relayed through this outbound.
networkstringtcptcp | ws | http | h2 | grpcUnderlying transport.
tlsboolfalsetrue | falseWrap the stream in TLS.
alpn[]string[]h2 | http/1.1ALPN list offered during TLS handshake.
skip-cert-verifyboolfalsetrue | falseDisable TLS certificate verification (test only).
fingerprintstring(unset)<SHA256 hex>Pin the server's TLS certificate to this SHA-256 fingerprint.
certificatestring(unset)<PEM file path>Client certificate (mTLS).
private-keystring(unset)<key file path>Private key matching `certificate`.
servernamestring(unset)<SNI>Override the TLS SNI.
ech-optsECHOptions(disabled)ECHOptionsEncrypted Client Hello configuration.
reality-optsRealityOptions(disabled)RealityOptionsREALITY client configuration.
http-optsHTTPOptions(unset)HTTPOptionsSettings for `network: http`.
h2-optsHTTP2Options(unset)HTTP2OptionsSettings for `network: h2`.
grpc-optsGrpcOptions(unset)GrpcOptionsSettings for `network: grpc`.
ws-optsWSOptions(unset)WSOptionsSettings for `network: ws`.
packet-addrboolfalsetrue | falseUse the legacy packet-addr UDP encoding.
xudpboolfalsetrue | falseUse xudp encoding for UDP packets (modern default). Mutually exclusive with packet-addr.
packet-encodingstring(use udp/xudp flags)packetaddr | xudpExplicit packet-encoding selector; overrides the boolean flags when set.
global-paddingboolfalsetrue | falsePad all writes to a uniform length. Server must match.
authenticated-lengthboolfalsetrue | falseUse the authenticated-length framing. Server must match.
client-fingerprintstring(global)chrome | firefox | safari | ios | edge | random | randomizeduTLS client-hello fingerprint.

Source: adapter/outbound/vmess.go:43-72 · pinned at v1.19.27 (5184081)

ws-opts

FieldTypeDefaultAllowed valuesDescription
pathstring//<path>WebSocket path.
headersmap[string]string{}{<header>: <value>}Extra HTTP headers on the upgrade request.
max-early-dataint0<bytes>Maximum bytes of early-data buffered before the WS handshake completes.
early-data-header-namestring(unset)<header name>Header used to carry the base64-encoded early data when the server expects it.
v2ray-http-upgradeboolfalsetrue | falseUse the V2Ray-style HTTP-upgrade transport instead of true WebSocket.
v2ray-http-upgrade-fast-openboolfalsetrue | falseSend the client payload alongside the HTTP-upgrade request to save one RTT.

Source: adapter/outbound/vmess.go:94-101 · pinned at v1.19.27 (5184081)

grpc-opts

FieldTypeDefaultAllowed valuesDescription
grpc-service-namestring(required)<name>gRPC service name path.
grpc-user-agentstring(unset)<UA string>Override the gRPC client User-Agent.
ping-intervalint0<seconds>HTTP/2 PING frame interval. 0 disables.
max-connectionsint0<int>Max concurrent gRPC channels (mux fan-out).
min-streamsint0<int>Minimum streams per channel before allocating a new channel.
max-streamsint0<int>Maximum streams per channel.

Source: adapter/outbound/vmess.go:85-92 · pinned at v1.19.27 (5184081)

Inbound

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

FieldTypeDefaultAllowed valuesDescription
users[]VmessUser(required)<VmessUser array>Accepted clients.
ws-pathstring(unset)/<path>WebSocket path served on this listener.
grpc-service-namestring(unset)<name>gRPC service name accepted on this listener.
certificatestring(unset)<PEM file path>TLS server certificate.
private-keystring(unset)<key file path>TLS private key.
client-auth-typestring(none)no-client-cert | request-client-cert | require-any-client-cert | verify-client-cert-if-given | require-and-verify-client-certMutual-TLS client-auth mode.
client-auth-certstring(unset)<PEM file path>CA bundle accepted as client roots.
ech-keystring(unset)<ECH config>Encrypted Client Hello material.
reality-configRealityConfig(disabled)RealityConfigREALITY server configuration.
mux-optionMuxOption(disabled)MuxOptionMultiplex settings (sing-style mux).

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

users[]

FieldTypeDefaultAllowed valuesDescription
usernamestring(unset)<string>Display name.
uuidstring(required)<UUID>User UUID.
alterIdint00 | <int>Legacy MD5-AEAD compatibility.

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

Examples

Outbound — VMess over WebSocket with TLS:

yaml
proxies:
  - name: vmess-ws
    type: vmess
    server: example.com
    port: 443
    uuid: a3482e88-686a-4a58-8126-99c9df64b7bf
    alterId: 0
    cipher: auto
    udp: true
    network: ws
    tls: true
    servername: example.com
    ws-opts:
      path: /vm
      headers:
        Host: example.com

Outbound — VMess over gRPC with REALITY:

yaml
proxies:
  - name: vmess-grpc
    type: vmess
    server: example.com
    port: 443
    uuid: a3482e88-686a-4a58-8126-99c9df64b7bf
    alterId: 0
    cipher: auto
    network: grpc
    tls: true
    servername: www.cloudflare.com
    client-fingerprint: chrome
    reality-opts:
      public-key: <reality public key>
      short-id: <short id>
    grpc-opts:
      grpc-service-name: GunService

Inbound under listeners:

yaml
listeners:
  - name: vmess-in
    type: vmess
    listen: 0.0.0.0
    port: 443
    users:
      - username: alice
        uuid: a3482e88-686a-4a58-8126-99c9df64b7bf
        alterId: 0
    certificate: /etc/mihomo/server.crt
    private-key: /etc/mihomo/server.key

Notes

  • mihomo's outbound uses cipher for the symmetric algorithm. Both Xray (security) and sing-box (security) call this field differently. Allowed values are otherwise the same: auto, aes-128-gcm, chacha20-poly1305, none, zero.
  • Three different UDP-encoding switches are exposed on the outbound: udp (boolean — enable UDP relay at all), xudp / packet-addr (legacy boolean selectors), and packet-encoding (modern explicit selector). When packet-encoding is set, the boolean selectors are ignored.
  • global-padding and authenticated-length mirror sing-box's global_padding / authenticated_length — both sides must agree.
  • ws-opts.v2ray-http-upgrade swaps the WebSocket handshake for the V2Ray HTTP-upgrade transport; v2ray-http-upgrade-fast-open further saves an RTT by piggybacking the client payload.

Cross-core notes

  • Xray is AEAD-only and removes alterId entirely; the field name is security (not cipher). See VMess — Xray-core.
  • sing-box keeps alterId (called alter_id on the outbound, alterId on inbound users), uses security rather than cipher, and surfaces multiplex via a dedicated multiplex block. See VMess — sing-box.

Source: adapter/outbound/vmess.go:43-101 · v1.19.27 (5184081)

Core Tutorial by Argsment