// from https://github.com/xixu-me/META // ################################################### this section can be flexibly customized ################################################### // Number of STATIC proxy groups (for IP-sensitive services) const STATIC_PROXY_COUNT = 4; // Routing rules are matched in order from top to bottom, with the rule at the top of the list taking precedence over the rules below it. const services = [ // Media & Content { name: "bilibili", tld: "com" }, { name: "Netflix", tld: "com" }, { name: "YouTube", tld: "com" }, // AI/LLM Services { name: "Anthropic", tld: "com" }, { name: "Arco", domain: "www.youware.com" }, { name: "Gemini", tld: "google", alias: "Google-Gemini" }, { name: "OpenAI", tld: "com" }, { name: "xAI", tld: "ai", sld: "x" }, // Social Media & Communication { name: "Douyin", domain: "douyin.com", alias: "Douyin" }, { name: "rednote", domain: "xiaohongshu.com", alias: "Xiaohongshu" }, { name: "Telegram", tld: "org" }, { name: "Truth Social", tld: "com", sld: "truthsocial", alias: "TruthSocial", }, { name: "X", tld: "com" }, // Financial Services { name: "Binance", tld: "com" }, { name: "Bybit", tld: "com" }, { name: "OKX", tld: "com" }, // Technology Companies { name: "Apple", tld: "com" }, { name: "Google", tld: "google", sld: "about" }, { name: "Microsoft", tld: "com" }, // Infrastructure { name: "Speedtest", tld: "net" }, { name: "Xget", domain: "xuc.xi-xu.me" }, { name: "Cloudflare", tld: "com" }, ]; const LOCATION_ICON_SET_URL = "https://img.icons8.com/color/144/"; const locations = [ { name: "Argentina ๐Ÿ‡ฆ๐Ÿ‡ท", icon: `${LOCATION_ICON_SET_URL}argentina`, keywords: ["้˜ฟๆ นๅปท", "Argentina"], codes: ["ARG", "AR"], emoji: ["๐Ÿ‡ฆ๐Ÿ‡ท"], }, { name: "Canada ๐Ÿ‡จ๐Ÿ‡ฆ", icon: `${LOCATION_ICON_SET_URL}canada`, keywords: ["ๅŠ ๆ‹ฟๅคง", "Canada"], codes: ["CAN", "CA"], emoji: ["๐Ÿ‡จ๐Ÿ‡ฆ"], }, { name: "Finland ๐Ÿ‡ซ๐Ÿ‡ฎ", icon: `${LOCATION_ICON_SET_URL}finland`, keywords: ["่Šฌๅ…ฐ", "Finland"], codes: ["FIN", "FI"], emoji: ["๐Ÿ‡ซ๐Ÿ‡ฎ"], }, { name: "France ๐Ÿ‡ซ๐Ÿ‡ท", icon: `${LOCATION_ICON_SET_URL}france`, keywords: ["ๆณ•ๅ›ฝ", "France"], codes: ["FR"], emoji: ["๐Ÿ‡ซ๐Ÿ‡ท"], }, { name: "Germany ๐Ÿ‡ฉ๐Ÿ‡ช", icon: `${LOCATION_ICON_SET_URL}germany`, keywords: ["ๅพทๅ›ฝ", "Germany"], codes: ["GER", "DE"], emoji: ["๐Ÿ‡ฉ๐Ÿ‡ช"], }, { name: "Hong Kong, China ๐Ÿ‡ญ๐Ÿ‡ฐ", icon: `${LOCATION_ICON_SET_URL}hongkong-circular`, keywords: ["้ฆ™ๆธฏ", "Hong Kong"], codes: ["HK"], emoji: ["๐Ÿ‡ญ๐Ÿ‡ฐ"], }, { name: "India ๐Ÿ‡ฎ๐Ÿ‡ณ", icon: `${LOCATION_ICON_SET_URL}india`, keywords: ["ๅฐๅบฆ", "India"], codes: ["IND", "IN"], emoji: ["๐Ÿ‡ฎ๐Ÿ‡ณ"], }, { name: "Iraq ๐Ÿ‡ฎ๐Ÿ‡ถ", icon: `${LOCATION_ICON_SET_URL}iraq`, keywords: ["ไผŠๆ‹‰ๅ…‹", "Iraq"], codes: ["IQ"], emoji: ["๐Ÿ‡ฎ๐Ÿ‡ถ"], }, { name: "Japan ๐Ÿ‡ฏ๐Ÿ‡ต", icon: `${LOCATION_ICON_SET_URL}japan`, keywords: ["ๆ—ฅๆœฌ", "Japan"], codes: ["JP"], emoji: ["๐Ÿ‡ฏ๐Ÿ‡ต"], }, { name: "Korea ๐Ÿ‡ฐ๐Ÿ‡ท", icon: `${LOCATION_ICON_SET_URL}south-korea`, keywords: ["้Ÿฉๅ›ฝ", "Korea"], codes: ["KR"], emoji: ["๐Ÿ‡ฐ๐Ÿ‡ท"], }, { name: "Russia ๐Ÿ‡ท๐Ÿ‡บ", icon: `${LOCATION_ICON_SET_URL}russian-federation`, keywords: ["ไฟ„็ฝ—ๆ–ฏ", "Russia Federation", "Russia"], codes: ["RU"], emoji: ["๐Ÿ‡ท๐Ÿ‡บ"], }, { name: "Singapore ๐Ÿ‡ธ๐Ÿ‡ฌ", icon: `${LOCATION_ICON_SET_URL}singapore`, keywords: ["ๆ–ฐๅŠ ๅก", "Singapore"], codes: ["SG"], emoji: ["๐Ÿ‡ธ๐Ÿ‡ฌ"], }, { name: "Taiwan, China ๐Ÿ‡จ๐Ÿ‡ณ", icon: `${LOCATION_ICON_SET_URL}china-circular`, keywords: ["ๅฐๆนพ", "Taiwan"], codes: ["TW"], emoji: ["๐Ÿ‡น๐Ÿ‡ผ"], }, { name: "Thailand ๐Ÿ‡น๐Ÿ‡ญ", icon: `${LOCATION_ICON_SET_URL}thailand`, keywords: ["ๆณฐๅ›ฝ", "Thailand"], codes: ["TH"], emoji: ["๐Ÿ‡น๐Ÿ‡ญ"], }, { name: "Tรผrkiye ๐Ÿ‡น๐Ÿ‡ท", icon: `${LOCATION_ICON_SET_URL}turkey`, keywords: ["ๅœŸ่€ณๅ…ถ", "Tรผrkiye", "Turkey"], codes: ["TUR", "TR"], emoji: ["๐Ÿ‡น๐Ÿ‡ท"], }, { name: "Ukraine ๐Ÿ‡บ๐Ÿ‡ฆ", icon: `${LOCATION_ICON_SET_URL}ukraine`, keywords: ["ไนŒๅ…‹ๅ…ฐ", "Ukraine"], codes: ["UKR", "UA"], emoji: ["๐Ÿ‡บ๐Ÿ‡ฆ"], }, { name: "United Kingdom ๐Ÿ‡ฌ๐Ÿ‡ง", icon: `${LOCATION_ICON_SET_URL}great-britain`, keywords: ["่‹ฑๅ›ฝ", "United Kingdom", "Great Britain"], codes: ["UK", "GB"], emoji: ["๐Ÿ‡ฌ๐Ÿ‡ง"], }, { name: "United States ๐Ÿ‡บ๐Ÿ‡ธ", icon: `${LOCATION_ICON_SET_URL}usa`, keywords: ["็พŽๅ›ฝ", "United States of America", "United States"], codes: ["USA", "US"], emoji: ["๐Ÿ‡บ๐Ÿ‡ธ"], }, { name: "Global ๐ŸŒ", icon: "https://img.icons8.com/?size=144&id=3685&format=png&color=7bbbe9", keywords: ["Global", "Cloudflare"], codes: ["GL", "CF"], emoji: ["๐ŸŒ"], }, ]; // ####################################### DO NOT MODIFY THE CODE BELOW UNLESS YOU KNOW WHAT YOU ARE DOING ####################################### function extractFavicon(domain) { return `https://t1.gstatic.com/faviconV2?client=SOCIAL&type=FAVICON&fallback_opts=TYPE,SIZE,URL&url=https://${domain}&size=128`; } function escapeRegex(text) { return text.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"); } function buildLocationFilter({ keywords = [], codes = [], emoji = [] }) { const patterns = [ ...keywords.map((keyword) => escapeRegex(keyword)), ...codes.map((code) => `\\b${escapeRegex(code)}\\b`), ...emoji.map((symbol) => escapeRegex(symbol)), ]; return `(?i)${patterns.join("|")}`; } locations.forEach((location) => { location.filter = buildLocationFilter(location); }); // General Configuration const generalConfig = { "mixed-port": 7890, "allow-lan": false, mode: "rule", "log-level": "info", ipv6: true, "find-process-mode": "strict", profile: { "store-selected": true, "store-fake-ip": true, }, "unified-delay": true, "tcp-concurrent": true, "global-ua": "\u0063\u006c\u0061\u0073\u0068.\u006D\u0065\u0074\u0061", "etag-support": true, }; // DNS const chineseNameservers = [ "https://dns.alidns.com/dns-query", "https://doh.pub/dns-query", ]; const internationalNameservers = [ "https://cloudflare-dns.com/dns-query", "https://dns.google/dns-query", // "https://dns.mullvad.net/dns-query", // "https://wikimedia-dns.org/dns-query", // "https://doh.dns.sb/dns-query", ]; const dns = { enable: true, "cache-algorithm": "arc", "prefer-h3": false, "use-hosts": true, "use-system-hosts": false, "respect-rules": true, ipv6: true, "enhanced-mode": "fake-ip", "fake-ip-range": "198.18.0.1/16", "fake-ip-range6": "fd00::/18", "fake-ip-filter-mode": "blacklist", "fake-ip-filter": [ "rule-set:fake-ip-filter", "rule-set:direct", "rule-set:private", "rule-set:connectivity-check", ], "default-nameserver": [ "tls://223.5.5.5", "tls://223.6.6.6", "tls://119.29.29.29", ], "proxy-server-nameserver": chineseNameservers, "nameserver-policy": { "rule-set:private": ["system://"], "rule-set:direct,geolocation-cn": chineseNameservers, }, nameserver: internationalNameservers, }; // Hosts const hosts = {}; // Domain Sniffing const sniffer = { enable: false, }; // TUN const tun = { enable: true, stack: "mixed", "auto-route": true, "auto-detect-interface": true, "strict-route": true, "dns-hijack": ["any:53", "tcp://any:53"], }; // Proxy Groups const proxyGroupDefaults = { url: "https://www.gstatic.com/generate_204", interval: 300, lazy: true, timeout: 5000, "max-failed-times": 5, }; // Generate STATIC proxy group names function generateStaticProxyNames() { if (STATIC_PROXY_COUNT === 1) { return ["STATIC"]; } return Array.from( { length: STATIC_PROXY_COUNT }, (_, i) => `STATIC-${i + 1}`, ); } const staticProxyNames = generateStaticProxyNames(); const serviceProxyGroupProxies = [ "PROXY", ...staticProxyNames, "AUTO", "DIRECT", "Chinese Mainland ๐Ÿ‡จ๐Ÿ‡ณ", ...locations.map(({ name }) => name), ]; const locationPolicyProxyGroupDefaults = { ...proxyGroupDefaults, proxies: ["REJECT"], "include-all": true, }; const SERVICE_ICON_SET_URL = "https://cdn.jsdelivr.net/gh/xixu-me/favicons@assets/favicons/"; function getServiceIcon(service) { if (service.icon) return service.icon; if (service.domain) return extractFavicon(service.domain); if (service.tld) { const secondLevelDomain = service.sld || service.name.toLowerCase(); return `${SERVICE_ICON_SET_URL}${secondLevelDomain}.${service.tld}.png`; } console.warn(`No icon configuration for service: ${service.name}`); return null; } services.forEach((service) => { service.icon = getServiceIcon(service); }); function generateServiceProxyGroups(items, defaultConfig) { return items.map(({ name, icon }) => ({ ...defaultConfig, name, icon, type: "select", proxies: serviceProxyGroupProxies, })); } function generateLocationPolicyProxyGroups( items, defaultConfig, type, extraProps = {}, ) { const getStrategyName = (type, strategy) => { switch (type) { case "url-test": return "AUTO"; case "fallback": return "FALLBACK"; case "load-balance": switch (strategy) { case "consistent-hashing": return "LOAD BALANCING (consistent hashing)"; case "round-robin": return "LOAD BALANCING (round-robin)"; case "sticky-sessions": return "LOAD BALANCING (sticky sessions)"; default: return "LOAD BALANCING"; } default: return type.toUpperCase(); } }; return items.map(({ name, icon, filter }) => { const strategyName = getStrategyName(type, extraProps.strategy); const emoji = name.split(" ").pop(); const newName = `${strategyName} ${emoji}`; return { ...defaultConfig, name: newName, type, icon, filter, hidden: true, ...extraProps, }; }); } function generateLocationSelectProxyGroups() { return locations.map(({ name, icon }) => ({ ...proxyGroupDefaults, name, type: "select", icon, proxies: [ `LOAD BALANCING (consistent hashing) ${name.split(" ").pop()}`, `LOAD BALANCING (round-robin) ${name.split(" ").pop()}`, `LOAD BALANCING (sticky sessions) ${name.split(" ").pop()}`, `FALLBACK ${name.split(" ").pop()}`, `AUTO ${name.split(" ").pop()}`, ], })); } const BASE_ICON_SET_URL = "https://cdn.jsdelivr.net/gh/Koolson/Qure@master/IconSet/Color/"; // Generate STATIC proxy groups function generateStaticProxyGroups(defaultConfig) { return staticProxyNames.map((name, index) => ({ ...defaultConfig, name, type: "select", "include-all": true, icon: `${BASE_ICON_SET_URL}Static.png`, })); } const proxyGroups = [ { ...proxyGroupDefaults, name: "PROXY", type: "select", proxies: [ ...staticProxyNames, "AUTO", "DIRECT", "Chinese Mainland ๐Ÿ‡จ๐Ÿ‡ณ", ...locations.map(({ name }) => name), ], icon: `${BASE_ICON_SET_URL}Proxy.png`, }, { ...proxyGroupDefaults, name: "AUTO", type: "url-test", tolerance: 50, "include-all": true, icon: `${BASE_ICON_SET_URL}Auto.png`, hidden: true, }, ...generateStaticProxyGroups(proxyGroupDefaults), ...generateServiceProxyGroups(services, proxyGroupDefaults), { ...proxyGroupDefaults, name: "Domestic", type: "select", proxies: [ "DIRECT", "PROXY", ...staticProxyNames, "AUTO", "Chinese Mainland ๐Ÿ‡จ๐Ÿ‡ณ", ...locations.map(({ name }) => name), ], icon: `${BASE_ICON_SET_URL}Domestic.png`, }, { ...proxyGroupDefaults, name: "Others", type: "select", proxies: [...serviceProxyGroupProxies], icon: `${BASE_ICON_SET_URL}Final.png`, }, { ...proxyGroupDefaults, name: "Advertising", type: "select", proxies: ["REJECT", "DIRECT", ...staticProxyNames], icon: `${BASE_ICON_SET_URL}Advertising.png`, }, { ...locationPolicyProxyGroupDefaults, name: "Chinese Mainland ๐Ÿ‡จ๐Ÿ‡ณ", type: "select", icon: `${LOCATION_ICON_SET_URL}china`, proxies: ["REJECT"], "include-all": true, filter: "(?i)\u5927\u9646|\u4e2d\u56fd|\u7535\u4fe1|\u79fb\u52a8|\u8054\u901a|Mainland|China|CN|mainland|china|cn|๐Ÿ‡จ๐Ÿ‡ณ", }, ...generateLocationPolicyProxyGroups( locations, locationPolicyProxyGroupDefaults, "url-test", { tolerance: 50, }, ), ...generateLocationPolicyProxyGroups( locations, locationPolicyProxyGroupDefaults, "fallback", ), ...generateLocationPolicyProxyGroups( locations, locationPolicyProxyGroupDefaults, "load-balance", { strategy: "round-robin", }, ), ...generateLocationPolicyProxyGroups( locations, locationPolicyProxyGroupDefaults, "load-balance", { strategy: "consistent-hashing", }, ), ...generateLocationPolicyProxyGroups( locations, locationPolicyProxyGroupDefaults, "load-balance", { strategy: "sticky-sessions", }, ), ...generateLocationSelectProxyGroups(), ]; // Routing Rules function generateServiceRules(services) { return services.map( ({ name }) => `RULE-SET,${name.toLowerCase().replace(/\s+/g, "")},${name}`, ); } const rules = [ "RULE-SET,applications,DIRECT", "RULE-SET,win-phonelink,DIRECT", "RULE-SET,lancidr,DIRECT,no-resolve", "RULE-SET,private,DIRECT", ...generateServiceRules(services), "RULE-SET,reject,Advertising", "RULE-SET,win-spy,Advertising", "RULE-SET,direct,Domestic", "RULE-SET,proxy,PROXY", "RULE-SET,telegramcidr,Telegram", "RULE-SET,xcidr,X", "RULE-SET,googlecidr,Google", "RULE-SET,cloudflarecidr,Cloudflare", "RULE-SET,cncidr,Domestic", "MATCH,Others", ]; // Rule Providers const ruleProviderDefaults = { type: "http", interval: 14400, }; function generateServiceRuleProviders(services, defaultConfig) { return services.reduce((acc, { name, alias }) => { const fileName = (alias || name).toLowerCase(); const ruleName = name.toLowerCase().replace(/\s+/g, ""); acc[ruleName] = { ...defaultConfig, format: "mrs", behavior: "domain", url: `https://cdn.jsdelivr.net/gh/xixu-me/RFM@universal/${fileName}.mrs`, path: `./rulesets/${ruleName}.mrs`, }; return acc; }, {}); } const ruleProviders = { "fake-ip-filter": { ...ruleProviderDefaults, format: "mrs", behavior: "domain", url: "https://cdn.jsdelivr.net/gh/xixu-me/RFM@basic/fake-ip-filter.mrs", path: "./rulesets/fake-ip-filter.mrs", }, "connectivity-check": { ...ruleProviderDefaults, format: "mrs", behavior: "domain", url: "https://cdn.jsdelivr.net/gh/xixu-me/RFM@universal/connectivity-check.mrs", path: "./rulesets/connectivity-check.mrs", }, applications: { ...ruleProviderDefaults, format: "yaml", behavior: "classical", url: "https://cdn.jsdelivr.net/gh/xixu-me/RFM@basic/applications.yaml", path: "./rulesets/applications.yaml", }, "win-phonelink": { ...ruleProviderDefaults, format: "yaml", behavior: "classical", url: "https://cdn.jsdelivr.net/gh/xixu-me/RFM@fixed/win-phonelink.yaml", path: "./rulesets/win-phonelink.yaml", }, lancidr: { ...ruleProviderDefaults, format: "mrs", behavior: "ipcidr", url: "https://cdn.jsdelivr.net/gh/xixu-me/RFM@basic/lancidr.mrs", path: "./rulesets/lancidr.mrs", }, cncidr: { ...ruleProviderDefaults, format: "mrs", behavior: "ipcidr", url: "https://cdn.jsdelivr.net/gh/xixu-me/RFM@basic/cncidr.mrs", path: "./rulesets/cncidr.mrs", }, cloudflarecidr: { ...ruleProviderDefaults, format: "mrs", behavior: "ipcidr", url: "https://cdn.jsdelivr.net/gh/xixu-me/RFM@basic/cloudflarecidr.mrs", path: "./rulesets/cloudflarecidr.mrs", }, googlecidr: { ...ruleProviderDefaults, format: "mrs", behavior: "ipcidr", url: "https://cdn.jsdelivr.net/gh/xixu-me/RFM@basic/googlecidr.mrs", path: "./rulesets/googlecidr.mrs", }, telegramcidr: { ...ruleProviderDefaults, format: "mrs", behavior: "ipcidr", url: "https://cdn.jsdelivr.net/gh/xixu-me/RFM@basic/telegramcidr.mrs", path: "./rulesets/telegramcidr.mrs", }, xcidr: { ...ruleProviderDefaults, format: "mrs", behavior: "ipcidr", url: "https://cdn.jsdelivr.net/gh/xixu-me/RFM@basic/xcidr.mrs", path: "./rulesets/xcidr.mrs", }, private: { ...ruleProviderDefaults, format: "mrs", behavior: "domain", url: "https://cdn.jsdelivr.net/gh/xixu-me/RFM@basic/private.mrs", path: "./rulesets/private.mrs", }, direct: { ...ruleProviderDefaults, format: "mrs", behavior: "domain", url: "https://cdn.jsdelivr.net/gh/xixu-me/RFM@basic/direct.mrs", path: "./rulesets/direct.mrs", }, proxy: { ...ruleProviderDefaults, format: "mrs", behavior: "domain", url: "https://cdn.jsdelivr.net/gh/xixu-me/RFM@basic/proxy.mrs", path: "./rulesets/proxy.mrs", }, "geolocation-cn": { ...ruleProviderDefaults, format: "mrs", behavior: "domain", url: "https://cdn.jsdelivr.net/gh/xixu-me/RFM@universal/geolocation-cn.mrs", path: "./rulesets/geolocation-cn.mrs", }, reject: { ...ruleProviderDefaults, format: "mrs", behavior: "domain", url: "https://cdn.jsdelivr.net/gh/xixu-me/RFM@basic/reject.mrs", path: "./rulesets/reject.mrs", }, "win-spy": { ...ruleProviderDefaults, format: "mrs", behavior: "domain", url: "https://cdn.jsdelivr.net/gh/xixu-me/RFM@universal/win-spy.mrs", path: "./rulesets/win-spy.mrs", }, ...generateServiceRuleProviders(services, ruleProviderDefaults), }; // generate configuration using the above settings function validateOriginalConfig(config) { if (!config) throw new Error("Configuration object cannot be null or undefined"); const proxyCount = Array.isArray(config.proxies) ? config.proxies.length : 0; const proxyProviderCount = Object.keys( config["proxy-providers"] || {}, ).length; if (proxyCount === 0 && proxyProviderCount === 0) throw new Error( "The original configuration must contain a non-empty proxies array (see https://wiki.\u006D\u0065\u0074\u0061\u0063\u0075\u0062\u0065\u0078.one/en/config/proxies/) or a proxy-providers object with at least one property (see https://wiki.\u006D\u0065\u0074\u0061\u0063\u0075\u0062\u0065\u0078.one/en/config/proxy-providers/)", ); if (proxyCount > 0) { const proxiesWithoutRemoteEndpoint = new Set([ "direct", "dns", "pass", "reject", ]); config.proxies.forEach((proxy, index) => { if (!proxy.name || !proxy.type) { throw new Error( `Invalid proxy number ${ index + 1 } configuration (see https://wiki.\u006D\u0065\u0074\u0061\u0063\u0075\u0062\u0065\u0078.one/en/config/proxies/)`, ); } if ( !proxiesWithoutRemoteEndpoint.has(String(proxy.type).toLowerCase()) && (!proxy.server || proxy.port == null) ) { throw new Error( `Invalid proxy number ${ index + 1 } configuration (see https://wiki.\u006D\u0065\u0074\u0061\u0063\u0075\u0062\u0065\u0078.one/en/config/proxies/)`, ); } }); console.log( `The original configuration contains ${proxyCount} proxies, which will be preserved`, ); } if (proxyProviderCount > 0) { Object.entries(config["proxy-providers"]).forEach( ([name, provider], index) => { if (!provider.type || (provider.type === "http" && !provider.url)) { throw new Error( `Invalid proxy provider number ${ index + 1 } configuration (see https://wiki.\u006D\u0065\u0074\u0061\u0063\u0075\u0062\u0065\u0078.one/en/config/proxy-providers/)`, ); } }, ); console.log( `The original configuration contains ${proxyProviderCount} proxy providers, which will be preserved`, ); } return true; } function main(config, options = {}) { try { if (!options.skipValidation) { validateOriginalConfig(config); } Object.assign(config, generalConfig, { dns, hosts, sniffer, tun, "proxy-groups": proxyGroups, rules, "rule-providers": ruleProviders, }); console.log("The generated configuration is as follows"); console.log(config); return config; } catch (error) { console.error( `An error occurred during configuration generation: ${error.message}`, ); return { error: error.message, originalConfig: config }; } }