Shadowrocket checks rules from top to bottom; the first match determines where a request goes, and FINAL handles requests with no earlier match. This guide is for iPhone and iPad users with their own provider and configuration who are ready to edit Config. Mac, Windows, Android, and Linux users can also apply the matching principles, but editing steps vary by platform. By the end, you’ll be able to distinguish six rule types, write rules with exceptions and a fallback, and verify results using a new connection.
1. Rule Structure and the Global Routing Prerequisite
Rules are neither connection settings nor a list that identifies traffic by app name. They use information available for each request, such as its domain or destination IP, to select a policy. To apply rules in a configuration file, select Config under Home → Global Routing on iPhone or iPad. Editing the Config file while Proxy or Direct is selected won’t verify rules as described here.
[Rule]
DOMAIN,example.com,DIRECT
DOMAIN-SUFFIX,example.org,PROXY
FINAL,DIRECT
Most conditional rules have three parts: type, match value, and policy, separated by commas. FINAL has no match value, so it uses two parts. DIRECT means connect directly; PROXY sends the request through the proxy route. Neither field is where you enter the address or password for your existing server. If you reference a custom policy name in the configuration, it must match the defined name exactly.
Bottom line: choose the default route first, then add exceptions
Decide whether unmatched requests should use DIRECT or PROXY. Put the corresponding FINAL rule last, then add clearly scoped exceptions above it. Don’t use a long list of keyword rules in place of an explicit default policy.
- Config: Uses rules in the currently selected configuration to choose where requests go. This is the mode required for the steps in this guide.
- Proxy: Applies a global proxy mode; it does not verify whether a specific DIRECT rule works.
- Direct: Applies a global direct mode; it does not verify whether a specific PROXY rule matches.
- Scene: Switches modes based on configured scene conditions. When troubleshooting, also check which configuration and policy the active scene uses.
2. DOMAIN, DOMAIN-SUFFIX, and DOMAIN-KEYWORD
These three domain rules differ in what they consider a match. DOMAIN requires an exact domain match. DOMAIN-SUFFIX matches the specified domain and its subdomains. DOMAIN-KEYWORD checks whether a domain contains a specified string. None of them matches URL paths, so adding /video/ won’t distinguish pages on the same domain.
| Rule | Matches | Doesn’t match |
|---|---|---|
DOMAIN,example.com,DIRECT |
example.com |
www.example.com |
DOMAIN-SUFFIX,example.com,PROXY |
example.com、cdn.example.com |
notexample.com、example.com.other.test |
DOMAIN-KEYWORD,example,PROXY |
example.com、notexample.net |
sample.test |
For example, to proxy all of example.com while connecting its login host directly, put the exact-domain exception first, followed by the suffix rule. DOMAIN-SUFFIX doesn’t need to be written as *.example.com; the asterisk isn’t required to specify subdomains here.
[Rule]
DOMAIN,login.example.com,DIRECT
DOMAIN-SUFFIX,example.com,PROXY
FINAL,DIRECT
In this configuration, login.example.com matches the first line and is not checked against the second. img.example.com doesn’t match the first line, but does match the second. If you swap the lines, the suffix rule takes the request first, leaving the exact-domain exception ineffective. “More specific rules first” is an order chosen by the editor, not automatic sorting by the system.
3. GEOIP and IP-CIDR: Matching by Destination Address
GEOIP matches the destination IP against the data in the configured geolocation database. GEOIP,CN,DIRECT sends destination IPs classified as CN by that database through DIRECT. It doesn’t use the device’s location or the domain suffix. A domain served from multiple locations may resolve to different IPs in different regions, which can change the rule outcome.
[Rule]
IP-CIDR,192.168.0.0/16,DIRECT,no-resolve
IP-CIDR,10.0.0.0/8,DIRECT,no-resolve
GEOIP,CN,DIRECT
FINAL,PROXY
IP-CIDR matches an address range. 192.168.0.0/16 covers 192.168.0.0 through 192.168.255.255; 10.0.0.0/8 covers 10.0.0.0 through 10.255.255.255. These examples show only some private IPv4 ranges; they aren’t a complete set of local network rules.
| Condition | Information required | What to check |
|---|---|---|
GEOIP,CN,DIRECT | Destination IP and geolocation database entry | A database entry isn’t proof of the current physical location. |
IP-CIDR,192.168.0.0/16,DIRECT | Destination IPv4 address | Check whether the actual destination falls within the specified prefix. |
no-resolve | Destination IP available when the rule is evaluated | Avoid triggering an extra DNS lookup solely for this IP rule. |
no-resolve doesn’t “block all DNS queries” or mean “always connect directly.” If a request has only a domain and no available IP yet, an IP rule with this option won’t resolve the domain just to check for a match; the request may continue to later rules. For IPv6 address ranges, use the corresponding IP-CIDR6 rule. An IPv6 prefix can’t be matched against the IPv4 examples above.
- To connect a fixed private-network address directly, confirm the actual address first, then use an appropriate IP-CIDR range.
- If a domain must use a specific policy, prefer a domain rule rather than relying on the region of its current IP address.
- If an IP rule doesn’t match, check the destination address, address family, resolution timing, and whether an earlier rule already matched.
4. FINAL Placement and a Complete Rule Example
FINAL is an unconditional fallback and must be the last rule in the list. If it appears earlier, later conditions never get a chance to handle requests already caught by FINAL. Choosing DIRECT or PROXY for FINAL is a choice of default routing policy; there’s no one setting that suits every configuration.
[Rule]
DOMAIN,login.example.com,DIRECT
DOMAIN-SUFFIX,example.com,PROXY
DOMAIN-KEYWORD,example-cdn,PROXY
IP-CIDR,192.168.0.0/16,DIRECT,no-resolve
IP-CIDR,10.0.0.0/8,DIRECT,no-resolve
GEOIP,CN,DIRECT
FINAL,PROXY
This syntax example covers all six rule types discussed here. It doesn’t include server or policy group definitions and isn’t a complete, ready-to-connect configuration. The example domains are for illustration; when testing, use domains whose purpose and actual addresses you know. Whether PROXY can establish a connection still depends on the validity of your existing proxy configuration.
login.example.com: Matches the first rule and uses DIRECT.static.example.com: Matches the second rule and uses PROXY; GEOIP isn’t checked afterward.192.168.1.20: If no earlier domain rule matches, it reaches the private-range rule and uses DIRECT.- Other requests: Later conditions are checked first; if none match, FINAL selects PROXY.
5. Edit and Verify Rules in Config
These steps refer to Home and Config on iPhone and iPad. Save a copy of the existing configuration before editing; don’t replace the entire file with a snippet containing only [Rule]. If the file already has that section, edit it in place rather than adding a duplicate. A remote configuration update may overwrite local changes, so first check whether you’re editing a local copy or an update source.
-
Save a backup
Open Config, find the configuration currently in use, and save a copy of its original contents. Note the file name so you can confirm later that you enabled and edited the same file.
-
Edit the rules
In Config, open the target configuration for editing and find
[Rule]. Add a clearly scoped domain rule and confirm that FINAL is still the last rule in the list. -
Enable the configuration
After saving, confirm the edited configuration is selected in Config. Then go to Home → Global Routing → Config to make sure the app isn’t still in Proxy, Direct, or another scene mode.
-
Create a new request
Disconnect and reconnect, close any existing connection from the test page, then visit the target domain. Check the connection log for the destination, matched rule, and selected policy; don’t rely only on whether the page loads.
-
Check each case
Test an exact domain, a subdomain, and an unmatched domain separately. Change only one condition or rule order per test and note the difference. If something goes wrong, restore the backup and narrow the test scope.
Existing long-lived TCP connections or reused connections may keep using the route they were established with, even after rules are saved. A page may also be served from the browser cache. So a single refresh that appears unchanged doesn’t prove the rules failed to apply; check the log for a new connection.
- Check subscriptions and rules separately: Updating existing Subscribe content under Home usually refreshes server details. It doesn’t mean the rules in the current Config were updated too.
- Check automatic connection and routing separately: Settings → On Demand manages automatic connection conditions; it doesn’t select Config as the routing mode.
- Check protocols and matching separately: Shadowsocks, VMess, VLESS, Trojan, Hysteria2, and WireGuard are different connection protocols. Domain rules don’t automatically convert one protocol to another.
6. Troubleshooting Rule Mismatches and Connection Errors
First distinguish “the wrong rule was selected” from “the correct route was selected, but the connection failed.” A page may request content from several domains, including the main site, images, login, and APIs. A DOMAIN rule for the main site doesn’t guarantee that its resource domains use the same policy. If some content fails to load, start with the actual destination domain in the failed connection rather than broadening the rule to a keyword match.
Error: connection refused
Cause and fix: This low-level connection error means the connection was refused. The destination port may not be listening, or a device along the route may have actively refused the connection. First check the failed connection’s actual address, port, and selected policy. If it correctly matched PROXY, check the connection settings for your existing server rather than changing the DOMAIN rule.
Error: i/o timeout
Cause and fix: This low-level timeout means a network operation didn’t complete in time; it doesn’t by itself indicate a rule syntax error. Check the connection log to see whether the request used DIRECT or PROXY, then investigate DNS, destination reachability, and the selected proxy route. The full log message may vary by protocol and platform.
Use these error messages to troubleshoot only when they appear in the actual connection log; they aren’t specific indicators of a rule mismatch. If the log shows FINAL, none of the earlier rules caught the request. Check whether the actual domain matches, whether the request uses an IP directly, whether IP matching depends on resolution timing, and whether the configuration is enabled.
| What you see | Check first | What to change |
|---|---|---|
| All requests go through the proxy | Is Home → Global Routing set to Proxy? | Switch to Config and test with a new connection. |
| The login domain exception doesn’t take effect | Is DOMAIN-SUFFIX listed before the exception? | Move the exact DOMAIN rule above the suffix rule. |
| Every request shows FINAL | Actual destination, active configuration, FINAL placement | Confirm the right file is selected, remove any earlier FINAL rule, and check the destination details. |
| The domain matches, but the IP rule doesn’t | Resolution result, address family, and no-resolve | Check the actual destination IP; don’t test an IPv6 address as if it were IPv4. |
| Traffic still uses the old route shortly after an edit | Reused connections and page cache | Create a new connection and check its match record. |
To expand your setup, see the rule reference, but start with a short, understandable rule list. For every rule you add, identify what it matches, the expected policy, and why it belongs in that position. This makes troubleshooting easier than adding many rules whose sources are difficult to verify.