Skip to content

Compare — choosing a core

The three cores cover overlapping feature sets but with very different design philosophies. This page summarizes the differences in a single place so you can pick the right tool and migrate between them.

Feature support at a glance

FeatureXray-coresing-boxmihomo
Config formatJSONJSONYAML
VLESS
VMess✓ (AEAD only)
Trojan✓ (no flow)
Shadowsocks (incl. 2022)
ShadowsocksR
Hysteria2✓ (split config)
TUIC✓ (v5)✓ (v4 + v5)
WireGuardoutboundendpointoutbound
Naive
AnyTLS
SSH
Tor
HTTP / SOCKS✓ (incl. mixed)✓ (incl. mixed)
Dokodemo / port-forwarddedicatedvia Directdedicated
TUN inboundminimalfullfull
Redirect / TProxydokodemo + sockoptdedicatedshortcut + listener
TLS / uTLS / REALITY / ECH
RoutingJSON rules + balancerstructured rules + actionscompact strings
DNSserver URL listtyped serversURL list + policy map
Rule providers— (built-in geo only)rule-setrule-providers
Proxy groupsbalancer (4 strategies)selector / urltestselect / url-test / fallback / load-balance
Stats / PrometheusgRPC + metricsclash_api + v2ray_apiClash API

Field-name divergences (the same feature, three names)

VLESS / VMess user list

ConceptXraysing-boxmihomo
User UUID fieldclients[].idusers[].uuiduuid
User name fieldclients[].emailusers[].nameusername
Per-user flowclients[].flowusers[].flowflow

Shadowsocks cipher

  • Xray / sing-box: method
  • mihomo: cipher

Server / port pair

  • Xray inbounds: listen + port
  • Xray outbounds: address + port (simplified) or servers[].address + servers[].port
  • sing-box inbounds: listen + listen_port
  • sing-box outbounds: server + server_port
  • mihomo: listen + port (inbound listener) / server + port (outbound)

Skip cert verify

  • Xray: tlsSettings.allowInsecure
  • sing-box: tls.insecure
  • mihomo: per-adapter skip-cert-verify

uTLS fingerprint

  • Xray: tlsSettings.fingerprint
  • sing-box: tls.utls: { enabled, fingerprint }
  • mihomo: per-adapter client-fingerprint (or top-level global-client-fingerprint)

Multiplex (mux)

  • Xray: streamSettings.sockopt (limited)
  • sing-box: multiplex: { ... } on inbound/outbound
  • mihomo: mux-option on inbound listener (sing-style mux)

Migration cookbook

From Xray VLESS to sing-box VLESS

Xray:

json
{
  "outbounds": [{
    "protocol": "vless",
    "settings": {
      "vnext": [{
        "address": "example.com",
        "port": 443,
        "users": [{ "id": "abc...", "flow": "xtls-rprx-vision" }]
      }]
    },
    "streamSettings": {
      "security": "reality",
      "realitySettings": { "publicKey": "...", "shortId": "...", "serverName": "cdn.com" }
    }
  }]
}

sing-box equivalent:

json
{
  "outbounds": [{
    "type": "vless",
    "server": "example.com",
    "server_port": 443,
    "uuid": "abc...",
    "flow": "xtls-rprx-vision",
    "tls": {
      "enabled": true,
      "server_name": "cdn.com",
      "utls": { "enabled": true, "fingerprint": "chrome" },
      "reality": { "enabled": true, "public_key": "...", "short_id": "..." }
    }
  }]
}

Key differences:

  • clients[].idusers[].uuid on inbound; outbound uses flat uuid.
  • streamSettings.realitySettingstls.reality sub-block.
  • streamSettings.security: "reality"tls.enabled: true plus tls.reality.enabled: true.
  • Xray's implicit chrome fingerprint becomes explicit tls.utls: { enabled, fingerprint }.

From sing-box to mihomo (same VLESS)

yaml
proxies:
  - name: vless-reality
    type: vless
    server: example.com
    port: 443
    uuid: abc...
    flow: xtls-rprx-vision
    tls: true
    servername: cdn.com
    client-fingerprint: chrome
    reality-opts:
      public-key: ...
      short-id: ...

Key differences:

  • All TLS fields move to the proxy root (tls, servername, client-fingerprint). No nested tls: block.
  • reality: becomes reality-opts:.

From Hysteria2 (Xray's split form) to sing-box

Xray splits the config; sing-box keeps everything in one block:

yaml
# Xray (two blocks)
outbounds:
  - protocol: hysteria
    settings: { version: 2, address: example.com, port: 443 }
    streamSettings:
      hysteriaSettings: { version: 2, auth: pw, up: 100mbps, down: 300mbps }
json
// sing-box (one block, integer Mbps)
{
  "type": "hysteria2",
  "server": "example.com",
  "server_port": 443,
  "password": "pw",
  "up_mbps": 100,
  "down_mbps": 300,
  "tls": { "enabled": true }
}

Routing rules

Xray (JSON):

json
{ "type": "field", "domain": ["geosite:cn"], "outboundTag": "direct" }

sing-box (JSON):

json
{ "rule_set": ["geosite-cn"], "outbound": "direct" }

mihomo (string):

GEOSITE,cn,DIRECT

Last updated:

Core Tutorial by Argsment