1141 lines
27 KiB
JavaScript
1141 lines
27 KiB
JavaScript
/* ============================================================
|
|
* 一、基础配置
|
|
* ============================================================
|
|
*/
|
|
const GENERAL_CONFIG = {
|
|
"mode": "rule",
|
|
"ipv6": true,
|
|
"log-level": "silent",
|
|
"allow-lan": true,
|
|
"mixed-port": 7890,
|
|
"unified-delay": false,
|
|
"tcp-concurrent": true,
|
|
"external-controller-tls": "127.0.0.1:9090",
|
|
"find-process-mode": "strict",
|
|
"global-client-fingerprint": "chrome",
|
|
"profile": {
|
|
"store-selected": true,
|
|
"store-fake-ip": true
|
|
}
|
|
};
|
|
/* ============================================================
|
|
* 二、统一测速配置
|
|
* ============================================================
|
|
*/
|
|
const TEST_URL =
|
|
"https://www.gstatic.com/generate_204";
|
|
const GROUP_INTERVAL = 600;
|
|
const GROUP_TIMEOUT = 5000;
|
|
const GROUP_TOLERANCE = 50;
|
|
const FALLBACK_INTERVAL = 300;
|
|
/* ============================================================
|
|
* 三、固定策略名称
|
|
* ============================================================
|
|
*
|
|
* 统一集中管理。
|
|
*
|
|
* 后续修改名称时只需要修改这里。
|
|
*
|
|
* ============================================================
|
|
*/
|
|
const GROUP_NAMES = {
|
|
NODE_SELECT: "🚀 节点选择",
|
|
AUTO: "♻️ 自动选择",
|
|
FALLBACK: "🔯 故障转移",
|
|
AI: "🤖 人工智能",
|
|
OVERSEAS: "🌍 海外服务",
|
|
NETWORK_TEST: "📈 网络测试",
|
|
PROXY_SERVICE: "🪜 代理服务",
|
|
DIRECT: "🎯 全球直连",
|
|
AD_BLOCK: "🛑 广告拦截",
|
|
FINAL: "🎯 兜底策略"
|
|
};
|
|
/* ============================================================
|
|
* 四、地区名称
|
|
* ============================================================
|
|
*/
|
|
const REGION_NAMES = [
|
|
"🇭🇰 香港",
|
|
"🇹🇼 台湾",
|
|
"🇯🇵 日本",
|
|
"🇸🇬 新加坡",
|
|
"🇺🇸 美国",
|
|
"🌐 其他"
|
|
];
|
|
/* ============================================================
|
|
* 五、Sniffer
|
|
* ============================================================
|
|
*/
|
|
const SNIFFER_CONFIG = {
|
|
"enable": true,
|
|
"parse-pure-ip": true,
|
|
"sniff": {
|
|
"HTTP": {
|
|
"ports": [
|
|
80,
|
|
"8080-8880"
|
|
],
|
|
"override-destination": true
|
|
},
|
|
"TLS": {
|
|
"ports": [
|
|
443,
|
|
8443
|
|
]
|
|
},
|
|
"QUIC": {
|
|
"ports": [
|
|
443,
|
|
8443
|
|
]
|
|
}
|
|
},
|
|
"skip-domain": [
|
|
"Mijia Cloud"
|
|
]
|
|
};
|
|
/* ============================================================
|
|
* 六、TUN
|
|
* ============================================================
|
|
*/
|
|
const TUN_CONFIG = {
|
|
"enable": true,
|
|
"stack": "system",
|
|
"dns-hijack": [
|
|
"any:53"
|
|
],
|
|
"auto-route": true,
|
|
"auto-detect-interface": true,
|
|
"strict-route": true
|
|
};
|
|
/* ============================================================
|
|
* 七、DNS
|
|
* ============================================================
|
|
*/
|
|
const DNS_CONFIG = {
|
|
"enable": true,
|
|
"ipv6": true,
|
|
"prefer-h3": true,
|
|
"listen": "0.0.0.0:53",
|
|
"fake-ip-range": "198.18.0.1/16",
|
|
"enhanced-mode": "fake-ip",
|
|
"fallback": [
|
|
"8.8.8.8"
|
|
],
|
|
"default-nameserver": [
|
|
"223.5.5.5",
|
|
"114.114.114.114"
|
|
],
|
|
"nameserver": [
|
|
"https://dns.alidns.com/dns-query#h3=true",
|
|
"https://doh.pub/dns-query"
|
|
],
|
|
"fake-ip-filter": [
|
|
/* 本地 */
|
|
"*.lan",
|
|
"*.localdomain",
|
|
"*.example",
|
|
"*.invalid",
|
|
"*.localhost",
|
|
"*.test",
|
|
"*.local",
|
|
"*.home.arpa",
|
|
/* 自定义 */
|
|
"*.woozooo.com",
|
|
"*.kiid.top",
|
|
"43.142.112.88",
|
|
/* 时间同步 */
|
|
"time.*.com",
|
|
"time.*.gov",
|
|
"time.*.edu.cn",
|
|
"time.*.apple.com",
|
|
"time-ios.apple.com",
|
|
"time1.*.com",
|
|
"time2.*.com",
|
|
"time3.*.com",
|
|
"time4.*.com",
|
|
"time5.*.com",
|
|
"time6.*.com",
|
|
"time7.*.com",
|
|
"ntp.*.com",
|
|
"ntp1.*.com",
|
|
"ntp2.*.com",
|
|
"ntp3.*.com",
|
|
"ntp4.*.com",
|
|
"ntp5.*.com",
|
|
"ntp6.*.com",
|
|
"ntp7.*.com",
|
|
"*.time.edu.cn",
|
|
"*.ntp.org.cn",
|
|
"+.pool.ntp.org",
|
|
"time1.cloud.tencent.com",
|
|
/* 网易云音乐 */
|
|
"music.163.com",
|
|
"*.music.163.com",
|
|
"*.126.net",
|
|
/* 太和音乐 */
|
|
"musicapi.taihe.com",
|
|
"music.taihe.com",
|
|
/* 酷狗 */
|
|
"songsearch.kugou.com",
|
|
"trackercdn.kugou.com",
|
|
/* 酷我 */
|
|
"*.kuwo.cn",
|
|
/* JOOX */
|
|
"api-jooxtt.sanook.com",
|
|
"api.joox.com",
|
|
"joox.com",
|
|
/* QQ音乐 */
|
|
"y.qq.com",
|
|
"*.y.qq.com",
|
|
"streamoc.music.tc.qq.com",
|
|
"mobileoc.music.tc.qq.com",
|
|
"isure.stream.qqmusic.qq.com",
|
|
"dl.stream.qqmusic.qq.com",
|
|
"aqqmusic.tc.qq.com",
|
|
"amobile.music.tc.qq.com",
|
|
/* 虾米 */
|
|
"*.xiami.com",
|
|
/* 咪咕 */
|
|
"*.music.migu.cn",
|
|
"music.migu.cn",
|
|
/* Windows 网络检测 */
|
|
"+.msftconnecttest.com",
|
|
"+.msftncsi.com",
|
|
/* QQ */
|
|
"localhost.ptlogin2.qq.com",
|
|
"localhost.sec.qq.com",
|
|
"+.qq.com",
|
|
"+.tencent.com",
|
|
/* Nintendo */
|
|
"+.srv.nintendo.net",
|
|
"*.n.n.srv.nintendo.net",
|
|
/* PlayStation */
|
|
"+.stun.playstation.net",
|
|
/* Xbox */
|
|
"xbox.*.*.microsoft.com",
|
|
"*.*.xboxlive.com",
|
|
"xbox.*.microsoft.com",
|
|
"xnotify.xboxlive.com",
|
|
/* Battle.net */
|
|
"+.battlenet.com.cn",
|
|
/* Wargaming */
|
|
"+.wotgame.cn",
|
|
"+.wggames.cn",
|
|
"+.wowsgame.cn",
|
|
"+.wargaming.net",
|
|
/* Go */
|
|
"proxy.golang.org",
|
|
/* STUN */
|
|
"stun.*.*",
|
|
"stun.*.*.*",
|
|
"+.stun.*.*",
|
|
"+.stun.*.*.*",
|
|
"+.stun.*.*.*.*",
|
|
"+.stun.*.*.*.*.*",
|
|
/* Belkin */
|
|
"heartbeat.belkin.com",
|
|
/* Linksys */
|
|
"*.linksys.com",
|
|
"*.linksyssmartwifi.com",
|
|
/* ASUS */
|
|
"*.router.asus.com",
|
|
/* Apple */
|
|
"mesu.apple.com",
|
|
"swscan.apple.com",
|
|
"swquery.apple.com",
|
|
"swdownload.apple.com",
|
|
"swcdn.apple.com",
|
|
"swdist.apple.com",
|
|
/* Google */
|
|
"lens.l.google.com",
|
|
"stun.l.google.com",
|
|
/* 游戏 */
|
|
"na.b.g-tun.com",
|
|
/* Netflix */
|
|
"+.nflxvideo.net",
|
|
/* Square Enix */
|
|
"*.square-enix.com",
|
|
"*.finalfantasyxiv.com",
|
|
"*.ffxiv.com",
|
|
"*.ff14.sdo.com",
|
|
"ff.dorado.sdo.com",
|
|
/* 哔哩哔哩 */
|
|
"*.mcdn.bilivideo.cn",
|
|
/* Disney */
|
|
"+.media.dssott.com",
|
|
/* Shark007 */
|
|
"shark007.net",
|
|
/* 小米 */
|
|
"Mijia Cloud",
|
|
/* 招商银行 */
|
|
"+.cmbchina.com",
|
|
"+.cmbimg.com",
|
|
/* AdGuard */
|
|
"adguardteam.github.io",
|
|
"adrules.top",
|
|
"anti-ad.net",
|
|
"local.adguard.org",
|
|
"static.adtidy.org",
|
|
/* 网络 */
|
|
"+.sandai.net",
|
|
"+.n0808.com",
|
|
"+.3gppnetwork.org"
|
|
]
|
|
};
|
|
/* ============================================================
|
|
* 八、节点地区识别
|
|
* ============================================================
|
|
*
|
|
* 注意:
|
|
*
|
|
* 不再使用单独的:
|
|
*
|
|
* 港
|
|
* 台
|
|
* 日
|
|
* 新
|
|
* 美
|
|
*
|
|
* 作为独立匹配条件。
|
|
*
|
|
* 防止机场自定义名称产生误判。
|
|
*
|
|
* ============================================================
|
|
*/
|
|
const REGION_PATTERNS = {
|
|
"🇭🇰 香港":
|
|
/(?:香港|香港地区|Hong[\s_-]?Kong|HKG|HK|🇭🇰)/i,
|
|
"🇹🇼 台湾":
|
|
/(?:台湾|台湾地区|Taiwan|TWN|TW|🇹🇼)/i,
|
|
"🇯🇵 日本":
|
|
/(?:日本|日本地区|Japan|JPN|JP|🇯🇵)/i,
|
|
"🇸🇬 新加坡":
|
|
/(?:新加坡|狮城|Singapore|Singapura|SGP|SG|🇸🇬)/i,
|
|
"🇺🇸 美国":
|
|
/(?:美国|美国地区|United[\s_-]?States|USA|US|America|🇺🇸)/i
|
|
};
|
|
/* ============================================================
|
|
* 九、节点辅助函数
|
|
* ============================================================
|
|
*/
|
|
function getProxyName(proxy) {
|
|
if (!proxy) {
|
|
return "";
|
|
}
|
|
if (typeof proxy === "string") {
|
|
return proxy;
|
|
}
|
|
return proxy.name || "";
|
|
}
|
|
/*
|
|
* 判断是否为真实代理节点。
|
|
*/
|
|
function isUsableProxy(proxy) {
|
|
const name =
|
|
getProxyName(proxy);
|
|
if (!name) {
|
|
return false;
|
|
}
|
|
const upperName =
|
|
name.toUpperCase();
|
|
const excludedNames = [
|
|
"DIRECT",
|
|
"REJECT",
|
|
"REJECT-DROP",
|
|
"PASS"
|
|
];
|
|
if (
|
|
excludedNames.indexOf(
|
|
upperName
|
|
) !== -1
|
|
) {
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
/*
|
|
* 获取节点地区。
|
|
*/
|
|
function getRegionName(proxyName) {
|
|
const regionNames =
|
|
Object.keys(REGION_PATTERNS);
|
|
for (
|
|
let i = 0;
|
|
i < regionNames.length;
|
|
i++
|
|
) {
|
|
const regionName =
|
|
regionNames[i];
|
|
if (
|
|
REGION_PATTERNS[
|
|
regionName
|
|
].test(proxyName)
|
|
) {
|
|
return regionName;
|
|
}
|
|
}
|
|
return "🌐 其他";
|
|
}
|
|
/*
|
|
* 初始化地区节点。
|
|
*/
|
|
function createEmptyRegionNodes() {
|
|
return {
|
|
"🇭🇰 香港": [],
|
|
"🇹🇼 台湾": [],
|
|
"🇯🇵 日本": [],
|
|
"🇸🇬 新加坡": [],
|
|
"🇺🇸 美国": [],
|
|
"🌐 其他": []
|
|
};
|
|
}
|
|
/*
|
|
* 分类节点。
|
|
*/
|
|
function classifyProxies(config) {
|
|
const regionNodes =
|
|
createEmptyRegionNodes();
|
|
const proxies =
|
|
Array.isArray(config.proxies)
|
|
? config.proxies
|
|
: [];
|
|
for (
|
|
let i = 0;
|
|
i < proxies.length;
|
|
i++
|
|
) {
|
|
const proxy =
|
|
proxies[i];
|
|
if (
|
|
!isUsableProxy(proxy)
|
|
) {
|
|
continue;
|
|
}
|
|
const proxyName =
|
|
getProxyName(proxy);
|
|
const regionName =
|
|
getRegionName(proxyName);
|
|
regionNodes[
|
|
regionName
|
|
].push(proxyName);
|
|
}
|
|
return regionNodes;
|
|
}
|
|
/*
|
|
* 获取实际存在的地区。
|
|
*/
|
|
function getExistingRegions(
|
|
regionNodes
|
|
) {
|
|
const result = [];
|
|
for (
|
|
let i = 0;
|
|
i < REGION_NAMES.length;
|
|
i++
|
|
) {
|
|
const regionName =
|
|
REGION_NAMES[i];
|
|
if (
|
|
regionNodes[
|
|
regionName
|
|
] &&
|
|
regionNodes[
|
|
regionName
|
|
].length > 0
|
|
) {
|
|
result.push(regionName);
|
|
}
|
|
}
|
|
return result;
|
|
}
|
|
/* ============================================================
|
|
* 十、代理组辅助函数
|
|
* ============================================================
|
|
*/
|
|
/*
|
|
* 创建地区测速组。
|
|
*/
|
|
function createRegionGroup(
|
|
name,
|
|
proxies
|
|
) {
|
|
return {
|
|
"name": name,
|
|
"type": "url-test",
|
|
"proxies": proxies,
|
|
"url": TEST_URL,
|
|
"interval": GROUP_INTERVAL,
|
|
"timeout": GROUP_TIMEOUT,
|
|
"lazy": true,
|
|
"tolerance": GROUP_TOLERANCE,
|
|
"max-failed-times": 3
|
|
};
|
|
}
|
|
/*
|
|
* 创建选择组。
|
|
*/
|
|
function createSelectGroup(
|
|
name,
|
|
proxies,
|
|
disableUdp
|
|
) {
|
|
const group = {
|
|
"name": name,
|
|
"type": "select",
|
|
"proxies": proxies
|
|
};
|
|
if (disableUdp === true) {
|
|
group["disable-udp"] = true;
|
|
}
|
|
return group;
|
|
}
|
|
/*
|
|
* 判断策略是否存在。
|
|
*/
|
|
function hasGroup(
|
|
groupNames,
|
|
name
|
|
) {
|
|
return (
|
|
groupNames.indexOf(name) !== -1
|
|
);
|
|
}
|
|
/*
|
|
* 创建地区策略。
|
|
*/
|
|
function addExistingRegionGroup(
|
|
groups,
|
|
regionNodes,
|
|
regionName
|
|
) {
|
|
const proxies =
|
|
regionNodes[
|
|
regionName
|
|
] || [];
|
|
if (
|
|
proxies.length === 0
|
|
) {
|
|
return;
|
|
}
|
|
groups.push(
|
|
createRegionGroup(
|
|
regionName,
|
|
proxies
|
|
)
|
|
);
|
|
}
|
|
/* ============================================================
|
|
* 十一、动态创建代理组
|
|
* ============================================================
|
|
*
|
|
* 排序结构:
|
|
*
|
|
* ① 🚀 节点选择
|
|
* ② ♻️ 自动选择
|
|
* ③ 🔯 故障转移
|
|
*
|
|
* ④ 地区策略
|
|
*
|
|
* ⑤ 人工智能
|
|
* ⑥ 海外服务
|
|
* ⑦ 网络测试
|
|
* ⑧ 代理服务
|
|
*
|
|
* ⑨ 全球直连
|
|
* ⑩ 广告拦截
|
|
* ⑪ 兜底策略
|
|
*
|
|
* ============================================================
|
|
*/
|
|
function createProxyGroups(config) {
|
|
const regionNodes =
|
|
classifyProxies(config);
|
|
const existingRegions =
|
|
getExistingRegions(
|
|
regionNodes
|
|
);
|
|
const groups = [];
|
|
/*
|
|
* ========================================================
|
|
* 第一层:核心节点控制
|
|
* ========================================================
|
|
*/
|
|
/*
|
|
* ① 节点选择
|
|
*
|
|
* 先预留,后面填充实际策略。
|
|
*/
|
|
const nodeSelectOptions = [];
|
|
/*
|
|
* ② 自动选择
|
|
*/
|
|
if (
|
|
existingRegions.length > 0
|
|
) {
|
|
groups.push({
|
|
"name": GROUP_NAMES.AUTO,
|
|
"type": "url-test",
|
|
"proxies": existingRegions,
|
|
"url": TEST_URL,
|
|
"interval": GROUP_INTERVAL,
|
|
"timeout": GROUP_TIMEOUT,
|
|
"lazy": true,
|
|
"tolerance": GROUP_TOLERANCE,
|
|
"max-failed-times": 3
|
|
});
|
|
nodeSelectOptions.push(
|
|
GROUP_NAMES.AUTO
|
|
);
|
|
}
|
|
/*
|
|
* ③ 故障转移
|
|
*/
|
|
if (
|
|
existingRegions.length > 0
|
|
) {
|
|
groups.push({
|
|
"name": GROUP_NAMES.FALLBACK,
|
|
"type": "fallback",
|
|
"proxies": existingRegions,
|
|
"url": TEST_URL,
|
|
"interval": FALLBACK_INTERVAL,
|
|
"timeout": GROUP_TIMEOUT,
|
|
"lazy": true
|
|
});
|
|
nodeSelectOptions.push(
|
|
GROUP_NAMES.FALLBACK
|
|
);
|
|
}
|
|
/*
|
|
* 地区加入节点选择。
|
|
*/
|
|
for (
|
|
let i = 0;
|
|
i < existingRegions.length;
|
|
i++
|
|
) {
|
|
nodeSelectOptions.push(
|
|
existingRegions[i]
|
|
);
|
|
}
|
|
/*
|
|
* ① 节点选择
|
|
*
|
|
* 最终插入到 groups[0]。
|
|
*/
|
|
groups.unshift(
|
|
createSelectGroup(
|
|
GROUP_NAMES.NODE_SELECT,
|
|
nodeSelectOptions
|
|
)
|
|
);
|
|
/*
|
|
* ========================================================
|
|
* 第二层:地区策略
|
|
* ========================================================
|
|
*/
|
|
addExistingRegionGroup(
|
|
groups,
|
|
regionNodes,
|
|
"🇭🇰 香港"
|
|
);
|
|
addExistingRegionGroup(
|
|
groups,
|
|
regionNodes,
|
|
"🇹🇼 台湾"
|
|
);
|
|
addExistingRegionGroup(
|
|
groups,
|
|
regionNodes,
|
|
"🇯🇵 日本"
|
|
);
|
|
addExistingRegionGroup(
|
|
groups,
|
|
regionNodes,
|
|
"🇸🇬 新加坡"
|
|
);
|
|
addExistingRegionGroup(
|
|
groups,
|
|
regionNodes,
|
|
"🇺🇸 美国"
|
|
);
|
|
addExistingRegionGroup(
|
|
groups,
|
|
regionNodes,
|
|
"🌐 其他"
|
|
);
|
|
/*
|
|
* ========================================================
|
|
* 第三层:人工智能
|
|
* ========================================================
|
|
*
|
|
* 排除香港。
|
|
*/
|
|
const aiRegions = [
|
|
"🇹🇼 台湾",
|
|
"🇯🇵 日本",
|
|
"🇸🇬 新加坡",
|
|
"🇺🇸 美国"
|
|
];
|
|
const aiProxies = [];
|
|
for (
|
|
let i = 0;
|
|
i < aiRegions.length;
|
|
i++
|
|
) {
|
|
if (
|
|
existingRegions.indexOf(
|
|
aiRegions[i]
|
|
) !== -1
|
|
) {
|
|
aiProxies.push(
|
|
aiRegions[i]
|
|
);
|
|
}
|
|
}
|
|
if (
|
|
aiProxies.length > 0
|
|
) {
|
|
groups.push({
|
|
"name": GROUP_NAMES.AI,
|
|
"type": "url-test",
|
|
"proxies": aiProxies,
|
|
"url": TEST_URL,
|
|
"interval": GROUP_INTERVAL,
|
|
"timeout": GROUP_TIMEOUT,
|
|
"lazy": true,
|
|
"tolerance": GROUP_TOLERANCE,
|
|
"max-failed-times": 3
|
|
});
|
|
}
|
|
/*
|
|
* ========================================================
|
|
* 第四层:海外服务
|
|
* ========================================================
|
|
*/
|
|
const overseasOptions = [];
|
|
overseasOptions.push(
|
|
GROUP_NAMES.NODE_SELECT
|
|
);
|
|
if (
|
|
hasGroup(
|
|
existingRegions,
|
|
GROUP_NAMES.AUTO
|
|
)
|
|
) {
|
|
overseasOptions.push(
|
|
GROUP_NAMES.AUTO
|
|
);
|
|
}
|
|
if (
|
|
hasGroup(
|
|
existingRegions,
|
|
GROUP_NAMES.FALLBACK
|
|
)
|
|
) {
|
|
overseasOptions.push(
|
|
GROUP_NAMES.FALLBACK
|
|
);
|
|
}
|
|
groups.push(
|
|
createSelectGroup(
|
|
GROUP_NAMES.OVERSEAS,
|
|
overseasOptions
|
|
)
|
|
);
|
|
/*
|
|
* ========================================================
|
|
* 第五层:网络测试
|
|
* ========================================================
|
|
*/
|
|
const networkTestOptions = [
|
|
GROUP_NAMES.DIRECT,
|
|
GROUP_NAMES.NODE_SELECT
|
|
];
|
|
if (
|
|
existingRegions.length > 0
|
|
) {
|
|
networkTestOptions.push(
|
|
GROUP_NAMES.AUTO
|
|
);
|
|
}
|
|
groups.push(
|
|
createSelectGroup(
|
|
GROUP_NAMES.NETWORK_TEST,
|
|
networkTestOptions
|
|
)
|
|
);
|
|
/*
|
|
* ========================================================
|
|
* 第六层:代理服务
|
|
* ========================================================
|
|
*/
|
|
const proxyServiceOptions = [
|
|
GROUP_NAMES.NODE_SELECT
|
|
];
|
|
if (
|
|
existingRegions.length > 0
|
|
) {
|
|
proxyServiceOptions.push(
|
|
GROUP_NAMES.AUTO,
|
|
GROUP_NAMES.FALLBACK
|
|
);
|
|
}
|
|
proxyServiceOptions.push(
|
|
GROUP_NAMES.DIRECT
|
|
);
|
|
groups.push(
|
|
createSelectGroup(
|
|
GROUP_NAMES.PROXY_SERVICE,
|
|
proxyServiceOptions,
|
|
true
|
|
)
|
|
);
|
|
/*
|
|
* ========================================================
|
|
* 第七层:全球直连
|
|
* ========================================================
|
|
*/
|
|
groups.push(
|
|
createSelectGroup(
|
|
GROUP_NAMES.DIRECT,
|
|
[
|
|
"DIRECT"
|
|
]
|
|
)
|
|
);
|
|
/*
|
|
* ========================================================
|
|
* 第八层:广告拦截
|
|
* ========================================================
|
|
*/
|
|
groups.push(
|
|
createSelectGroup(
|
|
GROUP_NAMES.AD_BLOCK,
|
|
[
|
|
"REJECT"
|
|
]
|
|
)
|
|
);
|
|
/*
|
|
* ========================================================
|
|
* 第九层:兜底策略
|
|
* ========================================================
|
|
*/
|
|
const finalOptions = [];
|
|
if (
|
|
existingRegions.length > 0
|
|
) {
|
|
finalOptions.push(
|
|
GROUP_NAMES.NODE_SELECT
|
|
);
|
|
}
|
|
finalOptions.push(
|
|
GROUP_NAMES.DIRECT
|
|
);
|
|
groups.push(
|
|
createSelectGroup(
|
|
GROUP_NAMES.FINAL,
|
|
finalOptions,
|
|
true
|
|
)
|
|
);
|
|
return groups;
|
|
}
|
|
/* ============================================================
|
|
* 十二、规则集
|
|
* ============================================================
|
|
*/
|
|
const RULE_PROVIDERS = {
|
|
"ads": {
|
|
"type": "http",
|
|
"behavior": "domain",
|
|
"format": "text",
|
|
"path": "./rules/adss.list",
|
|
"url":
|
|
"https://fastly.jsdelivr.net/gh/DustinWin/ruleset_geodata@clash-ruleset/ads.list",
|
|
"interval": 86400
|
|
},
|
|
"applications": {
|
|
"type": "http",
|
|
"behavior": "classical",
|
|
"format": "text",
|
|
"path": "./rules/applicationss.list",
|
|
"url":
|
|
"https://fastly.jsdelivr.net/gh/DustinWin/ruleset_geodata@clash-ruleset/applications.list",
|
|
"interval": 86400
|
|
},
|
|
"private": {
|
|
"type": "http",
|
|
"behavior": "domain",
|
|
"format": "text",
|
|
"path": "./rules/privates.list",
|
|
"url":
|
|
"https://fastly.jsdelivr.net/gh/DustinWin/ruleset_geodata@clash-ruleset/private.list",
|
|
"filter": "^((?!openai).)*$",
|
|
"interval": 86400
|
|
},
|
|
"microsoft-cn": {
|
|
"type": "http",
|
|
"behavior": "domain",
|
|
"format": "text",
|
|
"path": "./rules/microsoft-cns.list",
|
|
"url":
|
|
"https://fastly.jsdelivr.net/gh/DustinWin/ruleset_geodata@clash-ruleset/microsoft-cn.list",
|
|
"interval": 86400
|
|
},
|
|
"openai": {
|
|
"type": "http",
|
|
"behavior": "domain",
|
|
"format": "text",
|
|
"path": "./rules/openais.list",
|
|
"url":
|
|
"https://cdn.jsdelivr.net/gh/DustinWin/ruleset_geodata@refs/heads/mihomo-ruleset/ai.list",
|
|
"interval": 86400
|
|
},
|
|
"apple-cn": {
|
|
"type": "http",
|
|
"behavior": "domain",
|
|
"format": "text",
|
|
"path": "./rules/apple-cns.list",
|
|
"url":
|
|
"https://fastly.jsdelivr.net/gh/DustinWin/ruleset_geodata@clash-ruleset/apple-cn.list",
|
|
"interval": 86400
|
|
},
|
|
"google-cn": {
|
|
"type": "http",
|
|
"behavior": "domain",
|
|
"format": "text",
|
|
"path": "./rules/google-cns.list",
|
|
"url":
|
|
"https://fastly.jsdelivr.net/gh/DustinWin/ruleset_geodata@clash-ruleset/google-cn.list",
|
|
"interval": 86400
|
|
},
|
|
"games-cn": {
|
|
"type": "http",
|
|
"behavior": "domain",
|
|
"format": "text",
|
|
"path": "./rules/games-cns.list",
|
|
"url":
|
|
"https://fastly.jsdelivr.net/gh/DustinWin/ruleset_geodata@clash-ruleset/games-cn.list",
|
|
"interval": 86400
|
|
},
|
|
"networktest": {
|
|
"type": "http",
|
|
"behavior": "classical",
|
|
"format": "text",
|
|
"path": "./rules/networktests.list",
|
|
"url":
|
|
"https://fastly.jsdelivr.net/gh/DustinWin/ruleset_geodata@clash-ruleset/networktest.list",
|
|
"interval": 86400
|
|
},
|
|
"proxy": {
|
|
"type": "http",
|
|
"behavior": "domain",
|
|
"format": "text",
|
|
"path": "./rules/proxys.list",
|
|
"url":
|
|
"https://fastly.jsdelivr.net/gh/y7478729/ruleset_geodata@clash-ruleset/proxy.list",
|
|
"interval": 86400
|
|
},
|
|
"cn": {
|
|
"type": "http",
|
|
"behavior": "domain",
|
|
"format": "text",
|
|
"path": "./rules/cns.list",
|
|
"url":
|
|
"https://fastly.jsdelivr.net/gh/DustinWin/ruleset_geodata@clash-ruleset/cn.list",
|
|
"interval": 86400
|
|
},
|
|
"telegramip": {
|
|
"type": "http",
|
|
"behavior": "ipcidr",
|
|
"format": "text",
|
|
"path": "./rules/telegramips.list",
|
|
"url":
|
|
"https://fastly.jsdelivr.net/gh/DustinWin/ruleset_geodata@clash-ruleset/telegramip.list",
|
|
"interval": 86400
|
|
},
|
|
"privateip": {
|
|
"type": "http",
|
|
"behavior": "ipcidr",
|
|
"format": "text",
|
|
"path": "./rules/privateips.list",
|
|
"url":
|
|
"https://fastly.jsdelivr.net/gh/DustinWin/ruleset_geodata@clash-ruleset/privateip.list",
|
|
"interval": 86400
|
|
},
|
|
"cnip": {
|
|
"type": "http",
|
|
"behavior": "ipcidr",
|
|
"format": "text",
|
|
"path": "./rules/cnips.list",
|
|
"url":
|
|
"https://fastly.jsdelivr.net/gh/DustinWin/ruleset_geodata@clash-ruleset/cnip.list",
|
|
"interval": 86400
|
|
}
|
|
};
|
|
/* ============================================================
|
|
* 十三、规则
|
|
* ============================================================
|
|
*/
|
|
const RULES = [
|
|
/*
|
|
* AI
|
|
*/
|
|
"RULE-SET,openai,🤖 人工智能",
|
|
/*
|
|
* 广告
|
|
*/
|
|
"RULE-SET,ads,🛑 广告拦截",
|
|
/*
|
|
* 软件
|
|
*/
|
|
"RULE-SET,applications,🎯 全球直连",
|
|
/*
|
|
* 私有网络
|
|
*/
|
|
"RULE-SET,private,🎯 全球直连",
|
|
/*
|
|
* Microsoft
|
|
*/
|
|
"RULE-SET,microsoft-cn,🌍 海外服务",
|
|
/*
|
|
* Apple
|
|
*/
|
|
"RULE-SET,apple-cn,🌍 海外服务",
|
|
/*
|
|
* Google
|
|
*/
|
|
"RULE-SET,google-cn,🌍 海外服务",
|
|
/*
|
|
* 游戏
|
|
*/
|
|
"RULE-SET,games-cn,🌍 海外服务",
|
|
/*
|
|
* 网络测试
|
|
*/
|
|
"RULE-SET,networktest,📈 网络测试",
|
|
/*
|
|
* 代理域名
|
|
*/
|
|
"RULE-SET,proxy,🪜 代理服务",
|
|
/*
|
|
* 中国域名
|
|
*/
|
|
"RULE-SET,cn,🎯 全球直连",
|
|
/*
|
|
* Telegram IP
|
|
*/
|
|
"RULE-SET,telegramip,🌍 海外服务,no-resolve",
|
|
/*
|
|
* 私有 IP
|
|
*/
|
|
"RULE-SET,privateip,🎯 全球直连,no-resolve",
|
|
/*
|
|
* 中国 IP
|
|
*/
|
|
"RULE-SET,cnip,🎯 全球直连,no-resolve",
|
|
/*
|
|
* 最终兜底
|
|
*/
|
|
"MATCH,🎯 兜底策略"
|
|
];
|
|
/* ============================================================
|
|
* 十四、主函数
|
|
* ============================================================
|
|
*/
|
|
function main(config) {
|
|
/*
|
|
* --------------------------------------------------------
|
|
* 1. 检查配置
|
|
* --------------------------------------------------------
|
|
*/
|
|
const proxyCount =
|
|
config &&
|
|
Array.isArray(
|
|
config.proxies
|
|
)
|
|
? config.proxies.length
|
|
: 0;
|
|
const providerCount =
|
|
config &&
|
|
config["proxy-providers"] &&
|
|
typeof config["proxy-providers"] === "object"
|
|
? Object.keys(
|
|
config["proxy-providers"]
|
|
).length
|
|
: 0;
|
|
/*
|
|
* 没有节点,也没有节点提供器。
|
|
*/
|
|
if (
|
|
proxyCount === 0 &&
|
|
providerCount === 0
|
|
) {
|
|
throw new Error(
|
|
"当前订阅没有找到任何代理节点或代理集合"
|
|
);
|
|
}
|
|
/*
|
|
* --------------------------------------------------------
|
|
* 2. 基础配置
|
|
* --------------------------------------------------------
|
|
*/
|
|
Object.assign(
|
|
config,
|
|
GENERAL_CONFIG
|
|
);
|
|
/*
|
|
* --------------------------------------------------------
|
|
* 3. Sniffer
|
|
* --------------------------------------------------------
|
|
*/
|
|
config["sniffer"] =
|
|
SNIFFER_CONFIG;
|
|
/*
|
|
* --------------------------------------------------------
|
|
* 4. TUN
|
|
* --------------------------------------------------------
|
|
*/
|
|
config["tun"] =
|
|
TUN_CONFIG;
|
|
/*
|
|
* --------------------------------------------------------
|
|
* 5. DNS
|
|
* --------------------------------------------------------
|
|
*/
|
|
config["dns"] =
|
|
DNS_CONFIG;
|
|
/*
|
|
* --------------------------------------------------------
|
|
* 6. 代理组
|
|
* --------------------------------------------------------
|
|
*/
|
|
config["proxy-groups"] =
|
|
createProxyGroups(
|
|
config
|
|
);
|
|
/*
|
|
* --------------------------------------------------------
|
|
* 7. 规则集
|
|
* --------------------------------------------------------
|
|
*/
|
|
config["rule-providers"] =
|
|
RULE_PROVIDERS;
|
|
/*
|
|
* --------------------------------------------------------
|
|
* 8. 规则
|
|
* --------------------------------------------------------
|
|
*/
|
|
config["rules"] =
|
|
RULES;
|
|
/*
|
|
* --------------------------------------------------------
|
|
* 9. 返回配置
|
|
* --------------------------------------------------------
|
|
*/
|
|
return config;
|
|
}
|