Skip to content

Commit 6846830

Browse files
authored
Merge pull request cmliu#1248 from cmliu/beta2.1
Beta2.1
2 parents 109f93f + c2cd245 commit 6846830

3 files changed

Lines changed: 79 additions & 19 deletions

File tree

CHANGELOG

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,15 @@
1+
## [2.1.20260526210857] - 2026-05-26 21:08:57
2+
3+
### Debug
4+
5+
- 修复 **TURN 认证**:允许 STUN 鉴权 challenge 中存在空 `REALM`,避免空 realm 被误判为缺失导致连接失败。
6+
7+
## [2.1.20260518183745] - 2026-05-18 18:37:45
8+
9+
### ADD
10+
11+
- 新增 **TCP 预加载竞速拨号**:首次直连域名时可先通过 DoH 并发查询 A/AAAA 记录,优先使用 IPv4,数量不足时用 IPv6 补齐到 `TCP并发拨号数` 上限;反代失败兜底逻辑与普通首次直连拆分,避免误触发预加载。
12+
113
## [2.1.20260517185203] - 2026-05-17 18:52:03
214

315
### Debug

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,7 @@
127127
| **DEBUG** || `1``true` | **开发者模式**,默认关闭调试日志功能(console.log),设置`1``true`则开启调试日志功能 |
128128
| **OFF_LOG** || `1``true` | 默认开启日志记录功能,设置`1``true`则关闭日志记录功能 |
129129
| **BEST_SUB** || `1``true` | 默认关闭作为**优选订阅生成器**的功能,设置`1``true`则开启该功能 |
130+
| **PRELOAD_RACE_DIAL** || `1``true` | 默认关闭作为**预加载竞速拨号**的功能,设置`1``true`则开启该功能 |
130131

131132
---
132133

_worker.js

Lines changed: 66 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
const Version = '2026-05-17 18:52:03';
1+
const Version = '2026-05-26 21:08:57';
22
let config_JSON, 反代IP = '', 启用SOCKS5反代 = null, 启用SOCKS5全局反代 = false, 我的SOCKS5账号 = '', parsedSocks5Address = {};
33
let 缓存SOCKS5白名单 = null, 缓存反代IP, 缓存反代解析数组, 缓存反代数组索引 = 0, 启用反代兜底 = true, 调试日志打印 = false;
44
let SOCKS5白名单 = ['*tapecontent.net', '*cloudatacdn.com', '*loadshare.org', '*cdn-centaurus.com', 'scholar.google.com'];
@@ -7,7 +7,7 @@ const Pages静态页面 = 'https://edt-pages.github.io';
77
const WS早期数据最大字节 = 8 * 1024, WS早期数据最大头长度 = Math.ceil(WS早期数据最大字节 * 4 / 3) + 4;
88
const 上行合包目标字节 = 16 * 1024, 上行队列最大字节 = 16 * 1024 * 1024, 上行队列最大条目 = 4096;
99
const 下行Grain包字节 = 32 * 1024, 下行Grain尾部阈值 = 512, 下行Grain静默毫秒 = 0;
10-
const TCP并发拨号数 = 2;
10+
let TCP并发拨号数 = 2, 预加载竞速拨号 = false;
1111
///////////////////////////////////////////////////////主程序入口///////////////////////////////////////////////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.
1212
export default {
1313
async fetch(request, env, ctx) {
@@ -31,6 +31,7 @@ export default {
3131
const host = hosts[0];
3232
const 访问路径 = url.pathname.slice(1).toLowerCase();
3333
调试日志打印 = ['1', 'true'].includes(env.DEBUG) || 调试日志打印;
34+
预加载竞速拨号 = ['1', 'true'].includes(env.PRELOAD_RACE_DIAL) || 预加载竞速拨号;
3435
if (env.PROXYIP) {
3536
const proxyIPs = await 整理成数组(env.PROXYIP);
3637
反代IP = proxyIPs[Math.floor(Math.random() * proxyIPs.length)];
@@ -1903,7 +1904,61 @@ async function forwardataTCP(host, portNum, rawData, ws, respHeader, remoteConnW
19031904
}
19041905
}
19051906

1906-
async function connectDirect(address, port, data = null, 所有反代数组 = null, 反代兜底 = true) {
1907+
async function 构建预加载竞速候选列表(address, port) {
1908+
if (!预加载竞速拨号 || isIPHostname(address)) return null;
1909+
log(`[TCP直连] 预加载竞速拨号开启,开始并发查询 ${address} 的 A/AAAA 记录`);
1910+
const [aRecords, aaaaRecords] = await Promise.all([
1911+
DoH查询(address, 'A'),
1912+
DoH查询(address, 'AAAA')
1913+
]);
1914+
const ipv4List = [...new Set(aRecords.flatMap(r => {
1915+
const data = r.data;
1916+
return r.type === 1 && typeof data === 'string' && isIPv4(data) ? [data] : [];
1917+
}))];
1918+
const ipv6List = [...new Set(aaaaRecords.flatMap(r => {
1919+
const data = r.data;
1920+
return r.type === 28 && typeof data === 'string' && isIPHostname(data) ? [data] : [];
1921+
}))];
1922+
const 拨号上限 = Math.max(1, TCP并发拨号数 | 0);
1923+
const ipList = ipv4List.length >= 拨号上限
1924+
? ipv4List.slice(0, 拨号上限)
1925+
: ipv4List.concat(ipv6List.slice(0, 拨号上限 - ipv4List.length));
1926+
const 使用记录类型 = ipv4List.length > 0
1927+
? (ipList.length > ipv4List.length ? 'A+AAAA' : 'A')
1928+
: 'AAAA';
1929+
if (ipList.length === 0) {
1930+
log(`[TCP直连] ${address} 的 A/AAAA 未获得可用解析结果,预加载竞速不可用,回退到原始 hostname 直连。`);
1931+
return null;
1932+
}
1933+
const 选中IP列表 = ipList;
1934+
log(`[TCP直连] ${address} A记录:${ipv4List.length} AAAA记录:${ipv6List.length},使用${使用记录类型}记录,竞速拨号 ${选中IP列表.length}/${拨号上限}: ${选中IP列表.join(', ')}`);
1935+
return 选中IP列表.map((hostname, attempt) => ({ hostname, port, attempt, resolvedFrom: address }));
1936+
}
1937+
1938+
async function connectDirect(address, port, data = null, 启用预加载 = false) {
1939+
const 预加载候选列表 = 启用预加载 ? await 构建预加载竞速候选列表(address, port) : null;
1940+
const 候选列表 = 预加载候选列表 || Array.from({ length: TCP并发拨号数 }, (_, attempt) => ({ hostname: address, port, attempt }));
1941+
log(预加载候选列表
1942+
? `[TCP直连] 并发尝试 ${候选列表.length} 路: ${候选列表.map(候选 => `${候选.hostname}:${候选.port}`).join(', ')}`
1943+
: `[TCP直连] 并发尝试 ${候选列表.length} 路: ${address}:${port}`);
1944+
let socket = null;
1945+
try {
1946+
const 连接结果 = await 并发打开候选连接(候选列表);
1947+
socket = 连接结果.socket;
1948+
if (预加载候选列表) {
1949+
const winner = 连接结果.candidate;
1950+
log(`[TCP直连] 预加载竞速结果: ${winner.hostname}:${winner.port} 胜出,源域名: ${winner.resolvedFrom || address}`);
1951+
}
1952+
await 写入首包(socket, data);
1953+
return socket;
1954+
} catch (err) {
1955+
try { socket?.close?.() } catch (e) { }
1956+
if (预加载候选列表) log(`[TCP直连] 预加载竞速失败: ${err.message || err}`);
1957+
throw err;
1958+
}
1959+
}
1960+
1961+
async function connectProxyIP(address, port, data = null, 所有反代数组 = null, 启用反代失败兜底 = true) {
19071962
if (所有反代数组 && 所有反代数组.length > 0) {
19081963
for (let i = 0; i < 所有反代数组.length; i += TCP并发拨号数) {
19091964
const 候选列表 = [];
@@ -1929,20 +1984,8 @@ async function forwardataTCP(host, portNum, rawData, ws, respHeader, remoteConnW
19291984
}
19301985
}
19311986

1932-
if (反代兜底) {
1933-
const 候选列表 = Array.from({ length: TCP并发拨号数 }, (_, attempt) => ({ hostname: address, port, attempt }));
1934-
log(`[TCP直连] 并发尝试 ${候选列表.length} 路: ${address}:${port}`);
1935-
let socket = null;
1936-
try {
1937-
const 连接结果 = await 并发打开候选连接(候选列表);
1938-
socket = 连接结果.socket;
1939-
await 写入首包(socket, data);
1940-
return socket;
1941-
} catch (err) {
1942-
try { socket?.close?.() } catch (e) { }
1943-
throw err;
1944-
}
1945-
} else {
1987+
if (启用反代失败兜底) return connectDirect(address, port, data, false);
1988+
else {
19461989
closeSocketQuietly(ws);
19471990
throw new Error('[反代连接] 所有反代连接失败,且未启用反代兜底,连接终止。');
19481991
}
@@ -1989,7 +2032,7 @@ async function forwardataTCP(host, portNum, rawData, ws, respHeader, remoteConnW
19892032
} else {
19902033
log(`[反代连接] 代理到: ${host}:${portNum}`);
19912034
const 所有反代数组 = await 解析地址端口(反代IP, host, yourUUID);
1992-
newSocket = await connectDirect(atob('UFJPWFlJUC50cDEuMDkwMjI3Lnh5eg=='), 1, 本次首包数据, 所有反代数组, 启用反代兜底);
2035+
newSocket = await connectProxyIP(atob('UFJPWFlJUC50cDEuMDkwMjI3Lnh5eg=='), 1, 本次首包数据, 所有反代数组, 启用反代兜底);
19932036
}
19942037
if (本次发送首包) 已通过代理发送首包 = true;
19952038
remoteConnWrapper.socket = newSocket;
@@ -2019,14 +2062,18 @@ async function forwardataTCP(host, portNum, rawData, ws, respHeader, remoteConnW
20192062
} else {
20202063
try {
20212064
log(`[TCP转发] 尝试直连到: ${host}:${portNum}`);
2022-
const initialSocket = await connectDirect(host, portNum, rawData);
2065+
const initialSocket = await connectDirect(host, portNum, rawData, true);
20232066
remoteConnWrapper.socket = initialSocket;
20242067
connectStreams(initialSocket, ws, respHeader, async () => {
20252068
if (remoteConnWrapper.socket !== initialSocket) return;
20262069
await connecttoPry();
20272070
});
20282071
} catch (err) {
20292072
log(`[TCP转发] 直连 ${host}:${portNum} 失败: ${err.message}`);
2073+
if (err instanceof Error && err.name === '预加载解析为空') {
2074+
closeSocketQuietly(ws);
2075+
throw err;
2076+
}
20302077
await connecttoPry();
20312078
}
20322079
}

0 commit comments

Comments
 (0)