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.
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.
| Rule | What it matches | Example it does not match |
|---|---|---|
DOMAIN,example.com,DIRECT | Matches only example.com | www.example.com |
DOMAIN-SUFFIX,example.com,DIRECT | Matches example.com and its subdomains, such as a.b.example.com | notexample.com |
DOMAIN-KEYWORD,example,DIRECT | Matches requests to domains containing example | A 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 type | Meaning | What to check |
|---|---|---|
IP-CIDR | Whether the destination IPv4 address falls within the specified range | Enter a network address and prefix length, not a URL |
GEOIP,CN | Whether the destination IP is classified as CN in the geographic database being used | It does not use the domain suffix, webpage language, or device location |
no-resolve | Does not actively resolve a domain just to check this IP rule | Does 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
api.example.com: matchesDOMAINfirst and usesDIRECT; the next line does not change it toPROXY.www.example.com: does not match the first line, but matches the second and usesPROXY.- Direct access to
192.168.1.20: neither domain rule matches, so the local network range rule handles it. - Other destinations: check
GEOIP; if nothing matches,FINAL,PROXYhandles the request.
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.
-
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. -
Add a specific rule
Place the required
DOMAINexception before the relevantDOMAIN-SUFFIXrule, and keepFINALat the end of the file. After saving, make sure Config is using the edited file. -
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. -
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 symptom | Problem | How to fix it |
|---|---|---|
DOMAIN,https://example.com/a,DIRECT | Using a full URL as the domain | Use DOMAIN,example.com,DIRECT instead; paths are not checked |
DOMAIN-SUFFIX,*.example.com,DIRECT | Including a wildcard in a suffix match value | Use DOMAIN-SUFFIX,example.com,DIRECT instead |
IP-CIDR,192.168.1.20:8080,DIRECT | Including a port and omitting the CIDR prefix | Write a single address as 192.168.1.20/32; this rule does not specify a port |
FINAL,example.com,PROXY | Adding an extra match value to FINAL | Use FINAL,PROXY and place it at the end of the rules |
| Using Chinese commas between fields | Incorrect field separator | Replace 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.