顺便插一句,其实用了始皇的 oaifree 后我就很少访问 OpenAI 官网了,也就偶尔上去看看我的api使用额度。不过配置分流规则也不止适用于 ChatGPT,方法都是通用的,比如我也给 Claude 配置了一下,最近虽然现在有了 fuclaude,但也要每隔十天上官网去拿一次session key。
使用到的软件:clash verge rev,版本 v1.6.6,即大更新前的最后一个版本,可以使用多个全局配置文件,个人觉得比较方便。
下载地址:Release Clash Verge Rev v1.6.6 · clash-verge-rev/clash-verge-rev · GitHub
了解 Clash 配置文件中的规则的写法
首先,简单科普一下 Clash 系列软件配置文件的写法,
来,上官方文档:配置 - 虚空终端 Docs
文档内容很多,不过不用慌,咱们需要啥就看啥,当字典查就行。
咱们的主要目的是给我们需要的访问的网站单独配置规则,比如 OpenAI 的网站让它访问时美国节点(实际上,日本新加坡也可以,为了叙述方便后面就都说美国),Claude也用美国节点。那么我们就主要看规则部分的文档:路由规则 - 虚空终端 Docs 。
感觉还是很多?那我们就主要看 DOMAIN, DOMAIN-SUFFIX这两个,后面主要就用这些。内容也不多,我直接搬过来好了。
DOMAIN 匹配完整域名
DOMAIN-SUFFIX 匹配域名后缀
再放两个带例子的讲解(Rules 规则 | Clash 知识库 ):
DOMAIN 域名
DOMAIN,www.google.com,policy 将 www.google.com 路由到 policy.DOMAIN-SUFFIX 域名后缀
DOMAIN-SUFFIX,youtube.com,policy 将任何以 youtube.com 结尾的域名路由到 policy.在这种情况下, www.youtube.com 和 foo.bar.youtube.com 都将路由到 policy.
那我们现在就会写规则了,比如想给 ChatGPT 配置一个特定的规则,就写 DOMAIN,www.chatgpt.com,policy
就行了,是不是还挺简单的。但这个 policy 又是什么?
翻文档太慢了,反正我们现在大概知道规则怎么写了,不如直接去看看我们自己用的机场的配置文件,说不定就能找到 DOMAIN,www.chatgpt.com,policy
这样的格式。
于是打开配置文件
搜索一下 DOMAIN-SUFFIX,发现搜索结果还挺多的
于是我们看到填在 policy 的位置是叫 “节点选择” 的东西,还是不知道是干啥的,那么我们可以再搜索这个“节点选择”。
我们找到“节点选择”第一次出现的位置
再往上看看,proxies后面的那些是一个个位于不同地区的节点,这个我们认识。
再翻一翻,看到上面出现的“香港节点”
proxy-groups,意思是代理组,看了上面这三段配置文件内容,完全不用借助文档,我们大概就可以推测出,“节点选择”是一个代理组的名称,这个代理组可以由一个个具体的节点构成(第2、3张图),也可以由其他代理组(如“香港节点”)构成(第1张图),proxies后面就是这个代理组的构成元素。
现在,我们就可以回答上面的问题了,policy这个地方应该怎么写?policy这里应该填的是代理组的名称(name)。
所以,我们现在就可以,在图中的这些规则中,插入一条我们自己定义的规则
比如:DOMAIN,www.chatgpt.com,🇺🇸 美国节点
不过,别忘了文档(路由规则 - 虚空终端 Docs )最开始的那句话
所以我们一般把自定义的规则放在开头,优先级更高。
Merge 和 Script 配置文件
这样,我们就学会了在机场配置文件中添加自己的规则了,但是有一个问题:机场的配置文件每隔一段时间就会自动更新,那么我们自己添加的规则就被覆盖了。
这时,Merge配置文件和 Script配置文件就发挥作用了。Merge,合并,顾名思义,Merge配置文件需要与你自己机场的配置文件共同起作用。具体的,文档(扩展配置/脚本 - Clash Verge Rev Docs )是这样说的:
根据文件类型,扩展可分为
配置
和脚本
。配置
使用yaml
对配置进行覆写/合并,脚本
使用javascript
对配置进行更加灵活的调整。
还是来实践一下。
创建好并打开 Merge 文件,可以看到了里面已经有了一些内容:
append学过编程的大家应该很容易猜到,意思就是在后面添加东西,比如
StringBuilder sb = new StringBuilder("Hello ");
sb.append("World!");
System.out.println(sb.toString()); // 输出: Hello World!
prepend自然就是在前面添加东西。
rules, proxies, proxy-groups,这些都是在机场的配置文件里出现过的,那么根据上面讲的Merge的作用,大概也可以猜到,我们要添加自定义规则,那肯定是在 append/prepend-rules 里添加了。
前面讲过,一般把自定义的规则放在开头,优先级更高,最终,我们就知道了是添加在 prepend-rules 这里。
后面具体怎样添加就留给读者自己完成吧。或许还会踩一些小坑,不过使用AI大模型也可以辅助完成了。
Script 配置文件是使用 JavaScript 脚本对原有的机场配置文件进行修改,实现的功能和 Merge 差不太多,但更加灵活,其实我也没有系统学过 JavaScript ,我都是直接跟gpt说需求,来让它帮我写 Script配置,所以我也不打算在这里展开讲怎样写 script。我感觉只要大致的原理弄懂了,这些细节可以让AI帮我们去完成。
编写具体的分流规则
编写完 Merge 和 Script 配置并启用后,我们会发现还是不能正常访问 ChatGPT,其实登录的过程中我们就可以发现,实际上网址会跳转,比如跳转到 https://auth0.openai.com/ 。所以我们不止需要配置一个域名。具体需要配置哪些域名呢?参照:ios_rule_script/rule/Clash/OpenAI/OpenAI.list at master · blackmatrix7/ios_rule_script · GitHub
OpenAI更新了怎么办?引入RULE-SET
参照上面的链接,我们编写了 Merge 或 Script 配置文件并正常使用了一段时间,但是过段时间后发现,又没法正常访问 ChatGPT 了,这是怎么回事呢?原来是因为 ChatGPT 新加了几个网址,我们再回头去看 ios_rule_script/rule/Clash/OpenAI/OpenAI.list at master · blackmatrix7/ios_rule_script · GitHub ,发现这里面的域名也确实变多了(以上是我个人的真实经历)。
这时,就该引入 RULE-SET 了。RULE-SET就是规则集,简单来说,就是把上一张图中的那些域名规则全部放到一个文件里,我们不需要再手动复制这些域名规则到自己的Merge 或 Script 配置文件中了,而只需要配置这个规则集合(即那个文件的地址)即可。这样,GitHub仓库中的OpenAI.list更新了,我们实际使用到的规则也会更新。
那么下面就来看看怎么用 RULE-SET。
写到这有点累了,大家就自己看文档吧()
ios_rule_script/rule/Clash/OpenAI/README.md at master · blackmatrix7/ios_rule_script · GitHub
GitHub - Loyalsoldier/clash-rules: 🦄️ 🎃 👻 Clash Premium 规则集(RULE-SET),兼容 ClashX Pro、Clash for Windows 等基于 Clash Premium 内核的客户端。
https://wiki.metacubex.one/config/rule-providers/
规则集合内容 - 虚空终端 Docs
顺便放一下我看完文档后写的
rule-providers:
OpenAI:
type: http
behavior: "classical"
url: "https://raw.githubusercontent.com/blackmatrix7/ios_rule_script/master/rule/Clash/OpenAI/OpenAI.yaml"
path: ./ruleset/OpenAI.yaml
interval: 86400
rules:
- RULE-SET,OpenAI,myGPT
本文提到的内容基本上都是我在进入L站后在站内佬友们的提点下,结合自己看文档和借助GPT,逐步学习到的,既算是记录自己的学习历程,也算是回馈新入站的就像和当初啥也不懂的自己一样的小白(顺便骗点赞,维持三级 )。
附录 自用 Script
最后再附上我自己在用的 Script 配置吧
// Define main function (script entry)
function main(params) {
const USGroupName = addProxyGroup(params, "🇺🇲 美国节点", /美国|US|United States|America|🇺🇸/);
const JPGroupName = addProxyGroup(params, "🇯🇵 日本节点", /日本|JP|Japan|🇯🇵/);
const SGGroupName = addProxyGroup(params, "🇸🇬 新加坡节点", /新加坡|狮城|SG|Singapore|🇸🇬/);
const HKGroupName = addProxyGroup(params, "🇭🇰 香港节点", /香港|HK|Hong Kong|HongKong|🇭🇰/);
addGPTProxyGroup(params, USGroupName, JPGroupName, SGGroupName, HKGroupName);
// 添加规则
addRules(params, USGroupName, JPGroupName, SGGroupName, HKGroupName);
// 添加 rule-providers
addRuleProviders(params);
return params;
}
function addProxyGroup(params, groupName, regex) {
// 判断是否已经存在某个代理组(如"美国节点")的名称
const group = params["proxy-groups"].find((e) => regex.test(e.name) || e.name === groupName);
if (group === undefined) {
const proxiesByRegex = params.proxies.filter((e) => regex.test(e.name)).map((e) => e.name);
// 判断proxiesByRegex是否为空数组
if (proxiesByRegex.length === 0) {
return null; // 没有匹配的代理,直接返回
}
params["proxy-groups"].push({
name: groupName,
type: "url-test",
url: "http://www.gstatic.com/generate_204",
interval: 86400,
proxies: proxiesByRegex,
});
return groupName; // 没有的话就创建一个新的代理组
}
// 有了的话直接返回这个代理组的名称
return group.name;
}
function addGPTProxyGroup(params, USGroupName, JPGroupName, SGGroupName, HKGroupName){
// 创建一个名为"myGPT"的代理组
params["proxy-groups"].push({
name: "myGPT",
type: "select",
proxies: [],
});
// 找到新创建的代理组
const myGPTGroup = params["proxy-groups"].find(group => group.name === "myGPT");
// 为名为myGPT的代理组添加代理
if (HKGroupName !== null)
myGPTGroup.proxies.push(HKGroupName);
if (SGGroupName !== null)
myGPTGroup.proxies.push(SGGroupName);
if (JPGroupName !== null)
myGPTGroup.proxies.push(JPGroupName);
if (USGroupName !== null)
myGPTGroup.proxies.push(USGroupName);
}
function addRuleProviders(params) {
// 如果 params 中没有 rule-providers,则创建它
if (!params["rule-providers"]) {
params["rule-providers"] = {};
}
// 添加 OpenAI rule provider
params["rule-providers"]["OpenAI"] = {
type: "http",
behavior: "classical",
url: "https://raw.githubusercontent.com/blackmatrix7/ios_rule_script/master/rule/Clash/OpenAI/OpenAI.yaml",
path: "./ruleset/OpenAI.yaml",
interval: 86400
};
}
function addRules(params, USGroupName, JPGroupName, SGGroupName, HKGroupName) {
// 设置openai用哪个节点访问
const forOpenai = "myGPT";
// 创建一个规则数组
const rules = [
// 微软中国
"GEOSITE,microsoft@cn,DIRECT",
// openai
"GEOSITE,openai," + forOpenai,
"RULE-SET,OpenAI," + forOpenai,
// claude
"DOMAIN,servd-anthropic-website.b-cdn.net," + USGroupName,
"DOMAIN,cdn.usefathom.com," + USGroupName,
"DOMAIN-SUFFIX,anthropic.com," + USGroupName,
"DOMAIN-SUFFIX,claude.ai," + USGroupName,
// gemini api
"DOMAIN-SUFFIX,generativelanguage.googleapis.com," + USGroupName,
// linux.do
"DOMAIN-SUFFIX,linux.do,DIRECT",
// fuclaude.com
"DOMAIN-SUFFIX,fuclaude.com,DIRECT",
// oaifree
"DOMAIN-SUFFIX,oaifree.com,DIRECT",
];
// 把rules中的规则全部添加到params.rules中
params["rules"] = rules.concat(params["rules"]);
}