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

Learn what six Shadowrocket rule types match, how rules are evaluated from top to bottom, and why FINAL belongs on the last line.

At a glance

This guide is for people already using Shadowrocket on an iPhone or iPad who have their own server details or subscription but aren't sure why a rule matches—or doesn't. Check Global Routing and the active configuration first, then distinguish domain matches from IP matches and the FINAL fallback. By the end, you'll be able to write a minimal rule snippet and check where requests actually go using request records. Example domains and reserved addresses are for illustration only; no connectivity service is provided.

1. Before rules can work: Global Routing and the active configuration

Shadowrocket rules are not a server list. The server selected in Home determines the proxy exit used for connections, while the configuration in Config contains rules and other settings. Importing or updating your own subscription does not automatically switch to the configuration with the rules you expect. Check these separately before troubleshooting.

Check Global Routing in Home. This guide covers requests evaluated rule by rule when Config is selected. Proxy and Direct are global routing modes; their results alone don't prove that a specific rule in the configuration matched. Scene follows its selected scene settings and is not another name for Config.

SettingWhat it meansHow to test in this guide
ConfigApply the rules in the active configuration.Select this mode, then check that the active configuration is correct.
ProxyUse global proxy routing.Useful for isolating an exit issue, but not for validating individual rules.
DirectUse global direct routing.Compare with a direct connection, then switch back to Config when the test is done.
SceneFollow the settings for the selected scene.Check the scene settings first; use Config for an initial rule test.

2. Rule syntax and order: first match wins

A typical rule consists of an English keyword, a match value, and a policy, separated by commas. FINAL has no match value, so it uses two main fields: the keyword and the policy. DIRECT means connect directly; PROXY below means send traffic through the proxy. Make sure the selected proxy is working before using it. Any custom policy group name must also exist in the configuration.

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

This snippet illustrates syntax; it is not a complete, ready-to-connect configuration. Shadowrocket checks rules from top to bottom and applies the policy for the first matching rule. It does not continue looking for a “more specific” match. A precise rule does not automatically take priority over a broader one.

Request arrivesCheck rules in orderFirst matchApply policyConnect

In the example above, a request for login.example.com matches the first line and uses DIRECT. If DOMAIN-SUFFIX comes before DOMAIN, login.example.com matches the suffix rule first and goes to PROXY; the exact rule below never gets a chance to handle that request.

3. Where DOMAIN, DOMAIN-SUFFIX, and DOMAIN-KEYWORD differ

All three keywords match domains, but their coverage differs. Enter a hostname or keyword—not a full URL. Don't include https://, a page path, query parameters, or a port. For example, connecting to login.example.com on port 443 doesn't mean the DOMAIN match value should be login.example.com:443.

Rule exampleMatchesDoes not match
DOMAIN,example.com,DIRECTexample.comwww.example.com、example.com.test
DOMAIN-SUFFIX,example.com,PROXYexample.com、www.example.com、a.b.example.comnotexample.com、example.com.test
DOMAIN-KEYWORD,example,PROXYexample.com、myexample.test、example.netDomains that don't contain example

DOMAIN: match one exact hostname

DOMAIN is easiest to review when api.example.com and www.example.com need separate handling. It does not implicitly cover subdomains: DOMAIN,example.com,DIRECT won't also match api.example.com. When writing rules for an app, remember it may contact several hostnames for login, APIs, images, and other resources. The homepage domain alone won't tell you where every request goes.

DOMAIN-SUFFIX: cover a domain and its subdomains

DOMAIN-SUFFIX,example.com,PROXY matches the root domain and all levels of subdomains; no wildcard is needed. It isn't a search for any string ending in the same characters: notexample.com lacks the domain-level boundary, so it isn't a subdomain of example.com.

DOMAIN-KEYWORD: match domains containing a string

DOMAIN-KEYWORD doesn't require the keyword to fall on a domain-level boundary. It's useful when you really need to match multiple domains containing a string, but it can also produce unexpected matches. For example, example matches myexample.test. If you only want to handle the example.com domain and its subdomains, prefer DOMAIN-SUFFIX over a broader keyword.

4. GEOIP and IP-CIDR: match the destination address

GEOIP checks the destination IP's geographic classification in an address database. GEOIP,CN,DIRECT means use DIRECT when the database classifies the destination IP as CN. It doesn't check the website's language, where its domain was registered, or the user's location—and it can't guarantee that every service from a brand always uses addresses in the same region.

IP-CIDR matches a specific IPv4 range. IP-CIDR,192.0.2.0/24,DIRECT covers 192.0.2.0 through 192.0.2.255; /24 means the first 24 bits are the network prefix, not a port number. 192.0.2.0/24 is a range reserved for documentation and is shown here only to explain matching; it is not a usable server address.

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

Whether an IP rule needs to resolve a domain first can affect troubleshooting. The optional no-resolve parameter tells this rule not to initiate a DNS lookup just to match an IP. If the destination IP is already known, it can still be checked against the address. This does not “turn off DNS” or mean a webpage will never need name resolution. If the destination IP isn't available, the rule may be skipped and later rules can be checked.

5. Why FINAL belongs on the last line

FINAL is the fallback rule: if none of the preceding rules match, it applies the specified policy. It has no domain or network-range restriction, so placing it in the middle catches every request that reaches it and prevents rules below from being checked. “Last” means the end of the entire active rule sequence—not just the last section visible in the editor.

[Rule]
DOMAIN,login.example.com,DIRECT
DOMAIN-SUFFIX,example.com,PROXY
GEOIP,CN,DIRECT
FINAL,PROXY

FINAL,PROXY and FINAL,DIRECT are both explicit fallback choices; neither is right for everyone. The former sends unmatched requests through the proxy, while the latter connects directly. FINAL,PROXY requires a working proxy exit. With FINAL,DIRECT, unknown destinations connect directly. Before changing this setting, consider what you need—not just whether one webpage opens.

“Why doesn't my more specific rule match?”

Check whether a DOMAIN-SUFFIX, DOMAIN-KEYWORD, or FINAL rule above it has already matched. Move the DOMAIN exception ahead of broader rules, then make a new connection and check again.

“Can I add a rule after FINAL?”

You can add text, but that rule won't handle requests already caught by FINAL. Move new rules above FINAL and keep one clear fallback at the end.

“Will changing FINAL to DIRECT fix it?”

Not necessarily. It may simply bypass an unavailable proxy exit. Go back to Home and check the selected server, then see whether a more specific rule should handle the domain.

“Do subscription updates also update the rules?”

Updating a server subscription and updating a rule configuration are separate operations. Check the active configuration in Config, then confirm whether you updated the server list or the configuration file. A successful list refresh doesn't prove the rules were updated.

6. Minimal verification: change one rule at a time

Track both the expected policy and the actual request. A webpage loading only shows that one request succeeded; it doesn't prove whether it used DIRECT or PROXY. These steps don't require changing your subscription or protocol settings. Exit protocols such as Shadowsocks, VMess, and VLESS are separate from rule keywords.

  1. Keep the original configuration

    Check the active configuration in Config and save a recoverable copy or the original text before making changes. Note the current FINAL policy. Don't overwrite your only working configuration.

  2. Check the routing mode

    In Home → Global Routing, select Config. Then return to Config and confirm that the configuration you intend to test is active—not another configuration with the same name or a remote one.

  3. Add an exact-match exception

    In the rules section of the active configuration, add a DOMAIN rule for a real destination you can verify. Place it ahead of broad rules and FINAL. example.com in this guide is for syntax illustration only, not a proxy connectivity test target.

  4. Make a new request

    Save the configuration and make sure it is active. Close existing connections in the target app, then make a new request. Keep the server selected in Home unchanged so connection reuse or a different exit doesn't affect the result.

  5. Check the request record

    Use the fields shown in the interface to check the hostname, destination IP, matched rule, and actual policy in the request record or log. If the record doesn't include enough detail, enable the relevant logging first and repeat the same request. Don't infer the exit from latency alone.

7. When a rule matches but the request still fails: troubleshoot by layer

Rules choose where traffic goes; they can't guarantee that the destination, DNS, or proxy server is always available. If the request record shows the expected rule matched, check the connection stages that follow. The messages below are errors you may encounter during network troubleshooting, not rule syntax errors. Their exact wording depends on which layer reports the problem, so a single line isn't enough to identify a rule issue.

Error: Connection refused

Cause: A connection endpoint refused the connection. The destination port or proxy server port may not have a service listening on it.

What to do: Check the record for the address and port the client tried to reach. Then confirm that the server port in Home matches the service details you already have. If the failure is at the destination, check that service rather than broadening domain rules.

Error: Operation timed out

Cause: An operation didn't complete within the time limit. The issue could involve the network path, proxy connection, or destination response; a timeout alone doesn't show which one.

What to do: Use connection records around the error to identify the stage. Temporarily switch Home → Global Routing to Proxy or Direct for comparison, then restore Config. Keep the test destination the same.

Error: No route to host

Cause: The network path used for the connection can't reach the destination address. This doesn't mean the DOMAIN or FINAL fields are incorrect.

What to do: Check that the current network is available and that the actual destination IP and address family are as expected. Then confirm whether the request ultimately used DIRECT or the proxy exit, and troubleshoot that path.

If the failure is during DNS resolution, first check whether the DNS request succeeded. If server authentication failed, check your own server settings. Don't hide these issues by switching all requests to DIRECT, and don't rewrite the entire ruleset to fix one error. Keep the test conditions consistent so you can tell whether the fix worked.

Official App Store listingCheck the details before you buy