Skip to content

Routing — sing-box ​

sing-box's route block holds rules, rule-sets, and a handful of default-interface / process-lookup toggles. Rules are polymorphic (default + logical) and carry an explicit action selecting one of eight behaviors.

Top-level options ​

FieldTypeDefaultAllowed valuesDescription
geoip*GeoIPOptions(ignored)GeoIPOptionsGeoIP database is not supported: the block is parsed but ignored; use rule-sets.
geosite*GeositeOptions(ignored)GeositeOptionsGeoSite database is not supported: the block is parsed but ignored; use rule-sets.
rules[]Rule[][Rule]Routing rules, evaluated in order.
rule_set[]RuleSet[][RuleSet]Named rule-sets — referenced from rules via rule_set match keys. Three types: inline, local, remote.
finalstring(unset)<outbound tag>Default outbound when no rule matches. When unset, the first outbound in outbounds is used.
find_processboolfalsetrue | falseLook up the originating process for every connection. Required by process_name / process_path rules.
find_neighborboolfalsetrue | falseLinux / macOS. Force neighbor resolution (MAC address / hostname of LAN clients) for logging even when no source_mac_address / source_hostname rule exists.
dhcp_lease_filesbadoption.Listable[string](auto-detected)[<file path>]Linux / macOS. DHCP lease files used to map LAN clients to hostnames and MAC addresses. Auto-detected for dnsmasq, odhcpd, ISC dhcpd and Kea when empty.
auto_detect_interfaceboolfalsetrue | falseAuto-discover the system's default outbound interface — used by Direct outbounds without bind_interface.
override_android_vpnboolfalsetrue | falseAndroid only — bypass the system VPN service for outbound dials.
default_interfacestring(auto)<interface>Override the default outbound interface. Overrides auto_detect_interface.
default_markFwMark0<uint32>Linux SO_MARK applied to outbound sockets.
default_domain_resolver*DomainResolveOptions(none)DomainResolveOptionsDefault resolver for destination domains when no rule specifies one.
default_network_strategy*NetworkStrategy(unset)NetworkStrategyDefault network-strategy used by Happy-Eyeballs / cellular-vs-wifi dial races.
default_network_typebadoption.Listable[InterfaceType][]<InterfaceType>Preferred network types for the default outbound.
default_fallback_network_typebadoption.Listable[InterfaceType][]<InterfaceType>Fallback network types when the preferred one fails.
default_fallback_delaybadoption.Duration0<duration>Delay before switching to a fallback network.
default_http_clientstring(first http_clients entry)<http client tag>Tag of the top-level http_clients entry used by remote rule-sets that set no http_client. When no http_clients exist at all, a deprecated implicit client dialing through the default outbound is used.

Source: option/route.go:5-24 · pinned at v1.14.2 (af6e64c)

Rules ​

Each entry in rules[] is a polymorphic Rule object. The type field decides the shape:

  • type: "default" (or omitted) — flat RawDefaultRule with match fields + a RuleAction.
  • type: "logical" — boolean combinator over nested rules.

Default rule — match fields ​

RawDefaultRule has 44 fields, all optional and AND-combined when multiple are set. The most-used:

FieldTypeDescription
inbound[]stringMatch by inbound tag.
network[]stringtcp, udp, or tcp,udp.
protocol[]stringSniffed application protocol.
domain / domain_suffix / domain_keyword / domain_regex[]stringDomain matchers.
geosite / geoip / source_geoip[]stringNot supported — a rule using them fails at startup. Use rule_set instead.
ip_cidr / source_ip_cidr[]stringCIDR match.
ip_is_private / source_ip_is_privateboolMatch RFC1918 / link-local / loopback.
port / source_port[]uint16Discrete-port match.
port_range / source_port_range[]stringPort-range match (80:90, 1024:, …).
process_name / process_path / process_path_regex[]stringProcess match (needs find_process: true).
package_name[]stringAndroid package name (UID resolved via the system API). package_name_regex matches by regular expression.
source_mac_address / source_hostname[]stringSource device MAC address / DHCP hostname, via neighbor resolution (Linux, macOS, or the Android / macOS graphical clients).
user / user_id[]string / []int32Local user / UID.
clash_modestringMatch only when the runtime mode (controlled via the Clash API) matches this string.
wifi_ssid / wifi_bssid[]stringWifi-aware routing (mobile-only).
network_is_expensive / network_is_constrainedbooliOS/macOS network-type flags.
rule_set[]stringMatch if any of the named rule-sets matches.
invertboolInvert the entire rule's match result.

Logical rule ​

json
{
  "type": "logical",
  "mode": "and",
  "rules": [ <Rule>, <Rule>, … ],
  "invert": false,
  "action": "..."
}

mode is and (default) or or. Nested rules can themselves be logical.

Rule action ​

Every rule carries an action that decides what happens on match. Eight action values:

ActionMeaning
route (default)Send to outbound. Extra fields: override_address, override_port, network_strategy, udp_*, tls_fragment*, tls_spoof / tls_spoof_method.
route-optionsApply route options to subsequent matching without leaving the rule chain.
directDirect dial — bypass outbounds entirely (uses default_interface etc.).
bypassSame shape as route, deliberately distinct for logging.
rejectDrop the connection. With method: "drop" or method: "default".
hijack-dnsHijack the connection as if it were DNS, routing to the DNS engine.
sniffRun protocol sniffing on the connection. It also runs in pre-match for UDP connections from L3 inbounds (TUN, WireGuard, Tailscale), on the first packet.
resolveResolve the destination domain via the named DNS server before further rules run. Optional timeout and disable_optimistic_cache.

Rule-sets ​

FieldTypeDefaultAllowed valuesDescription
typestringinlineinline | local | remoteWhere the rule set lives. inline holds the rules right in this config; local reads from a file path; remote downloads from a URL.
tagbadoption.Listable[string](required)<string> | [<string>]Reference name used by rules' rule_set match key. A list defines several rule-sets sharing the other options; {tag} in path, url or initial_path is replaced by each tag (required with multiple tags; not allowed with type: inline).
formatstring(inferred)source | binaryFile format. source is JSON; binary is the compiled .srs format. Inferred from the file extension when unset.

Source: option/rule_set.go:22-29 · pinned at v1.14.2 (af6e64c)

Local rule-set ​

json
{ "type": "local", "tag": "cn", "format": "binary", "path": "geosite-cn.srs" }

Remote rule-set ​

json
{
  "type": "remote",
  "tag": "cn",
  "format": "binary",
  "url": "https://example.com/geosite-cn.srs",
  "http_client": { "detour": "direct" },
  "update_interval": "168h"
}

Inline rule-set ​

json
{
  "type": "inline",
  "tag": "block",
  "rules": [
    { "domain_keyword": ["ads", "tracker"] }
  ]
}

The inline form's rules are HeadlessRule — structurally identical to routing rules but without the action field (the action is whatever the referencing rule does).

Examples ​

CN-direct + everything else through proxy:

json
{
  "route": {
    "rule_set": [
      { "type": "remote", "tag": "geoip-cn", "format": "binary",
        "url": "https://github.com/SagerNet/sing-geoip/raw/rule-set/geoip-cn.srs" },
      { "type": "remote", "tag": "geosite-cn", "format": "binary",
        "url": "https://github.com/SagerNet/sing-geosite/raw/rule-set/geosite-cn.srs" }
    ],
    "rules": [
      { "ip_is_private": true, "outbound": "direct" },
      { "rule_set": ["geoip-cn", "geosite-cn"], "outbound": "direct" },
      { "action": "sniff" },
      { "protocol": "dns", "action": "hijack-dns" }
    ],
    "final": "proxy",
    "find_process": false,
    "auto_detect_interface": true
  }
}

Reject ads with an inline rule-set:

json
{
  "route": {
    "rule_set": [
      {
        "type": "inline",
        "tag": "ads",
        "rules": [
          { "domain_keyword": ["doubleclick", "googlesyndication"] }
        ]
      }
    ],
    "rules": [
      { "rule_set": "ads", "action": "reject" }
    ]
  }
}

Logical OR rule:

json
{
  "type": "logical",
  "mode": "or",
  "rules": [
    { "domain_suffix": [".onion"] },
    { "rule_set": ["tor-exit"] }
  ],
  "outbound": "tor"
}

Notes ​

  • geoip / geosite are not supported: the top-level blocks are parsed but ignored, and geoip / geosite / source_geoip rule items make the rule fail at startup. Load equivalent data via rule_set (remote .srs files) and reference it through the rule's rule_set match field.
  • Remote rule-sets download through an HTTP client: http_client takes an inline object (engine, TLS and dial fields such as detour) or the tag of a top-level http_clients entry; without it, route.default_http_client or the first http_clients entry is used. download_detour is deprecated in favour of http_client. initial_path seeds the rule-set from a local file so startup isn't blocked by the first download.
  • Rule-set matching: a referenced rule-set's fields are merged into the referencing rule only when it holds exactly one default rule without invert; any other rule-set is evaluated as a standalone condition that matches when any one of its rules matches.
  • source_mac_address / source_hostname rely on neighbor resolution, which turns on automatically when such rules (or a local DNS server's neighbor_domain) exist; find_neighbor forces it for logging, and dhcp_lease_files supplies hostnames on Linux / macOS.
  • rule_set_ip_cidr_match_source (snake_case in the struct) controls whether a rule-set's IP-CIDR rules match source or destination. The alias rule_set_ipcidr_match_source is deprecated.
  • The sniff and resolve rule actions are typically used at the head of the rule list to ensure later rules see useful metadata. The DNS engine relies on hijack-dns to capture DNS queries the routing engine wants to handle.
  • clash_mode only takes effect if the Clash API is enabled — that's where the mode comes from.

Cross-core notes ​

  • Xray-core uses a single polymorphic rule shape with camelCase field names and a much smaller match-key set. There is no action enum — every rule routes to an outboundTag or balancerTag. See Routing — Xray-core.
  • mihomo uses compact one-line string rules (DOMAIN-SUFFIX,example.com,proxy) and a separate rule-providers: mechanism for remote rule lists. See Routing — mihomo.

Source: option/route.go:5-24 · v1.14.2 (af6e64c)

Core Tutorial by Argsment