本文最后更新于 2025-09-29T11:20:49+00:00
使用SubstoreJS覆写定向添加链式代理
背景
前些日子笔者正在欢快摸鱼,突然某专线入口惨遭通报,一时大量节点失联,于是打算寻求一个低成本并且高可用性的方案来替换掉现有臃肿的入口组成。
前段时间体验了一下某机场链式拉部分落地,体验不错。决定暂时为这部分入口死掉的节点添加链式代理用一段时间。
由于本人节点池结构较为复杂,简而言之就是“既要又要”。有正常转发的,有优化线路直连的。目前手上的链式代理配置的结构是一个select组选前置机场,一个select组选落地。机场节点由配置里的proxy-provider提供,落地节点写死在前面的策略里。
先说一下,目前笔者的自建管理使用的是substore本地节点里面直接丢了转发好的节点sharelink的组合,配合其配置生成功能生成一份能用的mihomo配置并导入openclash。
这就导致了一个问题——无法做到”既要又要“,手动一个一个加节点在前面,还要为没被转发的落地节点指定dialer-proxy,太麻烦且不优雅。
还考虑了另一个方案是转发好的节点直接作为一个proxy-provider引入,不过这样的话需要维护一整份运行时配置。后期维护难度太大。
这时,笔者萌生了一个想法——能不能用substore的覆写功能,直接在生成的配置文件中为部分节点添加dialer-proxy?
答案是可以的.
原理
新增一个select组和一个proxy-provider组,链接填机场订阅,并把后者全部节点放在前者里,这就是前置的机场。
原来的被通报的节点的落地节点名字里面加上一个关键字,这里使用了原神。在生成的mihomo配置中为这部分节点的dialer-proxy指定为前置机场的select组,bingo!
不过有一点需要注意,需要在最终生成的配置上覆写,简而言之就是这个脚本在substore脚本操作的最底下。
脚本
以下示例中,机场名字使用哈基米,需要套链式的落地节点名里面含有关键字原神,前置select组名字使用嗯嗯嗯
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79
| function main(config) { if (!config || typeof config !== "object") { return config; } if (!config["proxy-providers"]) { config["proxy-providers"] = {}; }
if (!config["proxy-providers"]["哈基米"]) { config["proxy-providers"]["哈基米"] = { type: "http", url: "https://ys.mihomo.com/", interval: 3600, path: "./providers/1.yaml", "health-check": { enable: true, interval: 600, url: "http://www.gstatic.com/generate_204" }, override: { udp: true, "skip-cert-verify": true } }; } if (!Array.isArray(config["proxy-groups"])) { config["proxy-groups"] = []; }
const GROUP_NAME = "嗯嗯嗯"; let airportGroup = config["proxy-groups"].find(g => g && g.name === GROUP_NAME);
if (!airportGroup) { airportGroup = { name: GROUP_NAME, type: "select", use: ["哈基米"] }; config["proxy-groups"].unshift(airportGroup); } else { if (!Array.isArray(airportGroup.use)) { airportGroup.use = []; } if (!airportGroup.use.includes("哈基米")) { airportGroup.use.push("哈基米"); } airportGroup.type = "select"; }
if (Array.isArray(config.proxies)) { const REGEX_HUDISP = /原神/;
config.proxies.forEach(proxy => { if (proxy && typeof proxy.name === "string" && REGEX_HUDISP.test(proxy.name)) { proxy["dialer-proxy"] = GROUP_NAME; } }); }
return config; } if (typeof module !== 'undefined' && module.exports) { module.exports = { main }; } else if (typeof exports !== 'undefined') { exports.main = main; }
|
直接粘贴在脚本操作最底下即可,请确保对应的订阅来源中节点名字含有提取的关键字。