Skip to content

VLESS — mihomo

mihomo speaks VLESS on both sides. Outbound proxies live under the top-level proxies array (one object per server). Inbounds live under the listeners array. Field names use the proxy: tag convention for outbounds and the inbound: tag convention for listener inbounds.

Outbound

Entry under proxies: with type: vless. The struct embeds BasicOption (common-to-all-outbounds fields: interface-name, routing-mark, ip-version, dialer-proxy, mptcp, …) which is documented on the Proxies page.

FieldTypeDefaultAllowed valuesDescription
namestring(required)<string>Unique proxy name used elsewhere in the YAML (proxy-groups, rules).
serverstring(required)<host>Upstream server hostname or IP.
portint(required)<port>Upstream server port.
uuidstring(required)<UUID>User UUID accepted by the server.
flowstring(empty) | xtls-rprx-visionFlow algorithm. Empty for plain VLESS; `xtls-rprx-vision` enables Vision (requires TLS or REALITY).
tlsboolfalsetrue | falseWrap the stream in TLS. Required for `xtls-rprx-vision`.
alpn[]string[]h2 | http/1.1ALPN list offered during the TLS handshake.
udpboolfalsetrue | falseAllow UDP packets to be relayed through this outbound.
packet-addrboolfalsetrue | falseUse the older packet-addr UDP encoding instead of xudp.
xudpboolfalsetrue | falseUse the xudp encoding for UDP packets (modern default). Mutually exclusive with packet-addr.
packet-encodingstring(use udp/xudp flags)packetaddr | xudpExplicit packet-encoding selector; takes precedence over the boolean flags when set.
encryptionstring(unset)none | mlkem768x25519plus.<...>Optional VLESS encryption suite. `none` (or unset) for the classic mode.
networkstringtcptcp | ws | http | h2 | grpc | xhttpUnderlying transport. The respective `*-opts` block is required when this is non-tcp.
ech-optsECHOptions(disabled)ECHOptionsEncrypted Client Hello configuration; see TLS page (Phase 4).
reality-optsRealityOptions(disabled)RealityOptionsREALITY configuration. Requires `tls: true`.
http-optsHTTPOptions(unset)HTTPOptionsSettings for `network: http` (HTTP/1.1 disguise).
h2-optsHTTP2Options(unset)HTTP2OptionsSettings for `network: h2`.
grpc-optsGrpcOptions(unset)GrpcOptionsSettings for `network: grpc`.
ws-optsWSOptions(unset)WSOptionsSettings for `network: ws`.
xhttp-optsXHTTPOptions(unset)XHTTPOptionsSettings for `network: xhttp` (XTLS HTTP framing).
ws-headersmap[string]string(unset){<header>: <value>}Legacy header-map for WS — prefer the `headers` field inside `ws-opts`.
skip-cert-verifyboolfalsetrue | falseDisable TLS verification of the server certificate. Use only for testing.
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 sent on the handshake.
client-fingerprintstring(global)chrome | firefox | safari | ios | edge | random | randomizeduTLS client-hello fingerprint. Falls back to `global-client-fingerprint`.

Source: adapter/outbound/vless.go:50-79 · pinned at v1.19.27 (5184081)

Inbound

Entry under listeners: with type: vless. Embeds BaseOption (common listener fields: listen, port).

FieldTypeDefaultAllowed valuesDescription
users[]VlessUser(required)<VlessUser array>Accepted clients.
decryptionstring(unset)none | mlkem768x25519plus.<...>Encryption mode the inbound expects. `none` or unset accepts plain VLESS.
ws-pathstring(unset)/<path>WebSocket path the inbound serves.
xhttp-configXHTTPConfig(unset)XHTTPConfigXHTTP transport settings; required when clients connect over xhttp.
grpc-service-namestring(unset)<service name>gRPC service name the inbound serves.
certificatestring(unset)<PEM file path>TLS server certificate (or inline PEM).
private-keystring(unset)<key file path>TLS private key matching `certificate`.
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 configuration material.
allow-insecureboolfalsetrue | falseSkip TLS client-certificate verification on the listener (testing only).
reality-configRealityConfig(disabled)RealityConfigREALITY server configuration; see TLS page (Phase 4).
mux-optionMuxOption(disabled)MuxOptionMultiplex settings shared with sing-style mux.

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

users[]

FieldTypeDefaultAllowed valuesDescription
usernamestring(unset)<string>Display name for the user, used in stats and logs.
uuidstring(required)<UUID>User UUID.
flowstring(empty) | xtls-rprx-visionPer-user flow algorithm.

Source: listener/inbound/vless.go:29-33 · pinned at v1.19.27 (5184081)

Examples

Outbound — plain VLESS over WebSocket with TLS:

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

Outbound — REALITY + XTLS Vision:

yaml
proxies:
  - name: vless-reality
    type: vless
    server: example.com
    port: 443
    uuid: a3482e88-686a-4a58-8126-99c9df64b7bf
    flow: xtls-rprx-vision
    tls: true
    udp: true
    xudp: true
    servername: www.cloudflare.com
    client-fingerprint: chrome
    reality-opts:
      public-key: <reality public key>
      short-id: <short id>

Inbound under listeners:

yaml
listeners:
  - name: vless-in
    type: vless
    listen: 0.0.0.0
    port: 443
    users:
      - username: alice
        uuid: a3482e88-686a-4a58-8126-99c9df64b7bf
        flow: xtls-rprx-vision
    certificate: /etc/mihomo/server.crt
    private-key: /etc/mihomo/server.key
    reality-config:
      enable: true
      dest: www.cloudflare.com:443
      short-id: ['', <short id>]

Notes

  • mihomo accepts two UDP-encoding switches on the outbound: the legacy booleans udp, packet-addr, xudp, and the modern selector packet-encoding: xudp|packetaddr. When the selector is set, the booleans are ignored.
  • mihomo's client-fingerprint is mihomo-specific: a per-proxy uTLS fingerprint override. The same value can be set globally via global-client-fingerprint.
  • The inbound's mux-option is sing-style mux compatible with sing-box multiplex clients; not the same wire format as Xray's mux.
  • reality-config on the inbound takes a REALITY server-side bundle (private key, dest target, short-id list). The matching outbound on the other end uses reality-opts with the public-key half.

Cross-core notes

  • Xray keeps inbound users in clients[] with id (UUID), supports a richer fallbacks chain, and gates encryption with decryption / encryption fields that must be set. See VLESS — Xray-core.
  • sing-box keeps inbound users in users[] with uuid, and uses embedded tls/transport/multiplex blocks shared by every inbound type. See VLESS — sing-box.
  • mihomo bundles transport, TLS, REALITY, ECH, and UDP-encoding selection into the proxy object itself — there is no separate streamSettings / tls/transport block.

Source: adapter/outbound/vless.go:50-79 · v1.19.27 (5184081)

Core Tutorial by Argsment