Skip to content

Commit 11ea2f8

Browse files
authored
Merge pull request cmliu#926 from cmliu/beta2.0
Beta2.0
2 parents a4e73aa + f464070 commit 11ea2f8

2 files changed

Lines changed: 22 additions & 15 deletions

File tree

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -118,7 +118,7 @@
118118
| :--- | :---: | :--- | :--- |
119119
| **ADMIN** || `123456` | 后台管理面板登录密码 |
120120
| **KEY** || `CMLiussss` | 快速订阅路径密钥,访问 `/CMLiussss` 即可快速获取节点 |
121-
| **UUID** || `90cd4a77-141a-43c9-991b-08263cfe9c10` | 强制固定UUID |
121+
| **UUID** || `90cd4a77-141a-43c9-991b-08263cfe9c10` | 强制固定UUID,只支持**UUIDv4**标准格式 |
122122
| **HOST** || `edt.pages.dev` | 强制固定伪装域名 |
123123
| **PATH** || `/` | 强制固定伪装路径 |
124124
| **PROXYIP** || `proxyip.cmliussss.net:443` | 全局自定义反代 IP |

_worker.js

Lines changed: 21 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { connect } from "cloudflare:sockets";
22
let config_JSON, 反代IP = '', 启用SOCKS5反代 = null, 启用SOCKS5全局反代 = false, 我的SOCKS5账号 = '', parsedSocks5Address = {};
3-
let 缓存反代IP, 缓存反代解析数组, 缓存反代数组索引 = 0, 启用反代兜底 = true, ECH_DOH = 'https://doh.cmliussss.net/CMLiussss';
3+
let 缓存反代IP, 缓存反代解析数组, 缓存反代数组索引 = 0, 启用反代兜底 = true;
44
let SOCKS5白名单 = ['*tapecontent.net', '*cloudatacdn.com', '*loadshare.org', '*cdn-centaurus.com', 'scholar.google.com'];
55
const Pages静态页面 = 'https://edt-pages.github.io';
66
///////////////////////////////////////////////////////主程序入口///////////////////////////////////////////////
@@ -24,7 +24,6 @@ export default {
2424
} else 反代IP = (request.cf.colo + '.PrOxYIp.CmLiUsSsS.nEt').toLowerCase();
2525
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';
2626
if (env.GO2SOCKS5) SOCKS5白名单 = await 整理成数组(env.GO2SOCKS5);
27-
ECH_DOH = env.ECH_DOH || env.DOH || ECH_DOH;
2827
if (!upgradeHeader || upgradeHeader !== 'websocket') {
2928
if (url.protocol === 'http:') return Response.redirect(url.href.replace(`http://${url.hostname}`, `https://${url.hostname}`), 301);
3029
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 {
280279
return new Response('优选订阅生成器异常:' + error.message, { status: 403 });
281280
}
282281
}
283-
const ECHLINK参数 = config_JSON.ECH ? `&ech=${encodeURIComponent('cloudflare-ech.com+' + ECH_DOH)}` : '';
282+
const ECHLINK参数 = config_JSON.ECH ? `&ech=${encodeURIComponent((config_JSON.ECHConfig.SNI ? config_JSON.ECHConfig.SNI + '+' : '') + config_JSON.ECHConfig.DNS)}` : '';
284283
订阅内容 = 其他节点LINK + 完整优选IP.map(原始地址 => {
285284
// 统一正则: 匹配 域名/IPv4/IPv6地址 + 可选端口 + 可选备注
286285
// 示例:
@@ -322,10 +321,10 @@ export default {
322321
if (订阅类型 === 'mixed' && (!ua.includes('mozilla') || url.searchParams.has('b64') || url.searchParams.has('base64'))) 订阅内容 = btoa(订阅内容);
323322

324323
if (订阅类型 === 'singbox') {
325-
订阅内容 = Singbox订阅配置文件热补丁(订阅内容, config_JSON.UUID, config_JSON.Fingerprint, config_JSON.ECH ? await getECH(host) : null);
324+
订阅内容 = Singbox订阅配置文件热补丁(订阅内容, config_JSON.UUID, config_JSON.Fingerprint, config_JSON.ECH ? await getECH(config_JSON.ECHConfig.SNI || host) : null);
326325
responseHeaders["content-type"] = 'application/json; charset=utf-8';
327326
} else if (订阅类型 === 'clash') {
328-
订阅内容 = Clash订阅配置文件热补丁(订阅内容, config_JSON.UUID, config_JSON.ECH, config_JSON.HOSTS);
327+
订阅内容 = Clash订阅配置文件热补丁(订阅内容, config_JSON.UUID, config_JSON.ECH, config_JSON.HOSTS, config_JSON.ECHConfig.SNI, config_JSON.ECHConfig.DNS);
329328
responseHeaders["content-type"] = 'application/x-yaml; charset=utf-8';
330329
}
331330
return new Response(订阅内容, { status: 200, headers: responseHeaders });
@@ -786,7 +785,7 @@ async function httpConnect(targetHost, targetPort, initialData) {
786785
}
787786
}
788787
//////////////////////////////////////////////////功能性函数///////////////////////////////////////////////
789-
function Clash订阅配置文件热补丁(Clash_原始订阅内容, uuid = null, ECH启用 = false, HOSTS = []) {
788+
function Clash订阅配置文件热补丁(Clash_原始订阅内容, uuid = null, ECH启用 = false, HOSTS = [], ECH_SNI = null, ECH_DNS) {
790789
let clash_yaml = Clash_原始订阅内容.replace(/mode:\s*Rule\b/g, 'mode: rule');
791790

792791
// 基础 DNS 配置块(不含 nameserver-policy)
@@ -821,10 +820,13 @@ function Clash订阅配置文件热补丁(Clash_原始订阅内容, uuid = null,
821820
clash_yaml = baseDnsBlock + clash_yaml;
822821
}
823822

823+
// 如果 ECH_SNI 存在,添加到 HOSTS 数组中
824+
if (ECH_SNI && !HOSTS.includes(ECH_SNI)) HOSTS.push(ECH_SNI);
825+
824826
// 如果 ECH 启用且 HOSTS 有效,添加 nameserver-policy
825827
if (ECH启用 && HOSTS.length > 0) {
826828
// 生成 HOSTS 的 nameserver-policy 条目
827-
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');
829+
const hostsEntries = HOSTS.map(host => ` "${host}":\n - tls://223.5.5.5\n - tls://8.8.8.8\n - https://doh.090227.xyz/CMLiussss${ECH_DNS ? `\n - ${ECH_DNS}` : ''}`).join('\n');
828830

829831
// 检查是否存在 nameserver-policy:
830832
const hasNameserverPolicy = /^\s{2}nameserver-policy:\s*(?:\n|$)/m.test(clash_yaml);
@@ -908,7 +910,7 @@ function Clash订阅配置文件热补丁(Clash_原始订阅内容, uuid = null,
908910

909911
if (credentialMatch && credentialMatch[1].trim() === uuid.trim()) {
910912
// 在最后一个}前添加ech-opts
911-
fullNode = fullNode.replace(/\}(\s*)$/, `, ech-opts: {enable: true}}$1`);
913+
fullNode = fullNode.replace(/\}(\s*)$/, `, ech-opts: {enable: true${ECH_SNI ? `, query-server-name: ${ECH_SNI}` : ''}}}$1`);
912914
}
913915

914916
processedLines.push(fullNode);
@@ -981,10 +983,12 @@ function Clash订阅配置文件热补丁(Clash_原始订阅内容, uuid = null,
981983
if (insertIndex >= 0) {
982984
const indent = ' '.repeat(topLevelIndent);
983985
// 在节点末尾(最后一个属性块之后)插入 ech-opts 属性
984-
nodeLines.splice(insertIndex + 1, 0,
986+
const echOptsLines = [
985987
`${indent}ech-opts:`,
986988
`${indent} enable: true`
987-
);
989+
];
990+
if (ECH_SNI) echOptsLines.push(`${indent} query-server-name: ${ECH_SNI}`);
991+
nodeLines.splice(insertIndex + 1, 0, ...echOptsLines);
988992
}
989993
}
990994

@@ -1350,7 +1354,7 @@ async function getECH(host) {
13501354

13511355
async function 读取config_JSON(env, hostname, userID, path, 重置配置 = false) {
13521356
//const host = 随机替换通配符(hostname);
1353-
const host = hostname;
1357+
const host = hostname, CM_DoH = "https://doh.cmliussss.net/CMLiussss";
13541358
const 初始化开始时间 = performance.now();
13551359
const 默认配置JSON = {
13561360
TIME: new Date().toISOString(),
@@ -1364,6 +1368,10 @@ async function 读取config_JSON(env, hostname, userID, path, 重置配置 = fal
13641368
TLS分片: null,
13651369
随机路径: false,
13661370
ECH: false,
1371+
ECHConfig: {
1372+
DNS: CM_DoH,
1373+
SNI: null,
1374+
},
13671375
Fingerprint: "chrome",
13681376
优选订阅生成: {
13691377
local: true, // true: 基于本地的优选地址 false: 优选订阅生成器
@@ -1433,8 +1441,8 @@ async function 读取config_JSON(env, hostname, userID, path, 重置配置 = fal
14331441
const TLS分片参数 = config_JSON.TLS分片 == 'Shadowrocket' ? `&fragment=${encodeURIComponent('1,40-60,30-50,tlshello')}` : config_JSON.TLS分片 == 'Happ' ? `&fragment=${encodeURIComponent('3,1,tlshello')}` : '';
14341442
if (!config_JSON.Fingerprint) config_JSON.Fingerprint = "chrome";
14351443
if (!config_JSON.ECH) config_JSON.ECH = false;
1436-
else config_JSON.优选订阅生成.SUBUpdateTime = 1; // 启用 ECH 时强制将订阅更新时间改为 1 小时
1437-
const ECHLINK参数 = config_JSON.ECH ? `&ech=${encodeURIComponent('cloudflare-ech.com+' + ECH_DOH)}` : '';
1444+
if (!config_JSON.ECHConfig) config_JSON.ECHConfig = { DNS: CM_DoH, SNI: null };
1445+
const ECHLINK参数 = config_JSON.ECH ? `&ech=${encodeURIComponent((config_JSON.ECHConfig.SNI ? config_JSON.ECHConfig.SNI + '+' : '') + config_JSON.ECHConfig.DNS)}` : '';
14381446
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)}`;
14391447
config_JSON.优选订阅生成.TOKEN = await MD5MD5(hostname + userID);
14401448

@@ -2078,4 +2086,3 @@ async function html1101(host, 访问IP) {
20782086
</body>
20792087
</html>`;
20802088
}
2081-

0 commit comments

Comments
 (0)