diff --git a/_worker.js b/_worker.js index 87e1b14..2405c07 100644 --- a/_worker.js +++ b/_worker.js @@ -1,6 +1,6 @@ import { connect } from "cloudflare:sockets"; let config_JSON, 反代IP = '', 启用SOCKS5反代 = null, 启用SOCKS5全局反代 = false, 我的SOCKS5账号 = '', parsedSocks5Address = {}; -let 缓存反代IP, 缓存反代解析数组, 缓存反代数组索引 = 0, 启用反代兜底 = true, ECH_DOH = 'https://doh.cmliussss.net/CMLiussss'; +let 缓存反代IP, 缓存反代解析数组, 缓存反代数组索引 = 0, 启用反代兜底 = true; let SOCKS5白名单 = ['*tapecontent.net', '*cloudatacdn.com', '*loadshare.org', '*cdn-centaurus.com', 'scholar.google.com']; const Pages静态页面 = 'https://edt-pages.github.io'; ///////////////////////////////////////////////////////主程序入口/////////////////////////////////////////////// @@ -24,7 +24,6 @@ export default { } else 反代IP = (request.cf.colo + '.PrOxYIp.CmLiUsSsS.nEt').toLowerCase(); const 访问IP = request.headers.get('X-Real-IP') || request.headers.get('CF-Connecting-IP') || request.headers.get('X-Forwarded-For') || request.headers.get('True-Client-IP') || request.headers.get('Fly-Client-IP') || request.headers.get('X-Appengine-Remote-Addr') || request.headers.get('X-Forwarded-For') || request.headers.get('X-Real-IP') || request.headers.get('X-Cluster-Client-IP') || request.cf?.clientTcpRtt || '未知IP'; if (env.GO2SOCKS5) SOCKS5白名单 = await 整理成数组(env.GO2SOCKS5); - ECH_DOH = env.ECH_DOH || env.DOH || ECH_DOH; if (!upgradeHeader || upgradeHeader !== 'websocket') { if (url.protocol === 'http:') return Response.redirect(url.href.replace(`http://${url.hostname}`, `https://${url.hostname}`), 301); if (!管理员密码) return fetch(Pages静态页面 + '/noADMIN').then(r => { const headers = new Headers(r.headers); headers.set('Cache-Control', 'no-store, no-cache, must-revalidate, proxy-revalidate'); headers.set('Pragma', 'no-cache'); headers.set('Expires', '0'); return new Response(r.body, { status: 404, statusText: r.statusText, headers }); }); @@ -280,7 +279,7 @@ export default { return new Response('优选订阅生成器异常:' + error.message, { status: 403 }); } } - const ECHLINK参数 = config_JSON.ECH ? `&ech=${encodeURIComponent('cloudflare-ech.com+' + ECH_DOH)}` : ''; + const ECHLINK参数 = config_JSON.ECH ? `&ech=${encodeURIComponent((config_JSON.ECHConfig.SNI ? config_JSON.ECHConfig.SNI + '+' : '') + config_JSON.ECHConfig.DNS)}` : ''; 订阅内容 = 其他节点LINK + 完整优选IP.map(原始地址 => { // 统一正则: 匹配 域名/IPv4/IPv6地址 + 可选端口 + 可选备注 // 示例: @@ -325,7 +324,7 @@ export default { 订阅内容 = Singbox订阅配置文件热补丁(订阅内容, config_JSON.UUID, config_JSON.Fingerprint, config_JSON.ECH ? await getECH(host) : null); responseHeaders["content-type"] = 'application/json; charset=utf-8'; } else if (订阅类型 === 'clash') { - 订阅内容 = Clash订阅配置文件热补丁(订阅内容, config_JSON.UUID, config_JSON.ECH, config_JSON.HOSTS); + 订阅内容 = Clash订阅配置文件热补丁(订阅内容, config_JSON.UUID, config_JSON.ECH, config_JSON.HOSTS, config_JSON.ECHConfig.SNI, config_JSON.ECHConfig.DNS); responseHeaders["content-type"] = 'application/x-yaml; charset=utf-8'; } return new Response(订阅内容, { status: 200, headers: responseHeaders }); @@ -786,7 +785,7 @@ async function httpConnect(targetHost, targetPort, initialData) { } } //////////////////////////////////////////////////功能性函数/////////////////////////////////////////////// -function Clash订阅配置文件热补丁(Clash_原始订阅内容, uuid = null, ECH启用 = false, HOSTS = []) { +function Clash订阅配置文件热补丁(Clash_原始订阅内容, uuid = null, ECH启用 = false, HOSTS = [], ECH_SNI = null, ECH_DNS) { let clash_yaml = Clash_原始订阅内容.replace(/mode:\s*Rule\b/g, 'mode: rule'); // 基础 DNS 配置块(不含 nameserver-policy) @@ -824,7 +823,7 @@ function Clash订阅配置文件热补丁(Clash_原始订阅内容, uuid = null, // 如果 ECH 启用且 HOSTS 有效,添加 nameserver-policy if (ECH启用 && HOSTS.length > 0) { // 生成 HOSTS 的 nameserver-policy 条目 - const hostsEntries = HOSTS.map(host => ` "${host}":\n - tls://223.5.5.5\n - tls://8.8.8.8\n - https://doh.cmliussss.com/CMLiussss\n - ${ECH_DOH}`).join('\n'); + const hostsEntries = HOSTS.map(host => ` "${host}":\n - tls://223.5.5.5\n - tls://8.8.8.8\n - https://doh.cmliussss.com/CMLiussss${ECH_DNS ? `\n - ${ECH_DNS}` : ''}`).join('\n'); // 检查是否存在 nameserver-policy: const hasNameserverPolicy = /^\s{2}nameserver-policy:\s*(?:\n|$)/m.test(clash_yaml); @@ -908,7 +907,7 @@ function Clash订阅配置文件热补丁(Clash_原始订阅内容, uuid = null, if (credentialMatch && credentialMatch[1].trim() === uuid.trim()) { // 在最后一个}前添加ech-opts - fullNode = fullNode.replace(/\}(\s*)$/, `, ech-opts: {enable: true, query-server-name: cloudflare-ech.com}}$1`); + fullNode = fullNode.replace(/\}(\s*)$/, `, ech-opts: {enable: true${ECH_SNI ? `, query-server-name: ${ECH_SNI}` : ''}}}$1`); } processedLines.push(fullNode); @@ -981,11 +980,12 @@ function Clash订阅配置文件热补丁(Clash_原始订阅内容, uuid = null, if (insertIndex >= 0) { const indent = ' '.repeat(topLevelIndent); // 在节点末尾(最后一个属性块之后)插入 ech-opts 属性 - nodeLines.splice(insertIndex + 1, 0, + const echOptsLines = [ `${indent}ech-opts:`, - `${indent} enable: true`, - `${indent} query-server-name: cloudflare-ech.com` - ); + `${indent} enable: true` + ]; + if (ECH_SNI) echOptsLines.push(`${indent} query-server-name: ${ECH_SNI}`); + nodeLines.splice(insertIndex + 1, 0, ...echOptsLines); } } @@ -1351,7 +1351,7 @@ async function getECH(host) { async function 读取config_JSON(env, hostname, userID, path, 重置配置 = false) { //const host = 随机替换通配符(hostname); - const host = hostname; + const host = hostname, CM_DoH = "https://doh.cmliussss.net/CMLiussss"; const 初始化开始时间 = performance.now(); const 默认配置JSON = { TIME: new Date().toISOString(), @@ -1365,6 +1365,10 @@ async function 读取config_JSON(env, hostname, userID, path, 重置配置 = fal TLS分片: null, 随机路径: false, ECH: false, + ECHConfig: { + DNS: CM_DoH, + SNI: null, + }, Fingerprint: "chrome", 优选订阅生成: { local: true, // true: 基于本地的优选地址 false: 优选订阅生成器 @@ -1434,8 +1438,8 @@ async function 读取config_JSON(env, hostname, userID, path, 重置配置 = fal const TLS分片参数 = config_JSON.TLS分片 == 'Shadowrocket' ? `&fragment=${encodeURIComponent('1,40-60,30-50,tlshello')}` : config_JSON.TLS分片 == 'Happ' ? `&fragment=${encodeURIComponent('3,1,tlshello')}` : ''; if (!config_JSON.Fingerprint) config_JSON.Fingerprint = "chrome"; if (!config_JSON.ECH) config_JSON.ECH = false; - else config_JSON.优选订阅生成.SUBUpdateTime = 1; // 启用 ECH 时强制将订阅更新时间改为 1 小时 - const ECHLINK参数 = config_JSON.ECH ? `&ech=${encodeURIComponent('cloudflare-ech.com+' + ECH_DOH)}` : ''; + if (!config_JSON.ECHConfig) config_JSON.ECHConfig = { DNS: CM_DoH, SNI: null }; + const ECHLINK参数 = config_JSON.ECH ? `&ech=${encodeURIComponent((config_JSON.ECHConfig.SNI ? config_JSON.ECHConfig.SNI + '+' : '') + config_JSON.ECHConfig.DNS)}` : ''; config_JSON.LINK = `${config_JSON.协议类型}://${userID}@${host}:443?security=tls&type=${config_JSON.传输协议 + ECHLINK参数}&host=${host}&fp=${config_JSON.Fingerprint}&sni=${host}&path=${encodeURIComponent(config_JSON.启用0RTT ? config_JSON.PATH + '?ed=2560' : config_JSON.PATH) + TLS分片参数}&encryption=none${config_JSON.跳过证书验证 ? '&insecure=1&allowInsecure=1' : ''}#${encodeURIComponent(config_JSON.优选订阅生成.SUBNAME)}`; config_JSON.优选订阅生成.TOKEN = await MD5MD5(hostname + userID);