6.7 KiB
Native Routing Contract
Ownership map
| Layer | Paths | Authority |
|---|---|---|
| Shipped templates | data/templates/sing-box/*.json, data/templates/xray/*.json |
Versioned defaults and reset/import sources |
| Active raw configs | data/configs/sing-box/*.json, data/configs/xray/*.json |
Runtime routing and DNS source of truth |
| Runtime copies | data/runtime/*.json or manager-owned temporary files |
Launch artifacts; do not author product policy here |
| Legacy GUI routing | RoutingSettings, presets, engines/xray/config_builder.py |
Separate tun2socks/legacy path, not raw sing-box/Xray modes |
application/profile_service.py copies a selected or imported template into the corresponding active config. Reset performs the same copy. Saving in the raw editor writes the active config.
The self-updater preserves the installed data/ directory. To deliver template updates through that boundary, build.py generates assets/template-update from the versioned data/templates tree. Before the UI starts, template_sync.py compares each same-path active config with the previously installed template, refreshes the active config only when their parsed JSON is equivalent, and then installs the new shipped template. User-edited routing and other fields remain unchanged. The top-level dns section is explicitly app-maintained and always follows the engine default native template, on startup and before use. This is persisted in the active raw JSON, not injected into runtime copies. The generated asset is transport, not a second authoring source.
Mode map
| Mode | Routing owner | App-owned runtime work |
|---|---|---|
| System proxy to sing-box | Active sing-box JSON | Replace source proxy/TUN inbounds with public SOCKS/HTTP inbounds; allocate ports |
| sing-box TUN | Active sing-box JSON | Remove proxy inbounds; assign fresh TUN interface name |
| System/manual proxy to Xray | Active Xray JSON | Allocate proxy/API ports and add metrics contract |
| Xray TUN | Active Xray JSON | Add/keep TUN inbound, strip proxy inbounds, bind outbounds to the physical interface when required |
| sing-box hybrid Xray sidecar | Active sing-box JSON at the front | Route only the proxy outbound through the generated sidecar; preserve sing-box direct decisions |
| tun2socks fallback | GUI RoutingSettings and generated Xray config |
Outside raw JSON ownership |
Native sing-box rules
Use route.rules and upstream field names such as:
process_name,process_path,process_path_regex;domain,domain_suffix,domain_keyword,domain_regex;ip_cidr,ip_is_private;rule_set,protocol,inbound;actionandoutbound.
Prefer the current explicit route action:
{
"process_name": [
"Example.exe",
"example-helper.exe"
],
"action": "route",
"outbound": "direct"
}
Do not put Xray values such as domain:example.com, full:example.com, geosite:*, or geoip:* into a sing-box native rule. Use sing-box fields or native rule_set entries.
Keep this normal priority shape:
- non-final
{"action": "sniff"}; - DNS handling such as
{"protocol": "dns", "action": "hijack-dns"}; - narrow protected/direct process rules;
- LAN and other narrow rules;
- broader process/domain/rule-set rules;
route.finalfor unmatched traffic.
Rules are evaluated in order. A final route action stops ordinary matching. Put a forced direct process rule before any broader proxy rule that can match the same traffic.
The runtime may insert narrowly scoped endpoint, metrics, or hybrid-protection rules ahead of source-authored policy. Those rules match app-owned inbounds or the selected proxy endpoint and must not become a second product-policy layer.
Ensure the referenced tag exists, normally:
{
"type": "direct",
"tag": "direct",
"domain_resolver": "bootstrap-dns"
}
Native Xray rules
Use routing.rules with Xray field-rule keys such as:
type: "field";process;domainwith Xray-native items such asdomain:,full:,regexp:, orgeosite:when supported by the bundled data/core;ipwith CIDR,geoip:, or other Xray-native values;network,inboundTag,port;outboundTag.
Example process rule:
{
"type": "field",
"process": [
"Example.exe",
"example-helper.exe"
],
"network": "tcp,udp",
"outboundTag": "direct"
}
Put project policy rules at the beginning of the template's routing.rules, before broad proxy rules. The runtime metrics rule may be inserted ahead of them for a dedicated metrics inbound; it does not match normal application traffic.
Ensure the referenced direct outbound exists, normally:
{
"tag": "direct",
"protocol": "freedom",
"settings": {}
}
Reserved routing tags
- Keep
proxyas the selected-node placeholder when the template expects the application to replace it. - Keep
directfor native direct egress. - Keep
blockfor the engine's native block/blackhole outbound. - Do not rename app-owned tags beginning with
__app_without tracing every runtime consumer.
Files to trace before architecture changes
xray_fluent/application/profile_service.py: template, active-config, reset, and save ownership.xray_fluent/application/template_sync.py: updater-safe delivery of shipped templates and preservation of user-edited active JSON.xray_fluent/engines/singbox/runtime_planner.py: proxy/TUN inbound contracts, selected outbound, bootstrap rule, and hybrid sidecar.xray_fluent/application/xray_runtime_service.py: raw Xray metrics, TUN, selected outbound, and loop-prevention contracts.xray_fluent/ui/configs_page.pyandui/dashboard_page.py: user-facing mode semantics.docs/sing-box/runtime-config.md: current raw-config model and route-order explanation.docs/sing-box/reference/route-rules.md: local upstream-aligned sing-box field reference.docs/template-editor-v1.mdanddocs/sing-box/template-format-v1.md: design context only; do not treat placeholders as implemented runtime behavior without source proof.tests/test_yandex_music_direct_templates.py: concrete cross-core example that checks native process rules and first-match priority in every shipped template.
Verification checklist
- Parse every changed JSON file.
- Assert exact process/domain values, native action fields, and rule priority in a focused unit test.
- Run
sing-box checkfor changed sing-box templates. - Run
xray run -testfor changed Xray templates. - Run the relevant Python suite and
git diff --check. - Test both automatic synchronization of untouched active configs and preservation of user-edited active configs.
- Do not claim build or installed-runtime verification unless each was actually performed.