This guide is for users with a working connection who want to add domain-blocking rules in Config. First, distinguish match conditions from the REJECT policy; then add a precise rule, check connection logs, and assess whether shared-domain resources, cached content, or in-app content are beyond the scope of domain rules. The domains and addresses below are reserved examples used to explain syntax, not a ready-to-use blocklist.
1. REJECT is an action taken after a match—not a content filter
Shadowrocket rules answer two separate questions: what conditions a connection must meet, and what happens when it does. DOMAIN-SUFFIX, DOMAIN, and IP-CIDR are match conditions; REJECT is an action. Adding a domain to a rule does not identify ads, analytics code, or video segments on a webpage. It rejects connections that meet the rule's conditions.
This flow applies only to traffic that actually passes through Shadowrocket and is handled by the active rules. If traffic never enters the tunnel, rules cannot act on it. If traffic enters the tunnel but the overall routing mode is Proxy or Direct, that alone does not tell you whether a Config rule is working. To troubleshoot, check the connection status on Home first, then review Global Routing.
- Config: Applies the rules in the active configuration to determine how connections are handled. Use this mode to test the rule examples in this guide.
- Proxy: Routes all traffic through the proxy. This is not the right mode for testing Config routing rules.
- Direct: Routes all traffic directly. A page loading successfully does not, by itself, mean a reject rule has failed.
- Scene: Check which configuration and routing settings the scene actually uses. For testing, select Config first to reduce variables.
What happens after a connection is rejected depends on the app: it may show a failed resource, a blank placeholder, or repeatedly retry. REJECT does not remove page layout, guarantee faster loading, or replace remote content with something else.
2. DOMAIN and DOMAIN-SUFFIX: syntax and scope
For domain rules, enter only the hostname—not https://, a port, path, or query string. For a request to https://ads.example.com:443/banner?id=1, the hostname to check is ads.example.com. Port 443 is the connection port, and /banner is the path; neither belongs in a DOMAIN-SUFFIX domain parameter.
DOMAIN,ads.example.com,REJECT
DOMAIN-SUFFIX,metrics.example.com,REJECT
Exact hostname match
- Rule type
- DOMAIN
- Parameter
- ads.example.com
- Policy
- REJECT
- Match scope
- Only ads.example.com, not img.ads.example.com
For the first test, use an exact hostname to keep the impact limited.
Domain suffix match
- Rule type
- DOMAIN-SUFFIX
- Parameter
- metrics.example.com
- Policy
- REJECT
- Match scope
- metrics.example.com and its subdomains
Use a suffix rule only after confirming the entire domain branch serves the same purpose.
DOMAIN-SUFFIX,example.com,REJECT matches example.com and subdomains such as api.example.com. It is not a substring match, so notexample.com should not match. Don't use *.example.com in place of the suffix parameter; enter the bare domain as required by the rule syntax.
3. Rules are evaluated from top to bottom: exceptions first, FINAL last
Rule order directly affects the outcome. For a given connection, the first matching rule determines how it is handled; a more specific rule farther down does not automatically take priority. Put allowed exceptions before the reject rule they would otherwise match. Broad IP or region rules and FINAL usually come after the relevant domain rules.
[Rule]
DOMAIN,keep.metrics.example.com,DIRECT
DOMAIN-SUFFIX,metrics.example.com,REJECT
GEOIP,CN,DIRECT
FINAL,DIRECT
This snippet demonstrates rule order only: keep.metrics.example.com matches the exact exception first, while the rest of the metrics.example.com domain branch is rejected. FINAL,DIRECT is included only to make the example self-contained. Keep your existing fallback policy in a real configuration; don't route all unmatched traffic directly just to add a block rule.
| Rule position | Typical issue | How to fix it |
|---|---|---|
| Reject rule comes after FINAL | The connection was already handled by the fallback rule | Move the reject rule above FINAL |
| Exception comes after suffix reject | The exception hostname matches REJECT first | Move the exact exception above the suffix rule |
| Broad allow rule comes before reject | The destination matches the allow policy first | Check the match log and reorder overlapping rules |
Takeaway: check the first matching rule before adding another
If an earlier rule already handles the target connection, adding the same REJECT rule again won't change the outcome. Check the active configuration and the match position first, then move the rule or narrow its conditions.
For an IP address, syntax such as IP-CIDR,192.0.2.0/24,REJECT,no-resolve illustrates how an address range can be matched; this range is a documentation example. no-resolve means the IP rule won't trigger a DNS lookup for that rule. It does not disable DNS on the device. A shared IP may host unrelated domains, so don't reject an entire address range just because domain blocking had no effect.
4. Domain rules can't distinguish paths on the same host or control in-app layouts
Suppose the article uses api.example.com/article and the promotion uses api.example.com/promotion. Both use the same hostname, so DOMAIN and DOMAIN-SUFFIX cannot reject just the latter path. Setting api.example.com to REJECT may also block the article, login state, and comments API.
| How content is delivered | What domain rules can do | What they can't guarantee |
|---|---|---|
| Assets loaded from a separate hostname | Reject new connections to that hostname | That the app removes the resulting blank space |
| Different paths on the same hostname | Handle the hostname as a whole | Selecting a specific path with a domain rule |
| Promotion and main content in the same response | Reject the entire connection | Selecting part of the response content |
| Locally cached or bundled content | Match anything when there is no new connection | That already displayed content disappears immediately |
HTTPS usually hides URL paths and response bodies. Even when a rule can identify the destination domain, that does not mean it can read every resource in an encrypted connection. Domain-level REJECT can block a host without decrypting its content, but its scope is limited to the connection. Path-level handling, response rewriting, and hiding page elements are not domain-rule capabilities.
- If video and promotional segments have already been combined into one media stream, rejecting the media host may prevent the entire video from playing.
- An in-app page still makes network connections, but being displayed inside an app does not mean its assets come from a separate domain.
- If the app retries using a different hostname, the original rule may still be matching correctly; it simply doesn't cover the new destination.
- If a request connects directly by IP and provides no usable domain information, don't expect one domain rule to cover every case.
5. Add and test one rule at a time, with a way to roll back
Test with a configuration that already works. This guide assumes you have your own provider and subscription; it does not provide or recommend connection services. If the resource you're testing is normally accessible directly, keep your existing connection setup and observe only the effect of the new rule.
- Back up the current configuration. In Config, confirm which file is active, then save a copy or record its original contents. Don't overwrite the entire file with the example snippet.
- Set a consistent routing mode. On Home, confirm the connection is enabled, set Global Routing to Config, and make sure the configuration you edited is active.
- Add an exact rule. In the configuration's
[Rule]section, start with a rule such asDOMAIN,ads.example.com,REJECT. Replace the example hostname with the target hostname from your logs, and place the rule above relevant broad rules and FINAL. - Save and make a new request. Reopen the target page or app. If needed, reconnect so the new request is evaluated against the updated configuration. Existing long-lived connections and local caches are not reliable evidence on their own.
- Check connection logs. Find new requests to the target hostname and confirm the actual policy is REJECT. Also check essential features such as login, article content, images, and playback.
- Roll back if something breaks. Remove or disable the rule you just added, then test again. If the feature works again, decide whether to add an exact exception, narrow the rule to DOMAIN, or stop blocking that hostname altogether.
If automatic connection is enabled, also check Settings → On Demand so a connection being restored or its state changing during a test doesn't go unnoticed. On Demand controls when a connection starts; it does not change REJECT match priority. Troubleshoot them separately.
6. Troubleshooting: no match, content still visible, or a feature stops working
I added REJECT. Why does the webpage still open?
First check whether you rejected the webpage's hostname or the hostname of an asset it loads. If only an asset domain is rejected, the main page may still open as expected. Then confirm Global Routing on Home is set to Config, the right configuration is active, and the rule is above FINAL. Finally, check the actual policy for a new connection instead of judging by whether the whole page opens.
The log shows REJECT. Why is the app still showing the old content?
Reopen the target page and check whether it makes new requests. Downloaded images, preloaded content, and assets bundled with the app may remain visible. The app may also switch to another hostname. Compare request times and destination domains; don't widen the block just because content is still on screen.
I can't log in after adding a rule. How do I recover?
First remove the rule you added most recently, then try logging in again. If login works, the rule may have covered an essential endpoint. Compare the hostname logs from before and after login, and narrow the suffix rule to an exact hostname. Add an exact exception before the reject rule only when you've confirmed that hostname needs to be allowed.
Will switching to a different proxy protocol make REJECT more precise?
No. Switching to Shadowsocks, VMess, VLESS, Trojan, Hysteria2, or WireGuard does not add content-aware filtering. REJECT matches depend on traffic being handled by the rules, the destination information available, and rule order. Keep your connection setup unchanged while testing rules so you can isolate the cause.
Keep a rule only if three conditions are met: the new request to the target actually matches, the intended resource is restricted, and essential features remain unaffected. If a domain can't separate content you want to keep from content you want to block, recognize the limits of hostname-level rules rather than stacking broader reject rules.