Skip to content

Trojan — mihomo

mihomo speaks Trojan on both sides. The outbound supports tcp, ws, and grpc transports with TLS, REALITY, and ECH wrappers, plus the trojan-go compatible ss-opts layer that adds an inner Shadowsocks cipher on top of the Trojan password handshake.

Outbound

Entry under proxies: with type: trojan. Embeds BasicOption (common outbound fields).

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>Trojan password.
alpn[]string[]h2 | http/1.1ALPN list offered during TLS handshake.
snistring(server name)<SNI>TLS Server Name Indication. Defaults to `server`.
skip-cert-verifyboolfalsetrue | falseDisable TLS verification (test only).
fingerprintstring(unset)<SHA256 hex>Pin the server's TLS certificate to this fingerprint.
certificatestring(unset)<PEM file path>Client certificate (mTLS).
private-keystring(unset)<key file path>Private key matching `certificate`.
udpboolfalsetrue | falseAllow UDP packets to be relayed through this outbound.
networkstringtcptcp | ws | grpcUnderlying transport.
ech-optsECHOptions(disabled)ECHOptionsEncrypted Client Hello configuration.
reality-optsRealityOptions(disabled)RealityOptionsREALITY client configuration.
grpc-optsGrpcOptions(unset)GrpcOptionsSettings for `network: grpc`.
ws-optsWSOptions(unset)WSOptionsSettings for `network: ws`.
ss-optsTrojanSSOption(disabled)TrojanSSOptionOptional Shadowsocks-over-Trojan layer (trojan-go style).
client-fingerprintstring(global)chrome | firefox | safari | ios | edge | random | randomizeduTLS client-hello fingerprint.

Source: adapter/outbound/trojan.go:38-58 · pinned at v1.19.27 (5184081)

ss-opts

FieldTypeDefaultAllowed valuesDescription
enabledboolfalsetrue | falseWrap the Trojan stream in an additional Shadowsocks layer.
methodstring(unset)aes-128-gcm | aes-256-gcm | chacha20-ietf-poly1305Shadowsocks AEAD cipher used for the inner layer.
passwordstring(unset)<string>Password for the inner Shadowsocks layer (separate from the outer Trojan password).

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

Inbound

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

FieldTypeDefaultAllowed valuesDescription
users[]TrojanUser(required)[TrojanUser]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.
allow-insecureboolfalsetrue | falseSkip TLS client-certificate verification on the listener (testing only).
reality-configRealityConfig(disabled)RealityConfigREALITY server configuration.
mux-optionMuxOption(disabled)MuxOptionMultiplex settings (sing-style mux).
ss-optionTrojanSSOption(disabled)TrojanSSOptionShadowsocks-over-Trojan compat layer (must match outbound `ss-opts`).

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

users[]

FieldTypeDefaultAllowed valuesDescription
usernamestring(unset)<string>Display name.
passwordstring(required)<string>Trojan password.

Source: listener/inbound/trojan.go:28-31 · pinned at v1.19.27 (5184081)

Examples

Outbound — plain Trojan with TLS:

yaml
proxies:
  - name: trojan-srv
    type: trojan
    server: example.com
    port: 443
    password: <password>
    sni: example.com
    udp: true
    alpn: [h2, http/1.1]

Outbound — Trojan over WebSocket with trojan-go ss-opts:

yaml
proxies:
  - name: trojan-go
    type: trojan
    server: example.com
    port: 443
    password: <outer-password>
    udp: true
    network: ws
    sni: example.com
    ws-opts:
      path: /tj
    ss-opts:
      enabled: true
      method: aes-128-gcm
      password: <inner-password>

Inbound under listeners:

yaml
listeners:
  - name: trojan-in
    type: trojan
    listen: 0.0.0.0
    port: 443
    users:
      - username: alice
        password: <password>
    certificate: /etc/mihomo/server.crt
    private-key: /etc/mihomo/server.key

Notes

  • ss-opts implements the trojan-go pattern of stacking Shadowsocks AEAD inside the Trojan stream. The outer Trojan password authenticates the handshake; the inner Shadowsocks key encrypts the payload. The inbound's ss-option block must match the outbound's ss-opts exactly (enabled, method, password) or the inbound rejects the client.
  • mihomo has no equivalent of Xray's fallbacks[] or sing-box's fallback_for_alpn. For HTTP fallback behavior, terminate TLS in front of mihomo with a separate reverse proxy.
  • The outbound's client-fingerprint is a per-proxy uTLS override. The global default is global-client-fingerprint.

Cross-core notes

  • Xray uses clients[] for inbound users, supports a list-form fallbacks[] chain, and rejects any non-empty flow value. See Trojan — Xray-core.
  • sing-box uses users[] (name/password), and replaces the fallback list with a single default fallback plus a per-ALPN fallback_for_alpn map. See Trojan — sing-box.

Source: adapter/outbound/trojan.go:38-65 · v1.19.27 (5184081)

Core Tutorial by Argsment