规则列表是一份纯文本,一行一条,格式为「类型,值,策略」。本文把域名类(DOMAIN、DOMAIN-SUFFIX、DOMAIN-KEYWORD)、IP 类(GEOIP、IP-CIDR)与兜底(FINAL)逐个讲清匹配对象与命中顺序,并给出可以在 Config → Rules 里直接照抄的示例。适合已经导入订阅、想让流量按自己的意图分流的用户;读完能独立写出一份不互相打架的规则列表。
一条规则的三段结构
Shadowrocket 的规则列表是一份纯文本,保存在配置文件里,一行一条。每行用英文半角逗号切成三段:类型(TYPE)、值(VALUE)、策略(POLICY)。类型决定「拿什么去比」,值决定「比什么」,策略决定「命中之后怎么办」。
策略只有三种:PROXY 表示走当前选中的服务器,DIRECT 表示直连,REJECT 表示丢弃这条连接。以 # 开头的整行是注释,解析时跳过;空行同样忽略。写规则时用到的逗号必须是英文半角,中文逗号会让整行失效。
# 每行格式:类型 / 值 / 策略
DOMAIN-SUFFIX,example.com,PROXY
DOMAIN-KEYWORD,analytics,DIRECT
IP-CIDR,192.168.0.0/16,DIRECT,no-resolve
FINAL,DIRECT
三段里最容易出错的是值:域名类规则的值是主机名,IP 类规则的值是 CIDR 网段或两位国家/地区代码,端口类规则的值是数字。格式不对的行不会报错,只会被静默跳过——所以遇到「规则写了没反应」,先回头检查这一行的逗号与值格式,再去怀疑别的环节。
域名类:DOMAIN、DOMAIN-SUFFIX、DOMAIN-KEYWORD
域名类规则匹配的是请求里的主机名。HTTPS 请求的主机名通常来自 TLS 握手里的 SNI,HTTP 请求来自 Host 头,这两种信息在连接刚建立时就已经具备,不需要等待 DNS 解析,因此域名规则判断得最快,也最不受解析结果波动影响。三种常用写法的粒度依次放宽:
| 类型 | 匹配对象 | 写法示例 | 命中范围 |
|---|---|---|---|
DOMAIN | 完整主机名,一字不差 | DOMAIN,api.example.com,PROXY | 只命中 api.example.com;www.api.example.com 不命中 |
DOMAIN-SUFFIX | 域名后缀,含自身与全部子域 | DOMAIN-SUFFIX,example.com,PROXY | example.com、a.example.com、a.b.example.com 都命中 |
DOMAIN-KEYWORD | 主机名中任意位置出现的关键词 | DOMAIN-KEYWORD,analytics,DIRECT | analytics.example.com、cdn-analytics.example.net 都命中 |
DOMAIN-SET | 外置域名列表文件,每行一条域名 | DOMAIN-SET,example-domains.txt,DIRECT | 列表中写过的域名按该行策略执行 |
粒度越宽,误伤的概率越高。DOMAIN-KEYWORD,analytics,DIRECT 会命中主机名里任何位置出现 analytics 的请求,包括你并不想直连的站点;DOMAIN-SUFFIX,example.com,PROXY 则会连带把 mail.example.com、static.example.com 一起送进代理。写宽泛规则之前,先确认这个后缀下确实没有需要区别对待的子域。
选择写法时按下面的顺序判断:
- 只有单个主机名需要区别对待,用
DOMAIN,精确到字母; - 一个站点连同它的全部子域要一起处理,用
DOMAIN-SUFFIX; - 域名结构不固定、前缀随机的 CDN 或统计服务,才考虑
DOMAIN-KEYWORD; - 同类域名数量太多、会把主列表撑得过长,就把域名单独放进一个文本文件,用
DOMAIN-SET引用。
DOMAIN,www.example.com,DIRECT
DOMAIN-SUFFIX,example.com,PROXY
DOMAIN-KEYWORD,adservice,REJECT
DOMAIN-SET,example-domains.txt,DIRECT
IP 类:GEOIP 与 IP-CIDR 比的是解析后的地址
IP 类规则不看域名,只看连接目标的 IP 地址。要拿到 IP,系统必须先做一次 DNS 解析,所以 IP 规则比域名规则晚一步生效,而且会丢掉「域名」这个维度:同一个域名解析到不同地址时,命中结果可能跟着变化。
GEOIP 用两位国家/地区代码概括整段地址归属,GEOIP,CN,DIRECT 的含义是「目标是中国的 IP 就直连」。IP-CIDR 写精确网段,内网直连的常见写法是 IP-CIDR,192.168.0.0/16,DIRECT 与 IP-CIDR,10.0.0.0/8,DIRECT;IPv6 目标用 IP-CIDR6。按端口判断由 DST-PORT 与 SRC-PORT 承担,例如 DST-PORT,443,PROXY 表示目标端口是 443 的连接走代理。
GEOIP,CN,DIRECT
IP-CIDR,192.168.0.0/16,DIRECT,no-resolve
IP-CIDR,10.0.0.0/8,DIRECT,no-resolve
IP-CIDR6,fc00::/7,DIRECT,no-resolve
DST-PORT,443,PROXY
内网网段这类规则通常要在末尾补一个 no-resolve:它的作用是匹配这条规则时不要为了拿 IP 而触发 DNS 解析。少了这个参数,一个本来可以直接命中的请求会先被迫解析一次,既拖慢判断,也可能因为解析失败而落空。
结论:域名规则要写在 IP 规则前面
GEOIP 与 IP-CIDR 需要先拿到目标 IP。如果它们排在域名规则之前,一个本可被 DOMAIN-SUFFIX 精确命中的请求会先被迫解析,命中结果取决于当时解析到哪个地址。把域名类放前、IP 类放后,顺序才稳定。
命中顺序:自上而下,首条命中即停
Shadowrocket 从规则列表的第一行开始逐条比对,某一行命中后立即执行该行的策略,后面的规则不再参与判断。这条机制决定了排序原则:越具体、越需要优先处理的规则写在越上面,越宽泛的规则写在越下面。
FINAL 是一条只有策略、不需要匹配值的兜底规则,用来承接前面全部没有命中的请求:FINAL,DIRECT 让未命中的流量直连,FINAL,PROXY 让未命中的流量走代理。它必须放在列表最后一行——写在 FINAL 之后的规则不会被执行。
# 1. 内网与保留地址先直连
IP-CIDR,192.168.0.0/16,DIRECT,no-resolve
# 2. 明确要拦截的域名
DOMAIN-SUFFIX,ads.example.com,REJECT
# 3. 明确要走代理的域名
DOMAIN-SUFFIX,example.com,PROXY
# 4. 国内地址直连
GEOIP,CN,DIRECT
# 5. 兜底
FINAL,PROXY
排序时可以按下面五层从上往下摆:
- 第一层:内网与保留网段,如
IP-CIDR,192.168.0.0/16,DIRECT,no-resolve,放在最前面; - 第二层:明确要丢弃的域名,
REJECT必须写在同一域名的PROXY之前,拦截才有机会生效; - 第三层:明确要走代理或直连的域名,
DOMAIN在DOMAIN-SUFFIX之上; - 第四层:按地址归属判断的
GEOIP,以及按端口判断的DST-PORT; - 第五层:
FINAL,兜底并保持最后一行。
让规则生效:Global Routing 与配置文件
规则列表只在 Global Routing 处于 Config 姿态时才参与判断。姿态在 Settings → Global Routing 里切换,三个常用选项的差别是:
配置(Config)
推荐按配置文件里的规则列表逐条匹配:命中 PROXY 走代理,命中 DIRECT 直连,命中 REJECT 丢弃。
适合:日常主力,想让规则真正起作用
代理(Proxy)
忽略规则列表,所有连接一律走当前选中的服务器。
适合:临时全量代理、排查规则问题
直连(Direct)
忽略规则列表与服务器,所有连接直接发出。
适合:确认某个现象是否由代理引入
另一个前提是「改对了文件」。Config 标签里可能同时存在多份配置,只有当前选中(带勾)的那一份会被使用。编辑入口是 Config → 选中正在使用的配置文件 → Rules,列表按行展示,右上角「+」新增一行,点任意一行可以修改类型、值与策略。完整流程如下:
确认姿态
Settings → Global Routing 选 Config,否则规则列表不参与判断。
打开 Config
底部标签切到 Config,确认带勾的正是你在用的那份配置文件。
进入 Rules
点进配置文件,找到 Rules 一行,里面就是完整的规则列表。
插入新行
右上角「+」新增规则,按「类型,值,策略」三段填写,逗号用英文半角。
调整顺序
把具体规则移到宽泛规则之前,FINAL 保持在最后一行。
保存并重连
保存后回到 Home 断开再连接一次,让新的规则列表生效。
结论:先定姿态,再谈规则
规则写了不生效时,先确认 Global Routing 是否停在 Config、当前选中的是不是你改的那份配置文件,再去检查规则顺序与写法。顺序反过来查,通常会在写法上白折腾很久。
四个高频问题
下面四个问题覆盖了规则类反馈里最常见的场景,排查路径都是从「姿态 → 配置文件 → 规则顺序 → 规则写法」逐层往下。
加了 DOMAIN-SUFFIX,example.com,PROXY,这个域名还是直连?
先看列表里有没有更靠前的规则先命中——例如写在域名规则之前的 GEOIP,CN,DIRECT,或者一条宽泛的 DOMAIN-KEYWORD。再确认 Global Routing 停在 Config、当前选中的正是你编辑的那份配置,最后断开重连一次。
GEOIP,CN,DIRECT 为什么没让国内站点直连?
GEOIP 匹配的是解析后的 IP,不是域名。如果它写在域名规则之前、或者目标解析到的地址不在 CN 段内,这条规则就不会命中。把它放到域名规则之后、FINAL 之前,再重连一次观察。
IP-CIDR 规则为什么不匹配我写的域名?
IP-CIDR 只比对 IP 地址,不认域名。要按域名分流就用 DOMAIN-SUFFIX;要按网段分流,就确认目标解析到的地址确实落在你写的 CIDR 里。写内网网段时记得带上 no-resolve。
REJECT 写了,某些请求还是发出去了?
规则自上而下匹配、首条命中即停。如果 REJECT 上面已经有一条 PROXY 或 DIRECT 命中了同一个目标,请求就走不到这一行。把 REJECT 提到对应域名规则之前再试。