Shadowrocket Rule Syntax: DOMAIN-SUFFIX, DOMAIN-KEYWORD, GEOIP, IP-CIDR, and FINAL Explained

Learn what DOMAIN, DOMAIN-SUFFIX, DOMAIN-KEYWORD, GEOIP, IP-CIDR, and FINAL match, with examples and common mistakes.

Quick overview

Shadowrocket rules first determine what a request matches, then which policy handles it. This guide is for users with a working configuration who want to adjust their routing rules. Learn the difference between domain and IP rules, order exceptions from top to bottom, then verify the result in a new connection record. The examples cover rule syntax only and do not provide connectivity services; any proxy connections assume you already have your own service and subscription.

1. Rule syntax: type, value, and policy

A standard rule usually has three comma-separated fields: rule type, match value, and policy. Add rules under the [Rule] section of your configuration. FINAL has no match value, so it takes only two fields. Check the format and match scope first; this makes issues easier to pinpoint than simply adding more rules.

[Rule]
DOMAIN,api.example.com,DIRECT
DOMAIN-SUFFIX,example.com,PROXY
FINAL,DIRECT

DIRECT connects directly, PROXY uses a proxy policy, and REJECT blocks matching connections. The policy field can also reference a policy defined in your configuration, but its name must match exactly. These examples use built-in policy names to avoid introducing undefined policies.

Request received Inspect destination Check rules in order Choose policy Establish connection

2. What DOMAIN, DOMAIN-SUFFIX, and DOMAIN-KEYWORD match

These three rule types check domain names, not full URLs. Enter example.com, not a URL containing https://, a port, or a path. A webpage may load its main document, images, and API calls from different domains. A rule does not automatically cover every connection just because they appear on the same page.

RuleWhat it matchesExample it does not match
DOMAIN,example.com,DIRECTMatches only example.comwww.example.com
DOMAIN-SUFFIX,example.com,DIRECTMatches example.com and its subdomains, such as a.b.example.comnotexample.com
DOMAIN-KEYWORD,example,DIRECTMatches requests to domains containing exampleA request to sample.test where only the URL path contains example

DOMAIN-SUFFIX matches domain boundaries, not arbitrary string endings. Usually, enter example.com directly rather than *.example.com. To handle only api.example.com, use DOMAIN to define the scope precisely without also matching its subdomains.

DOMAIN-KEYWORD has a broader scope: example could match the intended site as well as other domains containing the same string. It is not a regular expression, so regex symbols are not match syntax. To target one specific domain and its subdomains, prefer a suffix rule that precisely describes the intended scope.

[Rule]
DOMAIN,api.example.com,DIRECT
DOMAIN-SUFFIX,example.com,PROXY
DOMAIN-KEYWORD,telemetry,REJECT
FINAL,DIRECT

Here, api.example.com matches the first line, while other example.com subdomains match the second. The third line checks only unmatched requests for domains containing telemetry; it does not override policies already set by the first two lines.

3. IP-CIDR and GEOIP: match destination IPs, not URL text

IP-CIDR matches IPv4 ranges. The number after the slash is the network prefix length, not a port. 192.168.1.0/24 covers the address range from 192.168.1.0 through 192.168.1.255; /32 represents a single IPv4 address. Use the corresponding IP-CIDR6 type for IPv6 ranges.

[Rule]
IP-CIDR,192.168.1.0/24,DIRECT,no-resolve
IP-CIDR,192.0.2.8/32,DIRECT,no-resolve
IP-CIDR6,2001:db8::/32,DIRECT,no-resolve
GEOIP,CN,DIRECT
FINAL,PROXY

192.0.2.8 and 2001:db8::/32 are documentation examples, not service endpoints. When connecting to 192.168.1.20:8080, the range rule checks 192.168.1.20, not just port 8080. Adding a port to a CIDR match value mixes two different conditions.

Field or typeMeaningWhat to check
IP-CIDRWhether the destination IPv4 address falls within the specified rangeEnter a network address and prefix length, not a URL
GEOIP,CNWhether the destination IP is classified as CN in the geographic database being usedIt does not use the domain suffix, webpage language, or device location
no-resolveDoes not actively resolve a domain just to check this IP ruleDoes not disable all DNS or guarantee that domain requests will match

For a domain request to match an IP rule, there must be a destination address to check. Whether rule matching triggers a lookup depends on the rule options and request context. With no-resolve, if no destination IP is available, the range rule cannot be relied on to cover the domain. To reliably cover a specific domain, add an explicit domain rule that is easier to verify.

GEOIP results depend on the IP geolocation database in use. A domain may resolve to multiple addresses, and their geographic classifications can change, so GEOIP does not express the same intent as DOMAIN-SUFFIX. To consistently apply a policy to a specific domain, place its domain exception before the general GEOIP rule.

4. Rules are checked top to bottom: why FINAL belongs last

Standard rules are checked in order, and the first match determines the policy. Rules are not automatically prioritized by specificity. Put specific exceptions first, broader rules after them, and FINAL last to handle requests that have not matched any earlier rule.

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

If you move the suffix rule to the top, api.example.com matches it first, so the specific domain exception below it no longer applies. Likewise, placing FINAL,DIRECT at the top prevents subsequent rules from being checked normally. After changing the order, verify it with a new connection rather than simply refreshing a page on an existing connection.

5. After editing Config, verify the result in four steps

Change one condition at a time while troubleshooting. First confirm you edited the configuration currently in use, then check the routing mode on Home, and finally inspect the destination and policy for a new connection. Seeing the connection toggle turned on does not prove that a particular rule matched.

  1. Save a copy of the original configuration

    Open Config, confirm which file is currently in use, and save a copy first. Open the file's text editor and make changes under [Rule]; do not add rules under [Host] or another section.

  2. Add a specific rule

    Place the required DOMAIN exception before the relevant DOMAIN-SUFFIX rule, and keep FINAL at the end of the file. After saving, make sure Config is using the edited file.

  3. Select Config

    Go to Home → Global Routing → Config and check the connection status. If you need to use PROXY, first check connectivity to your existing service with Home → Connectivity Test. A successful test does not by itself prove that a rule matched.

  4. Check a new connection

    Make the request again, then compare its actual domain, destination IP, and policy in the in-app connection log. If a page accesses multiple domains, check each one separately; do not assume the result for an image request applies to the main page request.

If the log shows a destination other than the one you expected, check for redirects, API domains, or direct IP access before broadening the rule. If the request is still using an existing connection, close the relevant page or app and try again; if necessary, reconnect in Shadowrocket. Testing with a repeatable new request helps distinguish a rule that did not match from a connection that has not changed yet.

6. Common rule mistakes and errors unrelated to rules

Syntax errors, incorrect match scopes, and unavailable services are different problems. Rules choose a policy; they do not fix a subscription URL or proxy connection settings. Start by checking issues visible in the rule text, then troubleshoot subscription loading errors separately.

Mistake or symptomProblemHow to fix it
DOMAIN,https://example.com/a,DIRECTUsing a full URL as the domainUse DOMAIN,example.com,DIRECT instead; paths are not checked
DOMAIN-SUFFIX,*.example.com,DIRECTIncluding a wildcard in a suffix match valueUse DOMAIN-SUFFIX,example.com,DIRECT instead
IP-CIDR,192.168.1.20:8080,DIRECTIncluding a port and omitting the CIDR prefixWrite a single address as 192.168.1.20/32; this rule does not specify a port
FINAL,example.com,PROXYAdding an extra match value to FINALUse FINAL,PROXY and place it at the end of the rules
Using Chinese commas between fieldsIncorrect field separatorReplace them with standard commas and check that the rule is under [Rule]

Error: Failed to load subscription

Cause and fix: This message means a subscription failed to load. The address may be invalid or unreachable; it is not a syntax diagnostic for a particular DOMAIN-SUFFIX rule. Ask your own service provider to confirm that your existing subscription URL is valid, then update it from Home. Troubleshoot rules separately after the subscription entry is available and the configuration is enabled.

If the configuration is maintained by a remote source, note that a later update may overwrite your local changes. Check where the file comes from and how it is updated, and keep a local copy to avoid losing a rule you just verified. Updating a subscription entry and editing the [Rule] section are separate tasks; repeatedly updating the subscription is not a substitute for checking the rules.

7. Frequently asked questions about rule matching

I added DOMAIN. Why aren't subdomains matched too?

DOMAIN matches only the exact domain. To cover example.com and its subdomains, use DOMAIN-SUFFIX,example.com,DIRECT. For an exception on a specific subdomain, place its DOMAIN rule above the suffix rule.

Does GEOIP,CN guarantee direct connections to every Chinese-language website?

No. Rules cannot determine this based on webpage language. GEOIP checks the IP's classification in a geographic database. Check the actual destination IP in the connection log. To handle a specific domain, add a domain rule before GEOIP.

My rules look right. Why does everything still use the same policy?

First, check that Home → Global Routing is set to Config, then confirm the active file in Config. Next, look for an overly broad DOMAIN-KEYWORD rule or a FINAL rule placed too early. Finally, verify the result in a new connection log.

Does no-resolve prevent all domains from being resolved?

No. It limits lookups triggered to check the corresponding IP rule. If you want a specific domain to connect directly, use an explicit DOMAIN or DOMAIN-SUFFIX rule rather than relying on no-resolve instead of domain matching.

Download on the App Store