Shadowrocket REJECT Rules: What Domain Blocking Can and Can’t Do

Learn how REJECT works in rule matching, how DOMAIN-SUFFIX blocks connections, and where domain rules fall short with shared hosts and encrypted DNS.

At a glance

In Shadowrocket, REJECT is a connection-handling policy, not a page element filter. This guide is for users checking domain-blocking rules in their own configuration. First confirm that Global Routing is set to Config, then check rule order, domain visibility, and records for new connections. Use a broader DOMAIN-SUFFIX rule only when you’re sure the entire target domain should be blocked.

Where REJECT fits: rules select the match; policies determine what happens

A rule typically includes a rule type, a match value, and an action. In DOMAIN-SUFFIX,example.com,REJECT, DOMAIN-SUFFIX matches a domain suffix, example.com is the match value, and REJECT is the policy that blocks the connection when the rule matches. REJECT is not a domain list, and its presence in a configuration alone doesn’t prove that a connection will be blocked.

Request enters the tunnel Destination details become available Rules are checked in order Matched policy is applied Check the connection result

In a typical rule-based routing flow, rules are checked from top to bottom, and the first match determines the policy. A broad allow rule near the top can prevent a later REJECT rule from being reached. FINAL is the fallback when no earlier rule matches, so place it at the end of the rule list. It isn’t an extra check and won’t override a result from an earlier match.

Whether rules are evaluated also depends on the current routing mode. Check the selection under Home → Global Routing. This guide assumes Config is selected. Proxy and Direct aren’t equivalent test conditions for checking whether a configuration rule matches. With Scene, first confirm which routing settings the active scene is using.

DOMAIN-SUFFIX scope: the entire domain suffix, not a URL path

DOMAIN-SUFFIX,example.com,REJECT matches example.com and subdomains such as img.example.com. It won’t match notexample.com just because the name contains similar text. To target one specific hostname, consider an exact DOMAIN match so you don’t block other services under the same suffix.

Rule or targetMatch resultWhat to check
example.comSuffix rule matchesRoot domain is included
img.example.comSuffix rule matchesSubdomain is included
notexample.comSuffix rule does not matchDifferent domain-label boundary
example.com/assets/banner.jpgPaths can’t be matched separatelySuffix matching doesn’t inspect URL paths

The rule snippet below illustrates the order: exact exception first, suffix rejection next, and fallback last. The example domains are for syntax only; they don’t identify real services to block and aren’t a complete, ready-to-use configuration. Before adding these rules to an existing configuration, make sure the direct-connect exception suits your needs.

[Rule]
DOMAIN,keep.example.com,DIRECT
DOMAIN-SUFFIX,example.com,REJECT
FINAL,DIRECT

Here, keep.example.com first matches the exact DIRECT rule. Other targets under example.com then reach the REJECT rule. If you reverse the order, the earlier suffix rule will override the exception. Don’t block an entire shared domain suffix to fix one page issue; start with the smallest confirmed target.

Start testing: fix the routing mode and active configuration

Change only one condition per troubleshooting round. Save a copy of the current configuration and note the rule order before and after testing. Then make sure you’re editing the configuration that’s actually in use. Editing a different file in Config without switching to it doesn’t show that the rule syntax is wrong.

Routing conditions

Routing mode
Home → Global Routing
Test mode
Config
Configuration check
Confirm which file is active in Config
Connection prerequisites
Confirm the VPN is connected, then send a new request

Fix the routing conditions before checking whether a rule matches.

Rule conditions

Exact match
DOMAIN,ads.example.com,REJECT
Suffix match
DOMAIN-SUFFIX,example.com,REJECT
Fallback position
Place FINAL at the end of the rule list
Connection record fields
Destination host, destination IP, matched rule, and policy

Check the fields shown in the app’s connection records; don’t use page appearance as proof of a rule match.

  1. Choose a destination domain whose purpose you can confirm, then test with an exact rule first to limit the impact.
  2. Place the test rule above any broad rule that could match first, save the configuration, and confirm it’s active.
  3. End existing requests, then reopen the target page or trigger the feature again to create a new connection.
  4. Check the connection records for the test time, destination details, and matched policy. If needed, reconnect the VPN without changing the configuration and test again.
  5. Remove the test rule and repeat the same steps. Compare the new connection results to see whether the rule caused the change.

On Demand controls automatic connection conditions; it doesn’t change the priority of domain-blocking rules. If the VPN connects or disconnects automatically during testing, check the relevant conditions under Settings → On Demand so a change in tunnel state isn’t mistaken for intermittent REJECT behavior.

Limits with shared domains: blocks connections, not individual page elements

When a page’s text, images, login API, and pending content all come from the same hostname, a domain rule can’t distinguish them by purpose. HTTPS paths, response bodies, and page elements aren’t match fields for DOMAIN-SUFFIX. Blocking the domain may also affect login, verification codes, image loading, or playback.

443
A common HTTPS destination port; the port alone doesn’t identify the type of content
2 types
Domain matching in this guide: exact DOMAIN matches and DOMAIN-SUFFIX matches
0 fields
URL path match fields in DOMAIN-SUFFIX rules

HTTP/3 typically uses UDP 443, while common HTTPS connections may use TCP 443. Seeing port 443 doesn’t tell you whether a connection carries page content, analytics, or video. It also doesn’t mean a REJECT rule will affect only one content type. After a connection is blocked, an app may switch to another domain or API, or use cached data, so the original content may still appear.

Bottom line: narrow the match when traffic purposes can’t be distinguished

If login or page content stops working after you add a suffix-blocking rule, remove it first. Use DOMAIN to test a specific host only when connection records confirm it has a separate hostname. Don’t keep broadening the domain or IP range.

Encrypted DNS and IP rules: what destination details are available at match time

Domain rules require usable domain information at the time of matching. DNS resolution, caching, whether the app connects directly to an IP, and DNS handling in the configuration can all affect what appears in connection records. Encrypted DNS doesn’t automatically disable every domain rule, and you can’t assume every IP connection can be reliably mapped back to its original domain.

An app using DoH may communicate with a resolver over HTTPS; that request doesn’t reveal every domain the app later looks up. If a subsequent connection exposes only an IP and there’s no usable domain mapping, a domain rule may not match. Conversely, Shadowrocket may have a usable domain mapping or other destination details. Check the connection record for that specific request.

Record or symptomCheck firstAvoid doing this immediately
Destination domain is visible, but a different policy matchedRule order, active configuration, and spellingSwitch DNS settings on a hunch
Only the destination IP is visibleResolution path, domain mapping, and how the app connectsAssume a domain rule must match
Several features break after blocking an IPShared IP, CDN, and connections for other servicesKeep widening the blocked IP range

IP-CIDR matches an address or network range; GEOIP classifies by IP geolocation database. Neither matches page content. The syntax example IP-CIDR,192.0.2.1/32,REJECT,no-resolve uses a documentation-only address. Here, /32 denotes a single IPv4 address, and no-resolve means this IP rule won’t trigger domain resolution. It doesn’t fill in all missing domain information and shouldn’t be copied as-is to block real traffic.

Troubleshooting takeaway: use match records for new connections

To determine whether a REJECT rule works, check three things separately: whether the configuration is active, whether the target matched, and whether the result was expected. Content still appearing on a page doesn’t prove that no connection was blocked; a failed connection alone doesn’t prove REJECT caused it. Match the destination, timestamp, rule, and app behavior in the records.

  1. REJECT didn’t match: Check that Home → Global Routing is set to Config, then verify the active configuration, rule order, domain boundaries, and available destination details.
  2. REJECT matched, but content still appears: Send a new request, rule out cached data, existing connections, and alternate domains, and identify the connection actually carrying the content.
  3. REJECT matched and a feature stopped working: Remove the rule and test with a narrower match. If the service shares a domain, don’t try to distinguish page content with a suffix rule.
  4. Keeping a rule long term: Record its target, purpose, and rollback steps. After updating the configuration, check that the rule is still there and its position hasn’t changed.

Existing subscriptions are generally used to update connection details; rules in Config are a separate item to check. Updating a subscription doesn’t necessarily update rejection rules, and updating a configuration file may overwrite local changes. If you already have your own provider and subscription, check the connection details and rule file separately. You don’t need to change connection services to test REJECT.

Verify Shadowrocket on the App Store