www.apple.com
主机名以 .apple.com 结尾,命中第一行,DIRECT。不会问 github,也不会问 GEOIP。Data 应见 Direct 增加。这与「Apple 在不在中国」无关,只与这一行写成了什么有关。
规则
规则文件只在全局策略为 Config 时被询问。Proxy 与 Direct 会跳过整份文件。首页的试纸用一份示意名单匹配域名,和设备上正在用的文件不是同一份。
01
可以写得再完整的规则,只要策略停在 Proxy,出站仍一律进当前记录;停在 Direct,则一律原路径。文件不会「自己打开」。把策略改回 Config 之后,当前选中的那一份配置才开始逐条匹配。策略三项的含义见 隧道。
配置文件可以有多份。连接时只使用当前选中的一份。服务器记录是另一套对象:换高亮行不会换文件,换文件也不会换高亮行。一份配置里写了什么名单,与列表里此刻高亮哪一条出口,是两件独立的事。见 对象 与 配置。
因此「规则没生效」有两种完全不同的意思。一种是引擎根本没被问到(策略不是 Config,或选中的不是你以为的那份文件)。另一种是引擎问到了,但先命中的那一行不是你以为的那一行。对照时先确认前者,再改后者。
产品页上的域名试纸用一份写死的示意名单。它只演示「自上而下、先命中的一行生效」。GEOIP 在网页上模拟不了。把试纸的结果当成自己手机上的分流,会得到错误结论。
02
常见写法是:条件类型,参数,动作。用逗号分隔。类型与参数决定「这行管谁」,动作决定「管到了之后怎么办」。行首以 # 开头的是注释,引擎跳过,不会参与匹配。
# 注释不会被匹配 DOMAIN,api.example.com,PROXY DOMAIN-SUFFIX,example.com,DIRECT IP-CIDR,10.0.0.0/8,DIRECT GEOIP,CN,DIRECT FINAL,PROXY
动作只有三种会真正改变出站:DIRECT(原路径)、PROXY(当前高亮的记录)、REJECT(拦截,不发出)。有的文件会写成策略组名,那是把动作指向另一套选择逻辑;本页只讨论这三种直接动作。类型选错、逗号写少、把 URI 整段贴进规则行,这一行通常不会按你期望工作,请求会继续往下掉。
同一文件里可以混用域名条件与地址条件。引擎对每一条连接只走一遍名单,不会「域名命中一次、IP 再命中一次然后取并集」。先命中的那一行已经给出动作,后面的行不再看。
03
匹配自上而下。某一行命中之后,后面的行不再看。所以例外必须写在通例之前。把 FINAL 放在文件中间,等于下面所有行作废——它们还在文件里,但永远不会被问到。
下面两份名单的行完全相同,只是顺序对调,结果相反。
# A:先点名主机,再写后缀 DOMAIN,api.example.com,PROXY DOMAIN-SUFFIX,example.com,DIRECT FINAL,PROXY # B:先写后缀,api 那一行永远走不到 DOMAIN-SUFFIX,example.com,DIRECT DOMAIN,api.example.com,PROXY FINAL,PROXY
对 api.example.com:名单 A 命中第一行,走记录;名单 B 命中后缀,走直连。对 www.example.com:两份都会在后缀处走直连。对 unrelated.org:两份都落到 FINAL,走记录。
KEYWORD 比 SUFFIX 更宽,GEOIP 比大多数域名行更宽,FINAL 最宽。一个稳妥的顺序是:具体主机 → 后缀 / 关键字 → 网段 → GEOIP → FINAL。这不是语法要求,是为了让例外有机会被看见。
04
DOMAIN,example.com,PROXY 匹配 example.com,不匹配 www.example.com,也不匹配 api.example.com。需要管一个精确名字时用它,不要用它冒充后缀。apple.com 匹配 apple.com 与 www.apple.com、icloud.com 不在其内。不匹配 notapple.com:后者只是以 apple.com 这串字符结尾,中间没有那一个点。KEYWORD,google 会打到 google.com,也会打到 googlevideo.com、以及任何名字里夹了 google 的主机。范围最大,也最容易误伤。能改成后缀时不要用它。后缀行不会自动覆盖子域的子域以外的名字。写了 DOMAIN-SUFFIX,google.com,PROXY 并不等于管到了 gstatic.com、youtube.com、googleapis.com。那些是不同的注册域,要各自写,或接受它们落到更后面的 GEOIP / FINAL。
大小写按域名惯例视为不敏感。国际域名若以 Unicode 出现在规则里、实际请求却是 punycode(xn--),两边对不上,这一行不会命中。对照时以规则文件里实际写下的字节为准。
05
10.0.0.0/8、172.16.0.0/12、192.168.0.0/16 常被写成 DIRECT,避免局域网进出隧道。只写这一条时,IPv6 目的地址不会命中,请求继续往下掉。GEOIP,CN,DIRECT 的意思是:这个目的地址被库标成 CN 时走直连。库版本在设备上,网页试纸模拟不了。CDN 把同一主机名指到不同国家的地址时,GEOIP 的结果会跟着变。部分 IP 行带 no-resolve 一类标注,表示不要为了匹配这一行去把域名解析成地址。解析策略还会和 解析 页里的 DNS 设置互相影响:规则若只能看见主机名、看不见地址,地址行全部落空;只能看见地址、看不见主机名,则域名行全部落空。
06
这条连接从系统原路径离开,不经过当前记录。Data 的 Direct 累加器会动。隧道可以仍显示已连接。
这条连接发给当前高亮的记录。Data 的 Proxy 累加器会动。记录握手失败时,动作仍然是 PROXY,只是对端没有把字节送出去。
不发出。应用侧通常表现为连接失败或超时,而不是「打开了但内容是空的」。REJECT 不会让 Data 像一次成功访问那样明显增加。
把本该直连的系统服务写成 PROXY,常见后果是推送、照片同步、商店更新变慢或失败,因为它们被送进了一条并不为它们准备的出口。把本该进记录的主机写成 DIRECT,则 Data 只见 Direct 增加,网页表现得像「没开代理」。把主机写成 REJECT,应用会报网络错误,容易被误判成节点坏了。
改动作之前先确认这一行真的会被命中。改了一行从未被走到的规则,屏幕上不会有任何变化。用 读数 看计数站在哪一侧,比反复开关更有效。
07
域名条件依据解析结果、HTTP 的 Host、或 TLS 的 Server Name Indication。应用如果直接连接 IP、或不带 SNI,规则可能只能看到地址,于是域名行全部落空,最后打在 IP-CIDR、GEOIP 或 FINAL 上。
这就是「同一网站,有时走代理有时走直连」的一种来源:有的请求带主机名,有的只剩 IP。浏览器地址栏显示 www.example.com,底层却可能先连 CDN 的地址;GEOIP 看到的是那台 CDN 的所在库,不是你对这个名字的印象。
系统 DNS 与应用内 DNS 各设一套且互相矛盾时,规则看到的主机名和真实目的地址会对不上。解析没有异常时,不必同时改两处。详见 解析。
改写 发生在请求已经被看见之后,不能代替规则决定走哪条路。先分流,再改写。HTTPS 内容级的改写还要额外的解密授权,见 系统。
08
假设当前策略为 Config,文件如下,当前高亮一条可用的记录:
DOMAIN-SUFFIX,apple.com,DIRECT DOMAIN-SUFFIX,icloud.com,DIRECT DOMAIN-SUFFIX,github.com,PROXY IP-CIDR,10.0.0.0/8,DIRECT GEOIP,CN,DIRECT FINAL,PROXY
主机名以 .apple.com 结尾,命中第一行,DIRECT。不会问 github,也不会问 GEOIP。Data 应见 Direct 增加。这与「Apple 在不在中国」无关,只与这一行写成了什么有关。
前两行不匹配,第三行命中,PROXY。GEOIP 写在后面,即使这个地址被库标成某个国家,也不会再被问到。Data 应见 Proxy 增加。若这里 Proxy 不动、网页失败,先查记录而不是再加一条 github 规则。
所有域名行落空,命中 IP-CIDR,DIRECT。若同一台服务有时用名字、有时用地址,你会看到两条完全不同的动作。这不是引擎随机,是两次请求带给引擎的信息不一样。
域名行都不中,网段不中,GEOIP,CN 命中,DIRECT。若库把这个地址标成别的国家,则落到 FINAL,PROXY。换一次解析、换一个 CDN 节点,同一名字可以在这两行之间跳动。
09
应用允许保存多份配置,连接时只跑当前选中的一份。从一份切到另一份,等于整份名单替换,不是「两条 FINAL 叠在一起」。导入别人的列表之前,先找到它的 FINAL 和 GEOIP:这两行决定了大多数未点名流量的命运。
若你的记录本身在国内、只想让少数主机走记录,FINAL 写成 PROXY 会把大量无关请求送进节点。若记录在境外、希望未点名的都走记录,FINAL 写成 DIRECT 则多数网站根本不会进节点。外来列表的作者按他自己的出口在写,不是按你的出口在写。
列表会过期。订阅型规则的刷新与服务器容器的刷新是不同对象上的同一类动作:保存的是 URL,拉取成功才替换本地文件,失败时保留上一次成功的文件,不会为了失败把规则抹空。刷新走当时的网络路径,开关正连着一条已失效的记录时,规则订阅本身也可能刷新失败。见 对象 与 配置。
一次只改一个条件。改完用固定的一条记录、只切换策略做对照,见 读数。同时换记录、换文件、改 FINAL,屏幕上的变化无法归因。