REJECT 只決定一條連線放不放行,不解析傳輸內容。讀完你能分清 REJECT 與 PROXY、DIRECT 在規則列表裡的位置關係,知道它為什麼攔不住同網域下的推廣 API 與硬編碼 IP 的 App 內請求,並照一套固定順序排查「規則寫了卻不生效」。適合已經能從自己的服務商取得訂閱、正在自己整理規則的人。
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、App 內請求與網域前置
REJECT 生效在連線建立階段:它在本機拒絕或丟棄連線,不參與 TLS 握手之後的資料交換。這決定了它的能力上限——它管的是「這條連線能不能通」,不是「頁面裡顯示什麼」。
邊界一:HTTPS 只攔到連線層
對 https://ads.example.com/x.js 這樣的請求,REJECT 攔掉的是到 ads.example.com:443 的連線,腳本自然拿不到。但如果推廣內容與正文來自同一個網域(例如 example.com 下的一個 API),REJECT 就無能為力:攔掉整個網域,正文也會一起打不開。規則裡沒有按 URL 路徑匹配的關鍵字,用戶端看不到 HTTPS 請求的路徑。
邊界二:App 內請求與硬編碼 IP
很多 App 把回報位址寫成 IP 字面值,或者從 API 動態下發網域。前者網域規則匹配不到,需要 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,而 App 是以網域形式發起連線的,這條規則不會觸發解析,也就匹配不到。
邊界三:網域前置
網域前置(domain fronting)的做法是:TLS 握手裡的 SNI 與請求實際指向的 Host 不一致,SNI 通常是一個「乾淨」的網域。Shadowrocket 按連線的目標網域(即 SNI)匹配規則,DOMAIN-SUFFIX 攔的是 SNI 上的那個網域。按 SNI 攔會連帶影響同一入口上的正常服務;按 Host 攔截則不在用戶端規則的處理範圍內。
結論:REJECT 是名單式連線攔截,不是內容過濾器
按網域與 IP 匹配、在連線層生效,意味著它能擋住獨立網域和獨立 IP 上的請求;同網域下的推廣 API、URL 路徑層級的內容、SNI 與 Host 不一致的流量,都不在它的處理範圍內。按這個邊界設預期,能省掉大量反覆改規則的試錯。
規則寫了卻不生效:按這個順序排查
規則不生效,原因大多落在「目前生效的 Config」和「匹配順序」這兩件事上。照下面的順序逐項確認,比反覆重寫規則更快。
-
確認目前生效的 Config
回 Home 看頂端顯示的 Config 名稱。規則寫在 A、目前選取的卻是 B,規則自然不會參與匹配。
-
檢查規則在列表中的位置
看有沒有更靠前的寬規則先命中,尤其是 DOMAIN-KEYWORD 排在 DOMAIN-SUFFIX 之前的情況。
-
確認連線是網域還是 IP 發起
網域規則匹配不到 IP 直連;帶 no-resolve 的 IP-CIDR 也不會為網域連線觸發解析。
-
確認 Global Routing 的狀態
停在 Proxy 或 Direct 時,規則列表不參與分流決策;回到 Config 才會按規則逐條匹配。
-
更新訂閱後複查規則
訂閱更新會重新拉取設定,本機手改的規則可能被覆蓋;更新完回 Home 確認規則還在。
REJECT 只作用於經過 Shadowrocket 隧道的連線,也不解析傳輸內容。規則能改變的是連線走向,不是 App 自身的行為。
關於 REJECT 的五個常見問題
加了 REJECT,同一個網域的正常頁面也打不開了?
說明這個網域同時承載正文與被攔內容。REJECT 按網域整條攔,不能只攔其中一部分;把規則收窄到具體子網域,或改用 DOMAIN 精確匹配單一主機名稱。
REJECT 和 DIRECT 到底差在哪?
DIRECT 是放行,連線照常建立,只是不走代理;REJECT 是在本機拒絕或丟棄,連線建立不起來。要「能連但不走代理」用 DIRECT,要「連不上」用 REJECT。
規則寫在 Home 裡,更新訂閱後就沒了?
訂閱更新會重新拉取設定檔,本機手改的規則可能被覆蓋。需要長期保留的規則,更新完回 Home 複查一遍,必要時重新加入。
按 IP 攔了一整段,結果別的服務也掛了?
IP-CIDR 攔的是整個網段,共用 CDN 的 IP 上往往還有正常服務。優先使用網域規則;確實要按 IP 處理時把網段切細,並帶上 no-resolve 避免額外解析。
為什麼被 REJECT 的連線在 Data 頁看不到流量?
連線在建立階段就結束了,沒有實際傳輸量,按伺服器與按 App 統計的讀數自然不會成長。判斷規則是否命中,以 Home 裡的目前 Config 與規則順序為準。