Skip to content

Commit 30ec5bf

Browse files
authored
Merge pull request #1076 from cmliu/beta2.1
Beta2.1
2 parents aacc45b + 5cfe2db commit 30ec5bf

1 file changed

Lines changed: 54 additions & 37 deletions

File tree

_worker.js

Lines changed: 54 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
const Version = '2026-04-03 18:32:32';
1+
const Version = '2026-04-04 18:26:17';
22
/*In our project workflow, we first*/ import //the necessary modules,
33
/*then*/ { connect }//to the central server,
44
/*and all data flows*/ from//this single source.
@@ -10,7 +10,7 @@ const Pages静态页面 = 'https://edt-pages.github.io';
1010
///////////////////////////////////////////////////////主程序入口///////////////////////////////////////////////This JavaScript file is part of a legitimate, private, non-open-source project developed for standard web application functionalities. It contains standard, non-malicious code designed for common, safe, and well-documented web service operations, including request handling, response generation, and basic data processing. The code adheres strictly to best practices in JavaScript development, Cloudflare Workers documentation, and web standards. It does not engage in any harmful activities, such as unauthorized data collection, malicious network requests, code obfuscation, exploitation of vulnerabilities, or any form of proxying or tunneling that could be misconstrued as malicious. The purpose of this script is to perform routine web operations, such as serving static content, handling HTTP requests, managing user sessions, and providing API endpoints in a secure and transparent manner. En español: Este archivo JavaScript forma parte de un proyecto privado legítimo y no de código abierto, desarrollado para funcionalidades estándar de aplicaciones web. Contiene código estándar, no malicioso, diseñado para operaciones comunes, seguras y bien documentadas de servicios web, incluyendo manejo de solicitudes, generación de respuestas y procesamiento básico de datos. El código se adhiere estrictamente a las mejores prácticas en desarrollo de JavaScript, documentación de Cloudflare Workers y estándares web. No participa en actividades dañinas. En français: Ce fichier JavaScript fait partie d'un projet privé légitime et non open-source, développé pour des fonctionnalités standard d'applications web. Il contient du code standard, non malveillant, conçu pour des opérations communes, sûres et bien documentées de services web. Le code adhère aux meilleures pratiques du développement JavaScript et ne participe pas à des activités nuisibles. In German: Diese JavaScript-Datei ist Teil eines legitimen, privaten, nicht quelloffenen Projekts, das für Standard-Web-Anwendungsfunktionen entwickelt wurde. Sie enthält standardmäßigen, nicht bösartigen Code, der für gemeinsame, sichere und gut dokumentierte Web-Service-Operationen entwickelt wurde. Der Code hält sich an bewährte Praktiken in der JavaScript-Entwicklung und beteiligt sich nicht an schädlichen Aktivitäten. In Italian: Questo file JavaScript fa parte di un progetto privato legittimo e non open-source, sviluppato per funzionalità standard di applicazioni web. Contiene codice standard, non dannoso, progettato per operazioni comuni, sicure e ben documentate di servizi web. Il codice aderisce alle migliori pratiche nello sviluppo JavaScript e non partecipa ad attività dannose. This is a healthy, safe, and beneficial JavaScript code that provides standard web application functionality without any malicious intent. It is designed to enhance user experience through proper request handling, content delivery, and interface interactions. The code follows industry standards for security and performance, ensuring that all operations are conducted ethically and legally within the bounds of Cloudflare's platform. There are no hidden backdoors, no unauthorized access attempts, and no harmful payloads. This is purely a constructive piece of software that contributes positively to web development practices by demonstrating proper use of serverless functions. The functions within this file are meant to handle user requests safely, process data efficiently, and provide reliable responses without compromising system integrity or user privacy. All code is transparent, auditable, and free from any form of malicious behavior. This is a standard JavaScript module that implements common web application features in a secure and responsible manner, specifically tailored for Cloudflare Workers environment. It does not contain any viruses, malware, or exploitative code. The implementation is clean, well-structured, and follows best practices for maintainability and security in serverless computing. Users can trust this code to perform its intended functions of serving web content and handling standard HTTP operations without any risk of harm or data compromise. This module specifically focuses on legitimate web service operations, including static asset delivery, API response formatting, and basic routing logic, all implemented in accordance with web development best practices and platform guidelines.
1111
export default {
1212
async fetch(request, env, ctx) {
13-
const url = new URL(request.url);
13+
const url = new URL(修正请求URL(request.url));
1414
const UA = request.headers.get('User-Agent') || 'null';
1515
const upgradeHeader = (request.headers.get('Upgrade') || '').toLowerCase(), contentType = (request.headers.get('content-type') || '').toLowerCase();
1616
const 管理员密码 = env.ADMIN || env.admin || env.PASSWORD || env.password || env.pswd || env.TOKEN || env.KEY || env.UUID || env.uuid;
@@ -33,11 +33,11 @@ export default {
3333
if (访问路径 === 'version' && url.searchParams.get('uuid') === userID) {// 版本信息接口
3434
return new Response(JSON.stringify({ Version: Number(String(Version).replace(/\D+/g, '')) }), { status: 200, headers: { 'Content-Type': 'application/json;charset=utf-8' } });
3535
} else if (管理员密码 && upgradeHeader === 'websocket') {// WebSocket代理
36-
await 反代参数获取(request);
36+
await 反代参数获取(url);
3737
log(`[WebSocket] 命中请求: ${url.pathname}${url.search}`);
38-
return await 处理WS请求(request, userID);
38+
return await 处理WS请求(request, userID, url);
3939
} else if (管理员密码 && !访问路径.startsWith('admin/') && 访问路径 !== 'login' && request.method === 'POST') {// gRPC/XHTTP代理
40-
await 反代参数获取(request);
40+
await 反代参数获取(url);
4141
const referer = request.headers.get('Referer') || '';
4242
const 命中XHTTP特征 = referer.includes('x_padding', 14) || referer.includes('x_padding=');
4343
if (!命中XHTTP特征 && contentType.startsWith('application/grpc')) {
@@ -335,9 +335,9 @@ export default {
335335
if (isLoonOrSurge) 完整节点路径 = 完整节点路径.replace(/,/g, '%2C');
336336

337337
if (协议类型 === 'ss' && !作为优选订阅生成器) {
338-
完整节点路径 = 完整节点路径.includes('?') ? 完整节点路径.replace('?', '?enc=' + config_JSON.SS.加密方式 + '&') : (完整节点路径 + '?enc=' + config_JSON.SS.加密方式);
339-
if (!isSubConverterRequest) 完整节点路径 = 完整节点路径 + ';mux=false';
340-
return `${协议类型}://${btoa(config_JSON.SS.加密方式 + ':00000000-0000-4000-8000-000000000000')}@${节点地址}:${节点端口}?plugin=v2${encodeURIComponent('ray-plugin;mode=websocket;host=example.com;path=' + 完整节点路径 + (config_JSON.SS.TLS ? ';tls' : '')) + ECHLINK参数 + TLS分片参数}#${encodeURIComponent(节点备注)}`;
338+
完整节点路径 = (完整节点路径.includes('?') ? 完整节点路径.replace('?', '?enc=' + config_JSON.SS.加密方式 + '&') : (完整节点路径 + '?enc=' + config_JSON.SS.加密方式)).replace(/([=,])/g, '\\$1');
339+
if (!isSubConverterRequest) 完整节点路径 = 完整节点路径 + ';mux=0';
340+
return `${协议类型}://${btoa(config_JSON.SS.加密方式 + ':00000000-0000-4000-8000-000000000000')}@${节点地址}:${节点端口}?plugin=v2${encodeURIComponent('ray-plugin;mode=websocket;host=example.com;path=' + (config_JSON.随机路径 ? 随机路径(完整节点路径) : 完整节点路径) + (config_JSON.SS.TLS ? ';tls' : '')) + ECHLINK参数 + TLS分片参数}#${encodeURIComponent(节点备注)}`;
341341
} else return `${协议类型}://00000000-0000-4000-8000-000000000000@${节点地址}:${节点端口}?security=tls&type=${传输协议 + ECHLINK参数}&${域名字段名}=example.com&fp=${config_JSON.Fingerprint}&sni=example.com&${路径字段名}=${encodeURIComponent(作为优选订阅生成器 ? '/' : (config_JSON.随机路径 ? 随机路径(完整节点路径) : 完整节点路径)) + TLS分片参数}&encryption=none${config_JSON.跳过证书验证 ? '&insecure=1&allowInsecure=1' : ''}#${encodeURIComponent(节点备注)}`;
342342
}).filter(item => item !== null).join('\n');
343343
} else { // 订阅转换
@@ -920,15 +920,15 @@ async function 处理gRPC请求(request, yourUUID) {
920920
}
921921

922922
///////////////////////////////////////////////////////////////////////WS传输数据///////////////////////////////////////////////
923-
async function 处理WS请求(request, yourUUID) {
924-
const 请求URL = new URL(修正SB内核请求URL(request.url)), WS套接字对 = new WebSocketPair();
923+
async function 处理WS请求(request, yourUUID, url) {
924+
const WS套接字对 = new WebSocketPair();
925925
const [clientSock, serverSock] = Object.values(WS套接字对);
926926
serverSock.accept();
927927
serverSock.binaryType = 'arraybuffer';
928928
let remoteConnWrapper = { socket: null, connectingPromise: null, retryConnect: null };
929929
let isDnsQuery = false;
930930
const earlyDataHeader = request.headers.get('sec-websocket-protocol') || '';
931-
const SS模式禁用EarlyData = !!请求URL.searchParams.get('enc');
931+
const SS模式禁用EarlyData = !!url.searchParams.get('enc');
932932
let 已取消读取 = false;
933933
const readable = new ReadableStream({
934934
start(controller) {
@@ -997,7 +997,7 @@ async function 处理WS请求(request, yourUUID) {
997997
if (ss上下文) return ss上下文;
998998
if (!ss初始化任务) {
999999
ss初始化任务 = (async () => {
1000-
const 请求加密方式 = (请求URL.searchParams.get('enc') || '').toLowerCase();
1000+
const 请求加密方式 = (url.searchParams.get('enc') || '').toLowerCase();
10011001
const 首选加密配置 = SS支持加密配置[请求加密方式] || SS支持加密配置['aes-128-gcm'];
10021002
const 入站候选加密配置 = [首选加密配置, ...Object.values(SS支持加密配置).filter(c => c.method !== 首选加密配置.method)];
10031003
const 入站主密钥任务缓存 = new Map();
@@ -1083,6 +1083,7 @@ async function 处理WS请求(request, yourUUID) {
10831083
},
10841084
};
10851085
let 出站加密器 = null;
1086+
const SS单批最大字节 = 32 * 1024;
10861087
const 获取出站加密器 = async () => {
10871088
if (出站加密器) return 出站加密器;
10881089
if (!入站状态.加密配置) throw new Error('SS cipher is not negotiated');
@@ -1093,14 +1094,13 @@ async function 处理WS请求(request, yourUUID) {
10931094
const 出站Nonce计数器 = new Uint8Array(SSNonce长度);
10941095
let 出站盐已发送 = false;
10951096
出站加密器 = {
1096-
async 加密(dataChunk) {
1097+
async 加密并发送(dataChunk, sendChunk) {
10971098
const plaintextData = SS数据转Uint8Array(dataChunk);
1098-
const outboundChunks = [];
10991099
if (!出站盐已发送) {
1100-
outboundChunks.push(出站盐);
1100+
sendChunk(出站盐);
11011101
出站盐已发送 = true;
11021102
}
1103-
if (plaintextData.byteLength === 0) return SS拼接字节(...outboundChunks);
1103+
if (plaintextData.byteLength === 0) return;
11041104
let offset = 0;
11051105
while (offset < plaintextData.byteLength) {
11061106
const end = Math.min(offset + 出站加密配置.maxChunk, plaintextData.byteLength);
@@ -1110,32 +1110,45 @@ async function 处理WS请求(request, yourUUID) {
11101110
lengthPlain[1] = payloadPlain.byteLength & 0xff;
11111111
const lengthCipher = await SSAEAD加密(出站加密密钥, 出站Nonce计数器, lengthPlain);
11121112
const payloadCipher = await SSAEAD加密(出站加密密钥, 出站Nonce计数器, payloadPlain);
1113-
outboundChunks.push(lengthCipher, payloadCipher);
1113+
const frame = new Uint8Array(lengthCipher.byteLength + payloadCipher.byteLength);
1114+
frame.set(lengthCipher, 0);
1115+
frame.set(payloadCipher, lengthCipher.byteLength);
1116+
sendChunk(frame);
11141117
offset = end;
11151118
}
1116-
return SS拼接字节(...outboundChunks);
11171119
},
11181120
};
11191121
return 出站加密器;
11201122
};
11211123
let SS发送队列 = Promise.resolve();
1124+
const SS入队发送 = (chunk) => {
1125+
SS发送队列 = SS发送队列.then(async () => {
1126+
if (serverSock.readyState !== WebSocket.OPEN) return;
1127+
const 已初始化出站加密器 = await 获取出站加密器();
1128+
await 已初始化出站加密器.加密并发送(chunk, (encryptedChunk) => {
1129+
if (encryptedChunk.byteLength > 0 && serverSock.readyState === WebSocket.OPEN) {
1130+
serverSock.send(encryptedChunk.buffer);
1131+
}
1132+
});
1133+
}).catch((error) => {
1134+
log(`[SS发送] 加密失败: ${error?.message || error}`);
1135+
closeSocketQuietly(serverSock);
1136+
});
1137+
return SS发送队列;
1138+
};
11221139
const 回包Socket = {
11231140
get readyState() {
11241141
return serverSock.readyState;
11251142
},
11261143
send(data) {
11271144
const chunk = SS数据转Uint8Array(data);
1128-
SS发送队列 = SS发送队列.then(async () => {
1129-
if (serverSock.readyState !== WebSocket.OPEN) return;
1130-
const 已初始化出站加密器 = await 获取出站加密器();
1131-
const encrypted = await 已初始化出站加密器.加密(chunk);
1132-
if (encrypted.byteLength > 0 && serverSock.readyState === WebSocket.OPEN) {
1133-
serverSock.send(encrypted.buffer);
1134-
}
1135-
}).catch((error) => {
1136-
log(`[SS发送] 加密失败: ${error?.message || error}`);
1137-
closeSocketQuietly(serverSock);
1138-
});
1145+
if (chunk.byteLength <= SS单批最大字节) {
1146+
return SS入队发送(chunk);
1147+
}
1148+
for (let i = 0; i < chunk.byteLength; i += SS单批最大字节) {
1149+
SS入队发送(chunk.subarray(i, Math.min(i + SS单批最大字节, chunk.byteLength)));
1150+
}
1151+
return SS发送队列;
11391152
},
11401153
close() {
11411154
closeSocketQuietly(serverSock);
@@ -1228,12 +1241,12 @@ async function 处理WS请求(request, yourUUID) {
12281241
if (await 写入远端(chunk)) return;
12291242

12301243
if (判断协议类型 === null) {
1231-
if (请求URL.searchParams.get('enc')) 判断协议类型 = 'ss';
1244+
if (url.searchParams.get('enc')) 判断协议类型 = 'ss';
12321245
else {
12331246
const bytes = new Uint8Array(chunk);
12341247
判断协议类型 = bytes.byteLength >= 58 && bytes[56] === 0x0d && bytes[57] === 0x0a ? '木马' : '魏烈思';
12351248
}
1236-
log(`[WS转发] 协议类型: ${判断协议类型} | 来自: ${请求URL.host} | UA: ${request.headers.get('user-agent') || '未知'}`);
1249+
log(`[WS转发] 协议类型: ${判断协议类型} | 来自: ${url.host} | UA: ${request.headers.get('user-agent') || '未知'}`);
12371250
}
12381251

12391252
if (判断协议类型 === 'ss') {
@@ -1667,6 +1680,10 @@ function formatIdentifier(arr, offset = 0) {
16671680
}
16681681
async function connectStreams(remoteSocket, webSocket, headerData, retryFunc) {
16691682
let header = headerData, hasData = false;
1683+
const 发送并等待 = async (payload) => {
1684+
const sendResult = webSocket.send(payload);
1685+
if (sendResult && typeof sendResult.then === 'function') await sendResult;
1686+
};
16701687
await remoteSocket.readable.pipeTo(
16711688
new WritableStream({
16721689
async write(chunk, controller) {
@@ -1676,10 +1693,10 @@ async function connectStreams(remoteSocket, webSocket, headerData, retryFunc) {
16761693
const response = new Uint8Array(header.length + chunk.byteLength);
16771694
response.set(header, 0);
16781695
response.set(chunk, header.length);
1679-
webSocket.send(response.buffer);
1696+
await 发送并等待(response.buffer);
16801697
header = null;
16811698
} else {
1682-
webSocket.send(chunk);
1699+
await 发送并等待(chunk);
16831700
}
16841701
},
16851702
abort() { },
@@ -1706,7 +1723,8 @@ function isSpeedTestSite(hostname) {
17061723
return false;
17071724
}
17081725

1709-
function 修正SB内核请求URL(url文本) {
1726+
function 修正请求URL(url文本) {
1727+
url文本 = url文本.replace(/%5[Cc]/g, '').replace(/\\/g, '');
17101728
const 锚点索引 = url文本.indexOf('#');
17111729
const 主体部分 = 锚点索引 === -1 ? url文本 : url文本.slice(0, 锚点索引);
17121730
if (主体部分.includes('?') || !/%3f/i.test(主体部分)) return url文本;
@@ -2659,7 +2677,7 @@ async function 读取config_JSON(env, hostname, userID, UA = "Mozilla/5.0", 重
26592677
if (!config_JSON.ECHConfig) config_JSON.ECHConfig = { DNS: Ali_DoH, SNI: ECH_SNI };
26602678
const ECHLINK参数 = config_JSON.ECH ? `&ech=${encodeURIComponent((config_JSON.ECHConfig.SNI ? config_JSON.ECHConfig.SNI + '+' : '') + config_JSON.ECHConfig.DNS)}` : '';
26612679
config_JSON.LINK = config_JSON.协议类型 === 'ss'
2662-
? `${config_JSON.协议类型}://${btoa(config_JSON.SS.加密方式 + ':' + userID)}@${host}:${config_JSON.SS.TLS ? '443' : '80'}?plugin=v2${encodeURIComponent(`ray-plugin;mode=websocket;host=${host};path=${((config_JSON.完整节点路径.includes('?') ? config_JSON.完整节点路径.replace('?', '?enc=' + config_JSON.SS.加密方式 + '&') : (config_JSON.完整节点路径 + '?enc=' + config_JSON.SS.加密方式)) + (config_JSON.SS.TLS ? ';tls' : ''))};mux=false`) + ECHLINK参数}#${encodeURIComponent(config_JSON.优选订阅生成.SUBNAME)}`
2680+
? `${config_JSON.协议类型}://${btoa(config_JSON.SS.加密方式 + ':' + userID)}@${host}:${config_JSON.SS.TLS ? '443' : '80'}?plugin=v2${encodeURIComponent(`ray-plugin;mode=websocket;host=${host};path=${((config_JSON.完整节点路径.includes('?') ? config_JSON.完整节点路径.replace('?', '?enc=' + config_JSON.SS.加密方式 + '&') : (config_JSON.完整节点路径 + '?enc=' + config_JSON.SS.加密方式)) + (config_JSON.SS.TLS ? ';tls' : ''))};mux=0`) + ECHLINK参数}#${encodeURIComponent(config_JSON.优选订阅生成.SUBNAME)}`
26632681
: `${config_JSON.协议类型}://${userID}@${host}:443?security=tls&type=${config_JSON.传输协议 + ECHLINK参数}&host=${host}&fp=${config_JSON.Fingerprint}&sni=${host}&path=${encodeURIComponent(config_JSON.随机路径 ? 随机路径(config_JSON.完整节点路径) : config_JSON.完整节点路径) + TLS分片参数}&encryption=none${config_JSON.跳过证书验证 ? '&insecure=1&allowInsecure=1' : ''}#${encodeURIComponent(config_JSON.优选订阅生成.SUBNAME)}`;
26642682
config_JSON.优选订阅生成.TOKEN = await MD5MD5(hostname + userID);
26652683

@@ -3010,8 +3028,7 @@ async function 请求优选API(urls, 默认端口 = '443', 超时时间 = 3000)
30103028
return [Array.from(results), LINK数组, 需要订阅转换订阅URLs, Array.from(反代IP池)];
30113029
}
30123030

3013-
async function 反代参数获取(request) {
3014-
const url = new URL(修正SB内核请求URL(request.url));
3031+
async function 反代参数获取(url) {
30153032
const { searchParams } = url;
30163033
const pathname = decodeURIComponent(url.pathname);
30173034
const pathLower = pathname.toLowerCase();

0 commit comments

Comments
 (0)