Shadowrocket Rules: How DOMAIN-SUFFIX, GEOIP, IP-CIDR, and FINAL Work

Learn what DOMAIN, DOMAIN-SUFFIX, DOMAIN-KEYWORD, GEOIP, IP-CIDR, and FINAL match, how rules are evaluated top to bottom, and how to avoid common syntax mistakes.

At a glance

This guide is for users who have saved their own connection configuration in Shadowrocket and want to check how traffic is routed. First, make sure Home → Global Routing is set to Config. Then distinguish domain rules from IP rules, and use the per-rule match log to diagnose issues. The example.com domain and documentation-only IP ranges are included to explain syntax, not to provide connection services. After reading, you’ll be able to identify rule fields, order rules correctly, and troubleshoot why a rule was added but isn’t taking effect.

1. Check Global Routing before troubleshooting rule matches

Having a rules file doesn’t mean the current connection is using it to route traffic. Home manages connections and the selected outbound, Config manages configuration files, and Settings manages app preferences. Before troubleshooting, note the current selection under Home → Global Routing, then check which file is active in Config. Don’t assume that downloading a file also enables it.

Global Routing selectionWhat to checkHow to troubleshoot
ProxyHandles traffic using proxy routing rather than selecting a route from the regular rules in ConfigThis doesn’t prove that a particular DOMAIN-SUFFIX rule matched
DirectHandles traffic using direct connectionsCheck whether you forgot to switch back to Config after temporary testing
ConfigMatches rules in the currently selected configuration fileUse this selection for the rule tests in this guide
SceneRoutes traffic according to the configured Scene conditionsCheck both the Scene conditions and the route actually in use, not just the file contents

Settings → On Demand controls when connections are established based on conditions; it doesn’t set the priority of rules. A VPN connection indicator only shows that the tunnel is connected. To determine whether a particular request used a proxy, check the routing mode, matched rule, and final policy.

2. How to read a rule: type, match value, and policy

Rules are commonly separated by English commas. In DOMAIN-SUFFIX,example.com,DIRECT, the first field specifies the match type, the second is the value to match, and the third determines what happens when the rule matches. Regular rules belong in the [Rule] section of the configuration file. Don’t paste a rule at the end of the file without checking which section it belongs to.

[Rule]
DOMAIN,login.example.com,DIRECT
DOMAIN-SUFFIX,example.com,DIRECT
IP-CIDR,192.0.2.0/24,DIRECT,no-resolve
FINAL,DIRECT

This is a syntax example, not a complete configuration for every use case. 192.0.2.0/24 is a documentation-only network range. All rules use DIRECT so you can observe matching behavior without relying on an undefined proxy policy. Don’t use this example to replace an existing configuration.

For example, when a browser visits https://docs.example.com:443/help, a domain rule matches docs.example.com. Here, 443 is the connection port and /help is the URL path; neither is a DOMAIN-SUFFIX match value. Connection protocol settings and routing rules are separate layers, so don’t enter a protocol name in the domain field.

3. DOMAIN, DOMAIN-SUFFIX, and DOMAIN-KEYWORD: what’s the difference?

All three keywords match domains, but their scopes differ. Use DOMAIN when you need a precise exception, and DOMAIN-SUFFIX when you want to include an entire domain and its subdomains. DOMAIN-KEYWORD has a broader scope, so make sure it won’t also match unrelated domains that happen to contain the same text.

Rule exampleMatchesDoesn’t match
DOMAIN,example.com,DIRECTexample.comwww.example.com
DOMAIN-SUFFIX,example.com,DIRECTexample.com、www.example.comnotexample.com、example.com.other.test
DOMAIN-KEYWORD,example,DIRECTexample.com、myexample.testsample.test

DOMAIN-SUFFIX checks domain boundaries; it doesn’t match any string that happens to end with the same text. Usually, enter example.com directly without adding *.. If you only want to match api.example.com, use DOMAIN to avoid including other hosts under the same domain.

4. How IP-CIDR, GEOIP, and DNS work together

IP-CIDR matches whether a destination IP address falls within a specified network range; it doesn’t match domain text. 192.0.2.0/24 represents an IPv4 network, while 192.0.2.18/32 represents a single IPv4 address. The prefix number is neither a port nor a priority. A larger prefix usually means a smaller network range, but it won’t move the rule higher in the list.

IP-CIDR,192.0.2.18/32,DIRECT,no-resolve
IP-CIDR,192.0.2.0/24,DIRECT,no-resolve
GEOIP,CN,DIRECT
FINAL,DIRECT

GEOIP uses the location associated with the destination IP in an address database. For example, GEOIP,CN,DIRECT matches addresses the database associates with CN. It doesn’t match Chinese-language websites or domains ending in .cn. Content delivery networks, changing IP addresses, and database data can all produce results that differ from what you might infer from a website’s name.

So, a domain that appears to belong to a particular region doesn’t necessarily mean GEOIP will match as expected. First confirm the actual destination, then check the DNS result and the database lookup. If no address is available to evaluate, an IP rule with no-resolve may not match, and traffic will continue to the next rule.

5. Top-to-bottom rule matching: put precise exceptions first and FINAL last

Regular rules are checked in the order they appear in the configuration. When a rule matches, its policy is applied and evaluation doesn’t continue to find a “more specific” rule below it. DOMAIN doesn’t automatically outrank DOMAIN-SUFFIX, and a single-IP rule doesn’t automatically outrank a broader network rule. To prioritize an exception, put it before any rule with a wider scope.

Request receivedRead destinationCheck rules in orderSelect policyEstablish connection
[Rule]
DOMAIN,login.example.com,DIRECT
DOMAIN-SUFFIX,example.com,PROXY
GEOIP,CN,DIRECT
FINAL,PROXY

This example assumes the current configuration already has an available PROXY policy. For login.example.com, the first rule matches and uses a direct connection. For img.example.com, the first rule doesn’t match, so the second rule matches and sends the request to PROXY. If you move the second rule above the first, the suffix rule will match the login domain first, and the specific exception below it won’t take effect.

  1. Put specific host exceptions first, such as a single login domain.
  2. Next, add domain suffixes, keywords, and other rules as needed. Watch for overlapping match scopes.
  3. For IP-based rules, check whether resolution is allowed for matching and whether the rule might override later rules.
  4. Keep FINAL last to handle requests that don’t match any rule above it.

FINAL isn’t a fallback connection for failed requests. If a rule selects PROXY and that connection times out, evaluation won’t continue to FINAL. What happens after a connection fails depends on the policy group in use and its settings; adding another rule after FINAL won’t provide a fallback.

6. Back up, test, and change one rule at a time

These steps assume you already have your own connection configuration. Keep the original file before making changes. Test one clearly defined domain rule before reorganizing multiple rules. A remote configuration update may overwrite local edits, so distinguish your edited copy from the file that may be fetched again later.

  1. Keep a copy of the original configuration

    Open Config, confirm which configuration file is in use, and keep a recoverable copy. Note the current Global Routing selection and the order of the rules you’ll test. Don’t delete the entire rules section.

  2. Edit the rules section

    In Config, open the editing controls for the file you want to change and find [Rule]. Add one DOMAIN rule for a domain you control and can test. After saving, confirm that the edited file is the one currently enabled. The editing controls may look different depending on the app version.

  3. Check routing

    Go to Home → Global Routing → Config. Make sure the connection is on and the referenced proxy policy has an available outbound. If you use Scene, note its settings first so a Scene change isn’t mistaken for a rule change.

  4. Send a new request

    Have the target app establish a new connection, then check the connection log for the destination domain, address, matched rule, and policy. Existing long-lived connections may keep using their original route; saving a file doesn’t necessarily reconnect them immediately.

  5. Compare results and restore the original settings

    Compare the actual results with what you expected, checking the matched rule before connection success or failure. When testing is complete, remove the temporary rule or restore the original file, then restore the previous Global Routing selection.

Don’t rely on a latency test in Home alone to confirm that a rule is correct. It tests the selected outbound against a test destination, while a browser request may involve a different domain, address, or port. To reproduce an issue, record five details: destination domain, destination port, matched rule, final policy, and the observed error. This is more useful than repeatedly changing every setting.

7. Troubleshoot connection errors separately from rule errors

The following are common English error messages in network diagnostics. The app may show more context, and the wording may vary. First identify which rule matched the request, then troubleshoot the route it selected. Don’t switch all requests to the same policy just because you see a timeout.

Error: Connection refused

Cause and fix: This usually means the destination port or connection path refused the connection. First check whether the matched policy is DIRECT or a proxy policy, then check the destination address, port, and existing connection configuration. Adding a DOMAIN-SUFFIX rule won’t fix a port that isn’t accepting connections.

Error: Operation timed out

Cause and fix: The operation didn’t complete within the allowed time. The issue may involve DNS resolution, establishing the connection, or communication afterward. Use the connection log to identify the failed stage, then check DNS, outbound reachability, and the destination port separately. Don’t assume every timeout is caused by rule syntax.

If the file won’t save or load properly, check the section name, English commas, policy names, and number of fields. If the file works but the wrong rule matches, check rule order and match scope. If the correct rule matches but the destination is unreachable, investigate the connection path. Each issue requires a different approach.

Why does traffic still use the old route after I add DOMAIN-SUFFIX?

First check Home → Global Routing → Config, then confirm that Config has the edited file enabled. Next, look for an earlier rule that already covers the same domain, and start a new connection to avoid checking an existing one.

What happens if I put FINAL at the top?

FINAL matches requests that reach it, leaving no opportunity for later regular rules to evaluate those requests. Move it to the end of the rules section, then test again with a request that has a specific DOMAIN exception.

Can I put a full webpage URL in a rule?

DOMAIN and DOMAIN-SUFFIX take a domain, not a full URL. Split https://docs.example.com/help into the host docs.example.com, then choose the rule type based on whether you need to include subdomains. These rules don’t match URL paths.

What should I do if my rule disappears after updating the configuration?

In Config, check whether you fetched the remote file again or switched to another file. Restore any needed rules from the copy you saved before editing, then confirm which file is enabled. Updating a connection entry in Home and updating a rules file in Config are separate actions.

Verify on the App Store →