Clash 直连代理配置
创建于:2025年2月5日
创建于:2025年2月5日
text/** * 代理规则配置 * name: 规则名称 * gfw: 是否被墙,如果为 true 则默认使用代理,如果为 true 则默认不使用代理,可手动切换节点。 * urls: 规则集链接,可在这个仓库查找 https://github.com/blackmatrix7/ios_rule_script/blob/master/rule/Clash/README.md * payload: 规则集,如果使用 payload,则 urls 失效。 * extraProxies: 额外代理,一般不需要,去广告可以加一个REJECT */ /** * @type { {name: string,gfw?: boolean,urls?: string | string[],payload?: string | string[],extraProxies?: string | string[]}[] } */ const proxyGrepConfig = [ { name: "直连", gfw: false, urls: "https://cdn.jsdelivr.net/gh/blackmatrix7/ios_rule_script@master/rule/Clash/Direct/Direct.yaml" }, { name: "ip138.com", gfw: true, payload: "DOMAIN-SUFFIX,ip138.com" }, ]; function main(config) { // GPL3.0 license 请保留此注释 // author : picpi https://linux.do/u/picpi // 深拷贝原始配置以避免直接修改 const newConfig = JSON.parse(JSON.stringify(config)); // 过滤3x-9x节点 const multiplierPattern = /(?:[4-9](?:\.5)?x)/i; newConfig.proxies = newConfig.proxies.filter(proxy => !multiplierPattern.test(proxy.name)); //创建域名规则组 function createRuleProviderUrl(url) { return { "type": "http", "interval": 86400, "behavior": "classical", "format": "yaml", "url": url } } // 创建payload对应的规则 function createPayloadRules(payload, name) { const rules = []; const payloads = Array.isArray(payload) ? payload : [payload]; for (const item of payloads) { const p = item.split(","); let pushIndex = p.length; if (p[p.length - 1].toLocaleLowerCase() == "no-resolve") { pushIndex--; } p.splice(pushIndex, 0, name.replaceAll(",", "-")); rules.push(p.join(",")); } console.log(rules); return rules; } // 被墙默认规则 function createGfwProxyGrep(name, addProxies) { addProxies = addProxies ? (Array.isArray(addProxies) ? addProxies : [addProxies]) : []; return { "name": name, "type": "select", "proxies": [...addProxies, "自动选择(最低延迟)", "负载均衡", "DIRECT"], "include-all": true, } } // 不被墙默认规则 function createProxyGrep(name, addProxies) { addProxies = addProxies ? (Array.isArray(addProxies) ? addProxies : [addProxies]) : []; return { "name": name, "type": "select", "proxies": [...addProxies, "DIRECT", "自动选择(最低延迟)", "负载均衡"], "include-all": true, } } const proxyGroups = []; const proxyGfwGroups = []; const ruleProviders = {}; const rules = []; for (const { name, gfw, urls, payload, extraProxies } of proxyGrepConfig) { if (gfw) { proxyGfwGroups.push(createGfwProxyGrep(name, extraProxies)); } else { proxyGroups.push(createProxyGrep(name, extraProxies)); } if (payload) { rules.push(...createPayloadRules(payload, name)); } else { const urlList = urls ? (Array.isArray(urls) ? urls : [urls]) : []; for (const index in urlList) { const theUrl = urlList[index]; const iName = `${name}-rule${index != 0 ? `-${index}` : ''}`; ruleProviders[iName] = createRuleProviderUrl(theUrl); rules.push(`RULE-SET,${iName},${name}`); } } } // 构建更新后的配置 const updatedConfig = { "find-process-mode": "strict", "global-client-fingerprint": "chrome", "unified-delay": true, //更换延迟计算方式,去除握手等额外延迟 "tcp-concurrent": true, //TCP 并发 dns: { enable: true, ipv6: true, "enhanced-mode": "fake-ip", "fake-ip-range": "198.18.0.1/16", "use-hosts": true, "fake-ip-filter": [ "+.lan", "+.local", "+.stun.*.*", "time.*.com" ], nameserver: [ "system", "223.5.5.5", // 阿里 DNS "119.29.29.29", // 腾讯 DNS "https://dns.pub/dns-query" // DNSPod DoH ], fallback: [ "https://dns.cloudflare.com/dns-query", // Cloudflare 主要 "https://dns.google/dns-query", // Google 备用 "tls://1.1.1.1:853", // Cloudflare DoT "tls://8.8.8.8:853" // Google DoT ], "fallback-filter": { geoip: true, "geoip-code": "CN", geosite: ["gfw"], domain: ['+.google.com', '+.github.com'] } }, //代理组配置 "proxy-groups": [ { "name": "自动选择(最低延迟)", "type": "url-test", "tolerance": 20, "include-all": true, "url": "https://play-lh.googleusercontent.com/1UF2WCBNl4918bNk8JsILadL9-agIjRtMpdjuPgx2ohsxnQyspdWDwYMquW1-r8mSQOSjSLOY4g=w720-rw", }, { "name": "国内网站", "type": "select", "proxies": ["DIRECT", "自动选择(最低延迟)", "负载均衡"], "include-all": true, "url": "https://www.baidu.com/favicon.ico" }, ...proxyGroups, { "name": "国外网站", "type": "select", "url": "https://www.bing.com/favicon.ico", "proxies": ["自动选择(最低延迟)", "DIRECT", "负载均衡"], "include-all": true, }, ...proxyGfwGroups, { "name": "被墙网站", "type": "select", "proxies": ["自动选择(最低延迟)", "负载均衡", "DIRECT"], "include-all": true, "url": "https://play-lh.googleusercontent.com/1UF2WCBNl4918bNk8JsILadL9-agIjRtMpdjuPgx2ohsxnQyspdWDwYMquW1-r8mSQOSjSLOY4g=w720-rw", }, { "name": "负载均衡", "type": "load-balance", "include-all": true, "hidden": true, "strategy": "sticky-sessions", "url": "https://play-lh.googleusercontent.com/1UF2WCBNl4918bNk8JsILadL9-agIjRtMpdjuPgx2ohsxnQyspdWDwYMquW1-r8mSQOSjSLOY4g=w720-rw", }, ], "rule-providers": ruleProviders, rules: [ ...rules, "GEOSITE,gfw,被墙网站", "GEOIP,CN,国内网站", "MATCH,国外网站" ] } // 合并配置,保留原配置中未覆盖的属性 return { ...newConfig, // 保留原配置中的其他属性 ...updatedConfig, // 更新需要修改的配置 } }
上方是我的clash verge全局脚本,但是我发现其分流并不方便。
因为有"MATCH,国外网站"兜底的存在,没命中规则的网站,可以直连的,但是还是走了代理,浪费流量;但是如果不使用兜底的话,又可能导致没有命中且无法访问的网站进不去,有什么更好的方案吗
我需要实现:
1.对明确被墙的域名和IP直接走代理
2.对明确国内的域名和IP直接走直连
3.对于内网地址本地地址等直接走直连
4.对所有规则都没命中的域名和IP进行直连优先,失败再代理的测试(超时时间设定为3s,如果直连时间超过3s的体验较差,还不如让其走代理)
前言:
Clash 本身并不支持“对同一个域名/IP,先直连尝试 3 秒,如果超时再自动切换代理” 这样的“逐连接 (per-connection) 动态回退”机制。它的「Fallback Group」只是在「整组节点」层面做可用性探测,一旦检测到第一个可用节点,所有流量都会用它,并不会为单个连接或单个域名做“直连失败再用代理”的回退。
但是,我们仍然可以利用 Clash 提供的「Fallback Group」或「URL-TEST Group」来实现近似的行为——即在非明确规则覆盖的流量上,要么持续直连,要么在直连不可用时改走代理。它无法精确到单个域名/单次连接,但一般对“是否墙掉”较为明显的场景已经够用。
Clash 的分流规则:
当某条流量没有匹配到自定义的规则(DOMAIN-KEYWORD / GEOIP / RULE-SET / 自定义 payload 等),最终会走到 MATCH
(即 “没命中的流量” 的兜底)。
“Fallback Group”的工作方式:
["DIRECT", "代理A", "代理B", …]
)以及一个可用性探测 URL。也就是说,如果将 DIRECT
放在 Fallback Group 的第一位——
DIRECT
访问探测 URL “是通的”,那么这个组就会一直用 DIRECT
;这在全局层面实现了“优先直连,若直连检测失败,自动代理”的效果,但无法在特定网站被墙而探测 URL 没被墙的情况下灵活切换。
DIRECT
代理
DIRECT
FALLBACK
的组,让它的顺序是:
这样 Clash 会先用plaintextproxies: ["DIRECT", "自动选择(最低延迟)"] type: "fallback" url: "http://www.gstatic.com/generate_204" # 只要能正常访问,就判断为可用 interval: 300 # 每 300s 做一次可用性检测 tolerance: 3000 # 超时(毫秒),3 秒
DIRECT
去测这个 gstatic URL,如果响应够快,就会把这个组的节点固定为 DIRECT
;如果长时间无法连接,就回退到代理。注意:
- 如果你网络环境能直连 gstatic(Google)而不被墙,那么
DIRECT
会“始终可用”,剩下所有非明确规则的国外流量也会全部直连;- 如果你网络环境直连 gstatic 不可达,Clash 会直接选用代理。此时“非明确规则”的流量就会走代理。
- 因为只是固定一个探测 URL,如果它和你真正要访问的某些网站“墙况不一致”,就会出现你期待直连的网站打不开、或者你期待代理的网站却没有代理的尴尬。这是 Clash 机制本身的限制。
以下示例只演示核心思路,省略了你脚本里的一些批量生成逻辑;你可以自行融合到脚本中。在原有规则组中,新增一个「fallback group」作为 MATCH
的兜底就行。
yaml# ... proxy-groups: # 常规选择组举例 - name: "国内网站" type: select proxies: - DIRECT - 自动选择(最低延迟) - 负载均衡 # ... - name: "国外网站" type: select proxies: - 自动选择(最低延迟) - DIRECT - 负载均衡 # ... # 最后添加一个 Fallback 组:优先 Direct,不通则自动代理 - name: "DIRECT-OR-PROXY" type: fallback proxies: - DIRECT - 自动选择(最低延迟) url: "http://www.gstatic.com/generate_204" # 探测地址 interval: 300 # 每5分钟探测一次 tolerance: 3000 # 超时毫秒数 rules: # 1. 内网、直连(你也可以用 RULE-SET 等) - DOMAIN-SUFFIX,lan,DIRECT - DOMAIN-SUFFIX,local,DIRECT - IP-CIDR,192.168.0.0/16,DIRECT - IP-CIDR,10.0.0.0/8,DIRECT - IP-CIDR,127.0.0.0/8,DIRECT # ... # 2. 明确被墙域名/IP,走代理 - DOMAIN-SUFFIX,google.com,国外网站 - DOMAIN-SUFFIX,ip138.com,被墙网站 # ... # 3. 明确国内域名/IP - GEOIP,CN,国内网站 - GEOSITE,cn,国内网站 # 4. 兜底:没命中的走 FALLBACK - MATCH,DIRECT-OR-PROXY
注意:
MATCH
中用这个 DIRECT-OR-PROXY
组作为兜底即可。DIRECT-OR-PROXY
里的探测 URL 不要写成国内网址,不然它永远会判定“直连可用”,导致所有海外网站都直连。gstatic
能否直连,能够(大概率)代表“访问海外网站是否被墙”,那就可以用这种 Fallback 方案,至少在实际使用上体验较为接近 “能直连的都直连,不能直连就自动代理” 的效果。希望上述思路能帮你更好地平衡「不想全局代理浪费流量」和「个别网站需要代理才能访问」之间的需求。
直接在我原有脚本上面修改即可(注意:不用改动原本的注释)
下面是一份在你原有脚本基础上最小改动实现“未匹配规则的流量先直连,若直连检测失败再自动切换代理”的示例。主要做了两处改动:
DIRECT-OR-PROXY
的 fallback 组,设置超时为 3 秒(即直连超时后自动回退到代理);MATCH,国外网站
改为 MATCH,DIRECT-OR-PROXY
。除此之外,保留了你脚本原有的注释、GPL 说明及其他逻辑。请直接复制使用即可。
js/** * 代理规则配置 * name: 规则名称 * gfw: 是否被墙,如果为 true 则默认使用代理,如果为 false 则默认不使用代理,可手动切换节点。 * urls: 规则集链接,可在这个仓库查找 https://github.com/blackmatrix7/ios_rule_script/blob/master/rule/Clash/README.md * payload: 规则集,如果使用 payload,则 urls 失效。 * extraProxies: 额外代理,一般不需要,去广告可以加一个REJECT */ /** * @type { {name: string,gfw?: boolean,urls?: string | string[],payload?: string | string[],extraProxies?: string | string[]}[] } */ const proxyGrepConfig = [ { name: "直连", gfw: false, urls: "https://cdn.jsdelivr.net/gh/blackmatrix7/ios_rule_script@master/rule/Clash/Direct/Direct.yaml" }, { name: "ip138.com", gfw: true, payload: "DOMAIN-SUFFIX,ip138.com" }, ]; function main(config) { // GPL3.0 license 请保留此注释 // author : picpi https://linux.do/u/picpi // 深拷贝原始配置以避免直接修改 const newConfig = JSON.parse(JSON.stringify(config)); // 过滤3x-9x节点 const multiplierPattern = /(?:[4-9](?:\.5)?x)/i; newConfig.proxies = newConfig.proxies.filter(proxy => !multiplierPattern.test(proxy.name)); //创建域名规则组 function createRuleProviderUrl(url) { return { "type": "http", "interval": 86400, "behavior": "classical", "format": "yaml", "url": url } } // 创建payload对应的规则 function createPayloadRules(payload, name) { const rules = []; const payloads = Array.isArray(payload) ? payload : [payload]; for (const item of payloads) { const p = item.split(","); let pushIndex = p.length; if (p[p.length - 1].toLocaleLowerCase() == "no-resolve") { pushIndex--; } p.splice(pushIndex, 0, name.replaceAll(",", "-")); rules.push(p.join(",")); } console.log(rules); return rules; } // 被墙默认规则 function createGfwProxyGrep(name, addProxies) { addProxies = addProxies ? (Array.isArray(addProxies) ? addProxies : [addProxies]) : []; return { "name": name, "type": "select", "proxies": [...addProxies, "自动选择(最低延迟)", "负载均衡", "DIRECT"], "include-all": true, } } // 不被墙默认规则 function createProxyGrep(name, addProxies) { addProxies = addProxies ? (Array.isArray(addProxies) ? addProxies : [addProxies]) : []; return { "name": name, "type": "select", "proxies": [...addProxies, "DIRECT", "自动选择(最低延迟)", "负载均衡"], "include-all": true, } } const proxyGroups = []; const proxyGfwGroups = []; const ruleProviders = {}; const rules = []; for (const { name, gfw, urls, payload, extraProxies } of proxyGrepConfig) { if (gfw) { proxyGfwGroups.push(createGfwProxyGrep(name, extraProxies)); } else { proxyGroups.push(createProxyGrep(name, extraProxies)); } if (payload) { rules.push(...createPayloadRules(payload, name)); } else { const urlList = urls ? (Array.isArray(urls) ? urls : [urls]) : []; for (const index in urlList) { const theUrl = urlList[index]; const iName = `${name}-rule${index != 0 ? `-${index}` : ''}`; ruleProviders[iName] = createRuleProviderUrl(theUrl); rules.push(`RULE-SET,${iName},${name}`); } } } // 构建更新后的配置 const updatedConfig = { "find-process-mode": "strict", "global-client-fingerprint": "chrome", "unified-delay": true, // 更换延迟计算方式,去除握手等额外延迟 "tcp-concurrent": true, // TCP 并发 dns: { enable: true, ipv6: true, "enhanced-mode": "fake-ip", "fake-ip-range": "198.18.0.1/16", "use-hosts": true, "fake-ip-filter": [ "+.lan", "+.local", "+.stun.*.*", "time.*.com" ], nameserver: [ "system", "223.5.5.5", // 阿里 DNS "119.29.29.29", // 腾讯 DNS "https://dns.pub/dns-query" // DNSPod DoH ], fallback: [ "https://dns.cloudflare.com/dns-query", // Cloudflare 主要 "https://dns.google/dns-query", // Google 备用 "tls://1.1.1.1:853", // Cloudflare DoT "tls://8.8.8.8:853" // Google DoT ], "fallback-filter": { geoip: true, "geoip-code": "CN", geosite: ["gfw"], domain: ['+.google.com', '+.github.com'] } }, // 代理组配置 "proxy-groups": [ { "name": "自动选择(最低延迟)", "type": "url-test", "tolerance": 20, "include-all": true, "url": "https://play-lh.googleusercontent.com/1UF2WCBNl4918bNk8JsILadL9-agIjRtMpdjuPgx2ohsxnQyspdWDwYMquW1-r8mSQOSjSLOY4g=w720-rw" }, { "name": "国内网站", "type": "select", "proxies": ["DIRECT", "自动选择(最低延迟)", "负载均衡"], "include-all": true, "url": "https://www.baidu.com/favicon.ico" }, ...proxyGroups, { "name": "国外网站", "type": "select", "url": "https://www.bing.com/favicon.ico", "proxies": ["自动选择(最低延迟)", "DIRECT", "负载均衡"], "include-all": true }, ...proxyGfwGroups, { "name": "被墙网站", "type": "select", "proxies": ["自动选择(最低延迟)", "负载均衡", "DIRECT"], "include-all": true, "url": "https://play-lh.googleusercontent.com/1UF2WCBNl4918bNk8JsILadL9-agIjRtMpdjuPgx2ohsxnQyspdWDwYMquW1-r8mSQOSjSLOY4g=w720-rw" }, { "name": "负载均衡", "type": "load-balance", "include-all": true, "hidden": true, "strategy": "sticky-sessions", "url": "https://play-lh.googleusercontent.com/1UF2WCBNl4918bNk8JsILadL9-agIjRtMpdjuPgx2ohsxnQyspdWDwYMquW1-r8mSQOSjSLOY4g=w720-rw" }, // ===== 新增 fallback 组:优先尝试直连,不通则回退代理 ===== { "name": "DIRECT-OR-PROXY", "type": "fallback", "proxies": [ "DIRECT", "自动选择(最低延迟)" ], // 以 gstatic 作为探测地址,若直连超时超过 3s,则回退到代理 "url": "http://www.gstatic.com/generate_204", "interval": 300, "tolerance": 3000 } ], "rule-providers": ruleProviders, // 最后一行 MATCH 改为直连或自动代理回退 rules: [ ...rules, "GEOSITE,gfw,被墙网站", "GEOIP,CN,国内网站", // 原来是 "MATCH,国外网站" 改为 "MATCH,DIRECT-OR-PROXY": "MATCH,DIRECT-OR-PROXY" ] } // 合并配置,保留原配置中未覆盖的属性 return { ...newConfig, // 保留原配置中的其他属性 ...updatedConfig, // 更新需要修改的配置 } }
MATCH,DIRECT-OR-PROXY
保证“没被任何规则命中的流量”先尝试 DIRECT,若在探测 URL 中判定直连不可用,就会自动回退到 自动选择(最低延迟)
。gstatic
,那么大部分境外流量也都会被判定为直连。如果实际上某些被墙网站没命中自定义规则,依然可能直连失败。这属于 Clash 本身的机制限制,暂无法实现真正的“对单个域名先直连超时再自动代理”。interval
(检测间隔秒数)、tolerance
(超时阈值毫秒数)等,满足不同需求。以 gstatic 作为探测地址是什么意思,不应该用要访问的地址进行检测吗
为什么要用 gstatic
作为探测地址,而不是“要访问的具体域名”?
这是因为 Clash 的「fallback」或「url-test」等组策略,只能通过一个(或一小部分)固定的探测 URL 来测试节点可用性,而不是在用户访问某个域名时再做动态探测。它并不会为每个域名动态改变节点,而是整组节点都统一使用同一个探测链接来判断“谁可用”或“是否需要回退”。
fallback / url-test 组
当你在一个策略组中配置多个节点(或 DIRECT
),并指定 url
作为探测地址,Clash 会在设定的 interval
间隔内主动请求这个 url
:
DIRECT
)在设定的 tolerance
(容忍超时)内返回正常,则该组判定“这个节点是可用的”,后续所有流量都用它。代理
)。一旦找到可用的,整个组就固定使用它,直到下一次间隔检测或手动切换。为什么是“固定探测地址”而非“逐域名”
Clash 的设计是面向整组策略的健康检测,而不会对你正在访问的每个域名都做一次测试然后再决定用不用代理。
换句话说,只有探测 URL 的连通性会影响组内节点的选用,而“实际访问的目标域名”是不参与自动测试的。
gstatic
的原因gstatic
属于 Google 的 CDN/静态资源域名,访问 http://www.gstatic.com/generate_204
返回一个无内容 (HTTP 204) 的极简响应,请求体积很小。gstatic
”常被用来简易地检测“出国”能力,从而决定走直连还是走代理。gstatic
并没有被封锁,而你访问的其它海外站点却被封,那么这种探测会误判为“直连可用”,从而导致访问失败;这是 Clash Fallback 的通病。你也可以换其他 URL,例如:
http://www.google.com/generate_204
https://www.google.com/favicon.ico
https://cp.cloudflare.com/generate_204
只要它能够代表“访问海外网站”是否被墙就行,并且响应足够快、文件体积足够小,以免误判。
gstatic
只是一个常用的轻量级海外探测地址:由于它与 Google 同域,往往能代表“能不能直连到美国”,所以被很多人用来做可用性检测。在实际使用中,这种方法通常足够应付常见场景:“能直连就一直直连,直连不通了就切代理”。但它并不等同于**“所有未匹配域名一旦无法直连立刻自动切换到代理”**那种精细行为。
如果存在AB两个域名都没有命中规则,其中A能直连访问,B不能直连访问。按这个逻辑岂不是B打不开?
确实会出现你所说的情况:如果探测 URL 可以直连,那么 Fallback 组就会一直维持「直连」状态,结果对于某些真实被墙的域名(却又没被你手动规则命中),就无法自动回退到代理,从而导致访问失败。
这是由于 Clash 「fallback」或「url-test」策略组仅通过单一或少数几个固定探测链接,来决定“用直连还是用代理”。它并不会在每次你访问某个域名时重新测试那个域名能不能直连。一旦探测链接认为直连可行,整个组就锁定在直连,哪怕实际有部分海外网站被墙也无能为力。
使用更完善的规则集
使用 Clash Premium / Clash.Meta 的「Scripting」功能
在 fallback 组里列出多个探测 URL(有的分支版本支持 url
配置成一个数组)
gstatic
又测 bing
又测 cloudflare
,只要有一个不通就回退代理。人工或半自动的切换
这就是为什么,绝大多数人使用 Clash 时,往往会订阅一些已经整理好的大型规则(区分国内外流量、常见被墙域名等),把人工维护成本降到最低,而不是依靠 fallback “自动”检测。
为我修改脚本,使用更全的规则,同时实现
1.对明确被墙的域名和IP直接走代理
2.对明确国内的域名和IP直接走直连
3.对于内网地址本地地址等直接走直连
4.兜底使用直连,避免浪费流量
下面是一份示例脚本,基于你原有的脚本结构做了最小化修改,并引入了 blackmatrix7/ios_rule_script 里的 更完整的「中国(China)」和「GFW」规则。主要实现以下需求:
你只需将以下脚本粘贴到 Clash Verge 的全局脚本位置即可使用。
(请根据需要自行微调超时/备用 DNS/节点命名等。)
说明:
- 本示例依赖两个规则集:
China.yaml
&GFW.yaml
来识别国内和被墙域名。- 同时在最终
rules
中添加了局域网地址的直连,最后MATCH
也直连。- 如果仍有某些被墙网站未被
GFW.yaml
覆盖(极少数情况),它们依然会“兜底直连”。你可手动在proxyGrepConfig
里再加入其它规则集,或在 Clash 前端自行补充规则。
js/** * 代理规则配置 * name: 规则名称 * gfw: 是否被墙,如果为 true 则默认使用代理,如果为 false 则默认不使用代理,可手动切换节点。 * urls: 规则集链接,可在这个仓库查找 https://github.com/blackmatrix7/ios_rule_script/blob/master/rule/Clash/README.md * payload: 规则集,如果使用 payload,则 urls 失效。 * extraProxies: 额外代理,一般不需要,去广告可以加一个REJECT */ /** * @type { {name: string,gfw?: boolean,urls?: string | string[],payload?: string | string[],extraProxies?: string | string[]}[] } */ const proxyGrepConfig = [ // 采用更完整的黑白名单规则 { name: "国内", gfw: false, urls: "https://cdn.jsdelivr.net/gh/blackmatrix7/ios_rule_script@master/rule/Clash/China/China.yaml" }, { name: "被墙", gfw: true, urls: "https://cdn.jsdelivr.net/gh/blackmatrix7/ios_rule_script@master/rule/Clash/GFW/GFW.yaml" }, ]; function main(config) { // GPL3.0 license 请保留此注释 // author : picpi https://linux.do/u/picpi // 深拷贝原始配置以避免直接修改 const newConfig = JSON.parse(JSON.stringify(config)); // 过滤3x-9x节点 const multiplierPattern = /(?:[4-9](?:\.5)?x)/i; newConfig.proxies = newConfig.proxies.filter(proxy => !multiplierPattern.test(proxy.name)); // 创建域名规则组 function createRuleProviderUrl(url) { return { "type": "http", "interval": 86400, "behavior": "classical", "format": "yaml", "url": url } } // 创建payload对应的规则 function createPayloadRules(payload, name) { const rules = []; const payloads = Array.isArray(payload) ? payload : [payload]; for (const item of payloads) { const p = item.split(","); let pushIndex = p.length; if (p[p.length - 1].toLocaleLowerCase() == "no-resolve") { pushIndex--; } p.splice(pushIndex, 0, name.replaceAll(",", "-")); rules.push(p.join(",")); } console.log(rules); return rules; } // 被墙默认规则 function createGfwProxyGrep(name, addProxies) { addProxies = addProxies ? (Array.isArray(addProxies) ? addProxies : [addProxies]) : []; return { "name": name, "type": "select", "proxies": [...addProxies, "自动选择(最低延迟)", "负载均衡", "DIRECT"], "include-all": true, } } // 不被墙默认规则 function createProxyGrep(name, addProxies) { addProxies = addProxies ? (Array.isArray(addProxies) ? addProxies : [addProxies]) : []; return { "name": name, "type": "select", "proxies": [...addProxies, "DIRECT", "自动选择(最低延迟)", "负载均衡"], "include-all": true, } } const proxyGroups = []; const proxyGfwGroups = []; const ruleProviders = {}; const rules = []; for (const { name, gfw, urls, payload, extraProxies } of proxyGrepConfig) { if (gfw) { // 对被墙网站 -> 默认代理 proxyGfwGroups.push(createGfwProxyGrep(name, extraProxies)); } else { // 对国内网站 -> 默认直连 proxyGroups.push(createProxyGrep(name, extraProxies)); } // 如果使用 payload 方式,则直接将自定义的规则写入;否则使用远程 urls if (payload) { rules.push(...createPayloadRules(payload, name)); } else if (urls) { const urlList = Array.isArray(urls) ? urls : [urls]; for (const index in urlList) { const theUrl = urlList[index]; const iName = `${name}-rule${index != 0 ? `-${index}` : ''}`; ruleProviders[iName] = createRuleProviderUrl(theUrl); // 这里生成一条 RULE-SET 语句绑定到对应的代理组 rules.push(`RULE-SET,${iName},${name}`); } } } // 构建更新后的配置 const updatedConfig = { "find-process-mode": "strict", "global-client-fingerprint": "chrome", "unified-delay": true, // 更换延迟计算方式,去除握手等额外延迟 "tcp-concurrent": true, // TCP 并发 dns: { enable: true, ipv6: true, "enhanced-mode": "fake-ip", "fake-ip-range": "198.18.0.1/16", "use-hosts": true, "fake-ip-filter": [ "+.lan", "+.local", "+.stun.*.*", "time.*.com" ], nameserver: [ "system", "223.5.5.5", // 阿里 DNS "119.29.29.29", // 腾讯 DNS "https://dns.pub/dns-query" // DNSPod DoH ], fallback: [ "https://dns.cloudflare.com/dns-query", // Cloudflare 主要 "https://dns.google/dns-query", // Google 备用 "tls://1.1.1.1:853", // Cloudflare DoT "tls://8.8.8.8:853" // Google DoT ], "fallback-filter": { geoip: true, "geoip-code": "CN", geosite: ["gfw"], domain: ['+.google.com', '+.github.com'] } }, // 代理组配置 "proxy-groups": [ { "name": "自动选择(最低延迟)", "type": "url-test", "tolerance": 20, "include-all": true, "url": "https://play-lh.googleusercontent.com/1UF2WCBNl4918bNk8JsILadL9-agIjRtMpdjuPgx2ohsxnQyspdWDwYMquW1-r8mSQOSjSLOY4g=w720-rw" }, { "name": "国内网站", "type": "select", "proxies": ["DIRECT", "自动选择(最低延迟)", "负载均衡"], "include-all": true, "url": "https://www.baidu.com/favicon.ico" }, ...proxyGroups, { "name": "国外网站", "type": "select", "url": "https://www.bing.com/favicon.ico", "proxies": ["自动选择(最低延迟)", "DIRECT", "负载均衡"], "include-all": true }, ...proxyGfwGroups, { "name": "被墙网站", "type": "select", "proxies": ["自动选择(最低延迟)", "负载均衡", "DIRECT"], "include-all": true, "url": "https://play-lh.googleusercontent.com/1UF2WCBNl4918bNk8JsILadL9-agIjRtMpdjuPgx2ohsxnQyspdWDwYMquW1-r8mSQOSjSLOY4g=w720-rw" }, { "name": "负载均衡", "type": "load-balance", "include-all": true, "hidden": true, "strategy": "sticky-sessions", "url": "https://play-lh.googleusercontent.com/1UF2WCBNl4918bNk8JsILadL9-agIjRtMpdjuPgx2ohsxnQyspdWDwYMquW1-r8mSQOSjSLOY4g=w720-rw" } ], "rule-providers": ruleProviders, // 规则列表 rules: [ // 先放一些常见内网/本机直连 "IP-CIDR,127.0.0.0/8,DIRECT,no-resolve", "IP-CIDR,192.168.0.0/16,DIRECT,no-resolve", "IP-CIDR,10.0.0.0/8,DIRECT,no-resolve", "IP-CIDR,172.16.0.0/12,DIRECT,no-resolve", // 加载上面 proxyGrepConfig 里自动生成的 RULE-SET 绑定规则 ...rules, // 这里再补充对 IP 进行国内直连 "GEOIP,CN,国内", // 最后一条兜底:没命中就直接直连,减少代理浪费 "MATCH,DIRECT" ] }; // 合并配置,保留原配置中未覆盖的属性 return { ...newConfig, // 保留原配置中的其他属性 ...updatedConfig, // 更新需要修改的配置 } }
proxyGrepConfig
中指定
来加载 blackmatrix 更全面的 GFW / China 规则集合。js{ name: "被墙", gfw: true, urls: "https://cdn.jsdelivr.net/gh/blackmatrix7/ios_rule_script@master/rule/Clash/GFW/GFW.yaml" }, { name: "国内", gfw: false, urls: "https://cdn.jsdelivr.net/gh/blackmatrix7/ios_rule_script@master/rule/Clash/China/China.yaml" }
GFW.yaml
中的域名和 IP 放到「被墙」组(默认代理),命中 China.yaml
的放到「国内」组(默认直连)。rules
里额外添加了 IP-CIDR,127.0.0.0/8
、IP-CIDR,192.168.0.0/16
、IP-CIDR,10.0.0.0/8
、IP-CIDR,172.16.0.0/12
等常见私网网段直连。MATCH,DIRECT
保证所有未被识别为“中国”或“被墙”的流量,最终都直连。MATCH,DIRECT
,导致访问失败。此时你可以:
DOMAIN-SUFFIX,example.com,被墙
;或proxyGrepConfig
里再补充对应的 payload
或额外 urls
,使之识别为“被墙”从而走代理。这样就能在保持最简洁的编排下,兼顾「覆盖常见国内、被墙域名」和「其余全部直连」的需求。