Skip to content

Outbounds ​

outbounds is the array of upstream targets. Each entry is one OutboundDetourConfig: a protocol name, a protocol-specific settings object, and optional transport (streamSettings) and multiplexing (mux) blocks. The first entry in the array is the default outbound — traffic that matches no routing rule goes there.

Options ​

FieldTypeDefaultAllowed valuesDescription
protocolstring—freedom | direct | blackhole | block | loopback | http | socks | shadowsocks | vless | vmess | trojan | hysteria | dns | wireguardWhich outbound handler to dial with. Lowercased before the registry lookup. direct is an alias for freedom, block for blackhole.
sendThrough*string0.0.0.0—Local source address to dial from. Accepts an IP, a CIDR (a random address inside it is used per connection), or the special domains origin / srcip.
tagstring——Unique name for this outbound. Referenced by routing rules, balancers, dialerProxy chains and stats counters.
settings*json.RawMessage——Protocol-specific settings object, decoded by the handler selected by protocol. See the per-protocol pages for each shape.
streamSettings*StreamConfig——Transport and security for outgoing connections (raw / ws / grpc / xhttp…, tls / reality). See the Transport and TLS pages.
proxySettings*json.RawMessage(unsupported)(use sockopt.dialerProxy)Not supported — setting it fails at startup with a pointer to streamSettings.sockopt.dialerProxy, which is how outbounds are chained.
mux*MuxConfig——Mux multiplexing over the underlying connection. Fields below.
targetStrategystringAsIsAsIs | UseIP | UseIPv4 | UseIPv6 | UseIPv4v6 | UseIPv6v4 | ForceIP | ForceIPv4 | ForceIPv6 | ForceIPv4v6 | ForceIPv6v4How to resolve the target domain before dialing (matched case-insensitively). Use* prefers the given families with fallback, Force* refuses to fall back. An unknown value is a startup error. On a freedom outbound a non-AsIs value is moved to streamSettings.sockopt.domainStrategy at startup (a warning is logged; behaviour is unchanged).

Source: infra/conf/xray.go:214-223 · pinned at v26.9.9 (52a412d)

Chaining ​

Outbound chaining is configured on the transport: set streamSettings.sockopt.dialerProxy to the tag of another outbound and this outbound's connections are dialed through it. There is no proxySettings object — a config that sets one fails at startup with a message pointing to dialerProxy.

Multiplexing (mux) ​

FieldTypeDefaultAllowed valuesDescription
enabledboolfalsetrue | falseTurn Mux on for TCP traffic through this outbound.
concurrencyint16——Maximum concurrent streams per physical connection. A negative value disables Mux entirely, including the XUDP path.
xudpConcurrencyint16——Separate concurrency for XUDP (UDP-over-Mux) connections.
xudpProxyUDP443stringrejectreject | allow | skipWhat to do with proxied UDP/443 (QUIC) traffic inside XUDP: reject it, allow it, or skip Mux for it.

Source: infra/conf/xray.go:103-108 · pinned at v26.9.9 (52a412d)

Minimal example ​

json
{
  "outbounds": [
    {
      "tag": "proxy",
      "protocol": "vless",
      "settings": {
        "vnext": [
          {
            "address": "example.com",
            "port": 443,
            "users": [{ "id": "uuid", "encryption": "none" }]
          }
        ]
      },
      "streamSettings": { "security": "tls" }
    },
    { "tag": "direct", "protocol": "freedom", "settings": {} },
    { "tag": "block", "protocol": "blackhole", "settings": {} }
  ]
}

Notes ​

  • Ordering matters: routing sends unmatched traffic to the first outbound. Keep the proxy or freedom entry you want as the default at index 0.
  • A proxySettings.tag value corresponds to streamSettings.sockopt.dialerProxy. There is no counterpart to transportLayer, since dialerProxy always chains at the transport layer.
  • sendThrough with a CIDR picks a random source address inside the range for every connection — useful with a routed IPv6 prefix.
  • The dns protocol is a special outbound that intercepts DNS queries; see DNS.

Cross-core notes ​

  • sing-box models the same concept as a flat object per entry (type + tag + fields at one level) and has no implicit "first is default" rule — the default is route.final. See sing-box Outbounds.
  • mihomo calls these proxies and always dispatches through proxy groups or rules rather than an ordered default.

Source: infra/conf/xray.go:214-223 · v26.9.9 (52a412d)

Core Tutorial by Argsment