分流规则
在 route-mode = "rule" 下,每条连接按 [rule].list 自上而下匹配,第一条命中的规则决定连接去向。 列表必须以 FINAL 结尾。
[rule]
list = [
"DOMAIN-SUFFIX,corp.example.com,office",
"PROCESS-NAME,cargo,work",
"IP-CIDR,10.0.0.0/8,DIRECT,no-resolve",
"FINAL,DIRECT",
]语法
类型,匹配值,出口
类型,匹配值,出口,no-resolve
FINAL,出口类型不区分大小写。MATCH是FINAL的另一个名字。匹配值不能包含逗号。出口是DIRECT、REJECT、某个[[proxy]]的name或某个[[proxy-group]]的name, 区分大小写。FINAL必须是最后一条,且只能有一条。- 含反斜杠的规则(例如正则表达式)必须用 TOML 单引号:
'DOMAIN-REGEX,^ci-[0-9]+\.example\.com$,work'。 在双引号中\.是非法转义,整个文件都会加载失败。 no-resolve是唯一的选项。用在 IP 规则上表示:不为了测试这条规则去解析域名,只匹配目标本身 就是 IP 的连接。
规则类型
域名
| 类型 | 匹配 | 示例 |
|---|---|---|
DOMAIN | 完全相同的域名 | DOMAIN,api.github.com,work |
DOMAIN-SUFFIX | 该域名及所有子域名 | DOMAIN-SUFFIX,github.com,work |
DOMAIN-KEYWORD | 包含该文本的域名 | DOMAIN-KEYWORD,tracker,REJECT |
DOMAIN-WILDCARD | * 和 ? 通配 | DOMAIN-WILDCARD,*.cdn.example.com,DIRECT |
DOMAIN-REGEX | 正则表达式 | DOMAIN-REGEX,^ci-[0-9]+\.example\.com$,work |
GEOSITE | GeoSite 文件中的分类 | GEOSITE,github,work |
IP
| 类型 | 匹配 | 示例 |
|---|---|---|
IP-CIDR | IPv4 网段 | IP-CIDR,10.0.0.0/8,DIRECT,no-resolve |
IP-CIDR6 | IPv6 网段 | IP-CIDR6,fd00::/8,DIRECT,no-resolve |
GEOIP | GeoIP 文件中的国家或分类 | GEOIP,private,DIRECT,no-resolve |
IP-ASN | 自治系统号 | IP-ASN,13335,DIRECT |
连接
| 类型 | 匹配 | 示例 |
|---|---|---|
DST-PORT | 目标端口或范围 a-b | DST-PORT,22,DIRECT |
NETWORK | TCP 或 UDP | NETWORK,UDP,DIRECT |
进程
进程规则需要知道连接是哪个程序发起的。在 Linux 上由 eBPF 增强模式提供;经本地 HTTP/SOCKS5 端口进入的连接,只有平台能提供时才带有进程信息。
| 类型 | 匹配 | 示例 |
|---|---|---|
PROCESS-NAME | 进程名;支持 * 和 ? | PROCESS-NAME,cargo,work |
PROCESS-PATH | 可执行文件绝对路径;支持 * 和 ? | PROCESS-PATH,/usr/bin/git,work |
PROCESS-NAME-REGEX | 进程名,正则表达式 | PROCESS-NAME-REGEX,^python3(\.[0-9]+)?$,work |
PROCESS-PATH-REGEX | 可执行文件路径,正则表达式 | PROCESS-PATH-REGEX,^/opt/tools/,work |
在 Linux 上,进程名是内核 comm,最多 15 个字符:git-remote-https 会显示为 git-remote-http。 名称匹配区分大小写。实际例子见《开发工具分流规则配方》。
规则集
| 类型 | 匹配 | 示例 |
|---|---|---|
RULE-SET | 指定规则集中的任意一项 | RULE-SET,ads,REJECT |
见下文规则集。
AND、OR、NOT、SUB-RULE 能被识别,但它们的匹配值需要逗号,而规则语法不允许逗号,因此不能在 [rule].list 中使用。
顺序
首条命中生效,所以把范围窄的规则放在范围宽的规则前面:
[rule]
list = [
"DOMAIN,status.corp.example.com,DIRECT", # 先写例外
"DOMAIN-SUFFIX,corp.example.com,office", # 再写一般情况
"FINAL,DIRECT",
]规则多了之后,一种好读的排列:拦截(REJECT)、进程名、域名、网段、规则集,最后 FINAL。
GeoIP 与 GeoSite
GEOIP 和 GEOSITE 读取 V2Ray 格式的数据文件(geoip.dat、geosite.dat,由 v2fly、Loyalsoldier 等发布)。用 [rule.cache] 告诉 Specola 文件位置:
[rule]
list = [
"GEOIP,private,DIRECT,no-resolve",
"GEOSITE,github,work",
"FINAL,DIRECT",
]
[rule.cache]
geoip = "/home/me/.local/share/specola/geoip.dat"
geosite = "/home/me/.local/share/specola/geosite.dat"没有设置文件时,校验会报 GEOIP rule requires a geoip resource。分类名不区分大小写。请使用绝对路径。
IP-ASN 需要在 [rule.cache] asn = "<路径>" 指定文本目录文件,每行一个 AS<编号>,<网段>。
规则集
规则集是一个有名字的规则列表,存在本地文件或远程下载,通过 RULE-SET 使用。在 [rule.cache] 下声明:
[rule]
list = [
"RULE-SET,ads,REJECT",
"RULE-SET,internal,office",
"FINAL,DIRECT",
]
[[rule.cache.rule-set]]
name = "ads"
behavior = "domain"
url = "https://lists.example.com/ads.txt"
[[rule.cache.rule-set]]
name = "internal"
behavior = "classical"
path = "/home/me/.config/specola/internal-rules.txt"| 字段 | 说明 |
|---|---|
name | 必填;作为 RULE-SET 的匹配值 |
path | 本地文件;与 url 同时使用时为下载后的保存位置 |
url | 下载地址;每次加载配置时都会下载 |
behavior | classical(默认)、domain 或 ipcidr |
proxy | 通过这个 [[proxy]] 下载 |
文件格式为每行一项;空行以及 #、// 开头的行会被跳过:
behavior | 每行格式 |
|---|---|
classical | 不带出口的 类型,匹配值,例如 DOMAIN-SUFFIX,example.com |
domain | example.com(后缀匹配),或加前缀 full:、domain:、keyword:、regexp: |
ipcidr | 10.0.0.0/8 或 fd00::/8 |
出口总是来自使用该规则集的那条 RULE-SET 规则。
排错
| 报错 | 原因 |
|---|---|
Rule must use TYPE,payload,target or FINAL,target | 逗号数量不对,常见于匹配值中含逗号 |
Unsupported rule type | 类型拼错 |
Rule references unknown outbound: X | X 不是 DIRECT、REJECT、代理或代理组;检查大小写 |
FINAL must be the last rule | 把 FINAL 移到最后 |
Rule list requires an explicit FINAL target | 加上 "FINAL,<出口>" |
RULE-SET references unknown cache: X | 没有 name = "X" 的 [[rule.cache.rule-set]] |
如果增强模式接管的流量匹配不到域名规则,通常是应用自己解析了域名,见 DNS。