REJECT 只决定一条连接放不放行,不解析传输内容。读完你能分清 REJECT 与 PROXY、DIRECT 在规则列表里的位置关系,知道它为什么拦不住同域名下的推广接口与硬编码 IP 的应用内请求,并按一套固定顺序排查「规则写了却不生效」。适合已经能从自己的服务商处拿到订阅、正在自己整理规则的人。
REJECT 在规则里是什么:一条出站策略
Shadowrocket 的规则行是类型,值,策略的三段式写法,策略段只有三种取值:PROXY(交给当前选中的服务器出站)、DIRECT(本地直连,不进代理)、REJECT(在本地拒绝或丢弃这条连接)。REJECT 不是 Settings 里的一个总开关,它只是某一条规则的动作,只有命中这条规则的连接才会被拦下来。
一条最小可用的屏蔽规则长这样:
DOMAIN-SUFFIX,ads.example.com,REJECT
DOMAIN-KEYWORD,metrics,REJECT
IP-CIDR,203.0.113.0/24,REJECT,no-resolve
FINAL,PROXY
规则写在当前 Config 文件里(Home → 当前配置 → 编辑),也可以在 Home 的规则列表中直接增删。改动后需要重新选中该 Config 才会参与匹配;更新订阅会重新拉取配置文件,本地手改的规则可能被覆盖,更新完建议复查一遍。
命中顺序:REJECT 什么时候才轮得到
每个新连接只做一次规则匹配:从列表第一行开始逐条比对,第一条匹配成功的规则决定这条连接的走向,后面的规则不再参与。REJECT 能不能生效,取决于它前面有没有更宽泛的规则先把这条连接领走。
顺序问题出在宽窄关系上。DOMAIN-KEYWORD,ads,REJECT 写在 DOMAIN-SUFFIX,ads.example.com,PROXY 前面,那么 ads.example.com 会先被 keyword 规则拦掉;反过来写,窄规则先命中,后面的 keyword 规则对这条连接就没有机会了。窄规则在前、宽规则在后,是规则列表的基本排法。
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
这六行是一副可用骨架:精确域名 → 域名后缀 → 关键字 → IP 段 → 地理归属 → 兜底,越具体的越靠前。
FINAL 是兜底规则,匹配所有未被前面命中的连接,必须放在最后一行;把它写在中间,等于给它后面的所有规则判了死刑。IP 类规则还有两个细节:带 no-resolve 表示这条规则不触发 DNS 解析,只在目标本身就是 IP 字面量时匹配;不带 no-resolve 的 IP-CIDR 会先把域名解析成 IP 再比对,解析结果不同就可能出现时灵时不灵。
FINAL不在最后一行,排在它后面的规则全部失效。DOMAIN-KEYWORD排在DOMAIN或DOMAIN-SUFFIX之前,把本该精确处理的域名一并拦掉。GEOIP,CN,DIRECT排在具体域名规则之前,国内域名全部直连,后面的规则轮不到。- 订阅自带的规则压在自己新增的规则前面,自建规则永远匹配不到。
拦截边界:HTTPS、应用内请求与域名前置
REJECT 生效在连接建立阶段:它在本地拒绝或丢弃连接,不参与 TLS 握手之后的数据交换。这决定了它的能力上限——它管的是「这条连接能不能通」,不是「页面里显示什么」。
边界一:HTTPS 只拦到连接层
对 https://ads.example.com/x.js 这样的请求,REJECT 拦掉的是到 ads.example.com:443 的连接,脚本自然拿不到。但如果推广内容与正文来自同一个域名(例如 example.com 下的一个接口),REJECT 就无能为力:拦掉整个域名,正文也会一起打不开。规则里没有按 URL 路径匹配的关键字,客户端看不到 HTTPS 请求的路径。
边界二:应用内请求与硬编码 IP
很多应用把上报地址写成 IP 字面量,或者从接口动态下发域名。前者域名规则匹配不到,需要 IP-CIDR 兜底;后者要等实际域名出现之后再补规则。按 IP 拦的代价是容易误伤——同一网段上往往还有正常服务,共享 CDN 的 IP 尤其如此。域名规则与 IP 规则是两条互补入口,分别对应下面两种发起方式:
DOMAIN-SUFFIX,ads.example.com,REJECT
IP-CIDR,203.0.113.0/24,REJECT,no-resolve
另一个细节是 QUIC。走 UDP 443 的连接同样会经过规则匹配,但如果你写的是带 no-resolve 的 IP-CIDR,而应用是以域名形式发起连接的,这条规则不会触发解析,也就匹配不到。
边界三:域名前置
域名前置(domain fronting)的做法是:TLS 握手里的 SNI 与请求实际指向的 Host 不一致,SNI 通常是一个「干净」的域名。Shadowrocket 按连接的目标域名(即 SNI)匹配规则,DOMAIN-SUFFIX 拦的是 SNI 上的那个域名。按 SNI 拦会连带影响同一入口上的正常服务;按 Host 拦截则不在客户端规则的处理范围内。
结论:REJECT 是名单式连接拦截,不是内容过滤器
按域名与 IP 匹配、在连接层生效,意味着它能挡住独立域名和独立 IP 上的请求;同域名下的推广接口、URL 路径级的内容、SNI 与 Host 不一致的流量,都不在它的处理范围内。按这个边界设预期,能省掉大量反复改规则的试错。
规则写了却不生效:按这个顺序排查
规则不生效,原因大多落在「当前生效的配置」和「匹配顺序」这两件事上。按下面的顺序逐项确认,比反复重写规则更快。
-
确认当前生效的 Config
回 Home 看顶部显示的配置名。规则写在 A 配置里、当前选中的是 B,规则自然不会参与匹配。
-
检查规则在列表中的位置
看有没有更靠前的宽规则先命中,尤其是 DOMAIN-KEYWORD 排在 DOMAIN-SUFFIX 之前的情况。
-
确认连接是域名还是 IP 发起
域名规则匹配不到 IP 直连;带 no-resolve 的 IP-CIDR 也不会为域名连接触发解析。
-
确认 Global Routing 姿态
停在 Proxy 或 Direct 时,规则列表不参与分流决策;回到 Config 才会按规则逐条匹配。
-
更新订阅后复查规则
订阅更新会重新拉取配置,本地手改的规则可能被覆盖;更新完回 Home 确认规则还在。
REJECT 只作用于经过 Shadowrocket 隧道的连接,也不解析传输内容。规则能改变的是连接走向,不是应用自身的行为。
关于 REJECT 的五个常见问题
加了 REJECT,同一个域名的正常页面也打不开了?
说明这个域名同时承载正文与被拦内容。REJECT 按域名整条拦,不能只拦其中一部分;把规则收窄到具体子域名,或改用 DOMAIN 精确匹配单条主机名。
REJECT 和 DIRECT 到底差在哪?
DIRECT 是放行,连接照常建立,只是不走代理;REJECT 是本地拒绝或丢弃,连接建立不起来。要「能连但不走代理」用 DIRECT,要「连不上」用 REJECT。
规则写在 Home 里,更新订阅后就没了?
订阅更新会重新拉取配置文件,本地手改的规则可能被覆盖。需要长期保留的规则,更新完回 Home 复查一遍,必要时重新加。
按 IP 拦了一整段,结果别的服务也挂了?
IP-CIDR 拦的是整个网段,共享 CDN 的 IP 上往往还有正常服务。优先用域名规则;确实要按 IP 处理时把网段切细,并带上 no-resolve 避免额外解析。
为什么被 REJECT 的连接在 Data 页看不到流量?
连接在建立阶段就结束了,没有实际传输量,按服务器与按应用统计的读数自然不会增长。判断规则是否命中,以 Home 里的当前配置与规则顺序为准。