feat(frontend): warn about catch-all routing rules - #230
Merged
Conversation
A rule with no domain, ip or protocol whose port range spans every port matches all traffic, so sing-box stops there: the rules below it and the resolve step the generator appends for IPIfNonMatch never run.
Marks the catch-all rule and the rules it makes unreachable, so a terminal rule stops silently swallowing the rest of the chain.
…back A catch-all routed to the proxy with nothing enabled below it shadows only the automatic tail, which already ends in the same proxy fallback. Saying it matches everything is true but unhelpful there — the rule buys nothing and costs the automatic IP check, so name that instead.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
A routing rule with no domain, ip or protocol whose port range spans every port matches all traffic. sing-box stops at it, so everything below is dead — including the
action: resolvestep plus the repeated IP checks that the generator appends after the user rules whendomainStrategyisIPIfNonMatch(crates/kasumi-core/src/singbox_config.rs:1116-1119).A rule like
port 0-65535 → proxyis easy to add as a "default" and looks harmless, but it silently disables the resolve-then-geoip fallback: a domain that no geosite rule matched is no longer resolved and re-checked againstgeoip-ru, so a host on a Russian address goes through the proxy instead of direct. The rule is also redundant —route.finalalready sends the remainder to the same outbound, but after the resolve step.The routing list now marks such a rule and greys out the rules it makes unreachable.
When the catch-all is the last enabled rule and routes to the proxy, it shadows nothing but the automatic tail, which already ends in the same fallback. Telling the user it matches every connection is true but unhelpful there, so that case gets its own line: the rule buys nothing and costs the automatic IP check.
Affected layer
frontend/— React Web UIcrates/·src-tauri/— Rust core / backend / Tauri desktopmodule/— Android installable zip (thin launcher over the Rust daemon)scripts/— build / release helpers.github/Verification
Web UI (
frontend/):bun run check— Biome lint + format clean (106 files)bun run test— vitest green (9 files, 82 tests; 7 new cases forisCatchAllRule, 5 forisRedundantCatchAll)bun run build—tsc -b+ vite build succeedbun run check:i18n— 8 locales, 655 keys in sync, no stale keysNo Rust or module code touched, so those gates are not applicable.
Checklist
frontend/src/generated/was regenerated from Rust, not hand-edited — untouched heresettings.routingCatchAll,settings.routingUnreachableandsettings.routingCatchAllRedundantadded toen.tsand all 7 other localesNotes for reviewers
The detector deliberately mirrors what the generator emits rather than guessing:
build_structured_singbox_rules(singbox_config.rs:938) only emits a port/network/protocol-only rule when neither the domain nor the ip half produced a match field, which is exactly the catch-all shape.tcporudpalone) is not flagged — it leaves the other half of the chain reachable.#,ext:…) also degrades to a port-only rule in the generator. That false negative is left alone: flagging it would mean re-implementingparse_singbox_domainin the UI.