REJECT only decides whether a single connection is allowed through; it never inspects the traffic inside it. After reading, you will be able to tell how REJECT, PROXY, and DIRECT relate to one another in a rule list, see why REJECT cannot block promotional endpoints on the same domain or in-app requests to hardcoded IPs, and work through a fixed checklist when a rule is written but does not take effect. Written for readers who already get a subscription from their own provider and are organizing their own rules.
What REJECT Is in a Rule: One Outbound Policy
A Shadowrocket rule line has three parts, written as type,value,policy, and the policy field takes only three values: PROXY (send the connection out through the currently selected server), DIRECT (connect locally without the proxy), and REJECT (reject or drop the connection locally). REJECT is not a master switch in Settings; it is the action of a single rule, and only connections that match that rule are blocked.
A minimal working blocking rule looks like this:
DOMAIN-SUFFIX,ads.example.com,REJECT
DOMAIN-KEYWORD,metrics,REJECT
IP-CIDR,203.0.113.0/24,REJECT,no-resolve
FINAL,PROXY
Rules live in the current Config file (Home → current configuration → Edit), and you can also add or remove them directly in the rule list on Home. After editing, you need to re-select that Config before it takes part in matching. Updating a subscription re-downloads the configuration file, so rules you edited locally may be overwritten — check them again after an update.
Matching order: when REJECT gets its turn
Every new connection is matched against the rules exactly once: the client compares them line by line from the top of the list, the first rule that matches decides where the connection goes, and the rules below it are not consulted. Whether REJECT takes effect depends on whether a broader rule above it claims the connection first.
The issue is about how broad each rule is. If DOMAIN-KEYWORD,ads,REJECT sits above DOMAIN-SUFFIX,ads.example.com,PROXY, then ads.example.com is caught by the keyword rule first. Reverse the order and the narrower rule matches first, leaving the keyword rule below with no chance at that connection. Narrow rules first, broad rules later — that is the basic way to order a rule list.
DOMAIN,api.example.com,DIRECT
DOMAIN-SUFFIX,example.com,PROXY
DOMAIN-KEYWORD,metrics,REJECT
IP-CIDR,198.51.100.0/24,REJECT,no-resolve
GEOIP,CN,DIRECT
FINAL,PROXY
These six lines form a workable skeleton: exact domain → domain suffix → keyword → IP range → geolocation → fallback, with the most specific rules first.
FINAL is the catch-all rule: it matches every connection the rules above it did not, and it must stay on the last line. Put it in the middle and every rule below it is dead on arrival. IP rules have two more details. Adding no-resolve means the rule does not trigger a DNS lookup and only matches when the target is already an IP literal; an IP-CIDR rule without no-resolve resolves the domain to an IP before comparing, so results can vary depending on what the lookup returns.
FINALis not on the last line, so every rule below it stops working.DOMAIN-KEYWORDsits aboveDOMAINorDOMAIN-SUFFIXand sweeps up domains that should have been handled precisely.GEOIP,CN,DIRECTsits above specific domain rules, so every domain in mainland China goes direct and the rules below never get a turn.- Rules that came with the subscription sit above the ones you added, so your own rules never match.
Blocking Limits: HTTPS, In-App Requests, and Domain Fronting
REJECT acts at connection setup: it rejects or drops the connection locally and takes no part in the data exchanged after the TLS handshake. That defines its ceiling — it governs whether a connection can be made, not what a page displays.
Limit 1: HTTPS Is Only Blocked at the Connection Layer
For a request such as https://ads.example.com/x.js, REJECT blocks the connection to ads.example.com:443, so the script never arrives. But when promotional content and the main content come from the same domain — say an endpoint under example.com — REJECT cannot help: block the whole domain and the page content fails to load too. No rule keyword matches on URL path, because the client cannot see the path of an HTTPS request.
Limit 2: In-App Requests and Hardcoded IPs
Many apps hardcode their reporting endpoints as IP literals, or hand out domains dynamically from an API. Domain rules cannot match the first case, so an IP-CIDR rule is needed as a fallback; for the second, you can only add a rule once the real domain shows up. Blocking by IP has a cost: it easily catches the wrong traffic, since the same subnet often carries legitimate services, especially on shared CDN IPs. Domain rules and IP rules are two complementary entry points, matching the two ways a connection can start:
DOMAIN-SUFFIX,ads.example.com,REJECT
IP-CIDR,203.0.113.0/24,REJECT,no-resolve
One more detail is QUIC. Connections over UDP 443 go through rule matching as well, but if you wrote an IP-CIDR rule with no-resolve and the app starts the connection by domain name, the rule will not trigger a lookup and therefore will not match.
Limit 3: Domain Fronting
Domain fronting works by making the SNI in the TLS handshake differ from the Host the request actually targets, with the SNI usually pointing at a clean domain. Shadowrocket matches rules against the connection's target domain — that is, the SNI — so DOMAIN-SUFFIX blocks the domain named in the SNI. Blocking by SNI also affects legitimate services on the same entry point, while blocking by Host is outside what client-side rules can do.
Conclusion: REJECT Is a List-Based Connection Blocker, Not a Content Filter
Matching by domain and IP and acting at the connection layer means REJECT can stop requests to standalone domains and standalone IPs. Promotional endpoints on the same domain, content at the URL-path level, and traffic where the SNI and Host disagree all fall outside its reach. Setting expectations around that boundary saves a lot of trial and error spent rewriting rules.
Rule Written but Not Working: Troubleshoot in This Order
When a rule does not take effect, the cause usually comes down to two things: which configuration is currently active and the matching order. Checking the items below in order is faster than rewriting the rule again and again.
-
Confirm the active Config
Go back to Home and check the configuration name shown at the top. If the rule lives in Config A but Config B is selected, it will never take part in matching.
-
Check where the rule sits in the list
Look for a broader rule higher up that matches first, especially when DOMAIN-KEYWORD sits above DOMAIN-SUFFIX.
-
Confirm whether the connection starts with a domain or an IP
Domain rules cannot match a direct IP connection, and an IP-CIDR rule with no-resolve will not trigger a lookup for a domain-based connection.
-
Confirm the Global Routing setting
While Global Routing is set to Proxy or Direct, the rule list takes no part in routing decisions; only back on Config are rules matched one by one.
-
Recheck rules after updating the subscription
A subscription update re-downloads the configuration, so locally edited rules may be overwritten; after updating, go back to Home and confirm your rules are still there.
REJECT only applies to connections that pass through the Shadowrocket tunnel, and it does not inspect traffic content. Rules can change where a connection goes, not how an app itself behaves.
Five Common Questions About REJECT
I added a REJECT rule and now normal pages on the same domain will not open?
That means the domain carries both the page content and the content you blocked. REJECT blocks the whole domain and cannot take only part of it; narrow the rule to a specific subdomain, or switch to DOMAIN to match a single hostname exactly.
What exactly is the difference between REJECT and DIRECT?
DIRECT lets the connection through: it is established as usual, just without the proxy. REJECT refuses or drops it locally, so the connection never gets established. Use DIRECT when you want the connection to work without the proxy, and REJECT when you want it to fail.
I added a rule on Home and it disappeared after a subscription update?
A subscription update re-downloads the configuration file, so locally edited rules may be overwritten. For rules you want to keep long term, check the list on Home after updating and add them again if needed.
I blocked a whole IP range and now other services are broken too?
An IP-CIDR rule blocks the entire subnet, and shared CDN IPs often host legitimate services as well. Prefer domain rules; if you really need to block by IP, split the range into smaller blocks and add no-resolve to avoid extra lookups.
Why do rejected connections show no traffic on the Data page?
The connection ends at the setup stage, so no data is transferred and the per-server and per-app counters naturally stay flat. To tell whether a rule matched, go by the active configuration and rule order on Home.