Skip to content

Commit 72b5679

Browse files
authored
Merge pull request cmliu#1362 from cmliu/alpha2.1
Alpha2.1
2 parents 999f86e + 3d9a1a9 commit 72b5679

2 files changed

Lines changed: 43 additions & 11 deletions

File tree

CHANGELOG

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,15 @@
1-
## [2.1.20260709001815] - 2026-07-09 00:18:15
1+
## [2.1.20260711022318] - 2026-07-11 02:23:18
22

33
### Change
44

55
- 优化 **反代相关逻辑**:解决多反代节点参数因全局变量被意外覆盖导致不生效的问题。
6+
- 优化 **DoH 缓存**:缓存近期的域名解析结果,减少重复请求,提升解析速度并降低资源占用;对于没有解析结果的域名也会暂时缓存,避免反复查询。
67

78
### ADD
89

9-
- **订阅转换配置**新增更多功能选项,包括 **UDP**、**XUDP**、**TLS 1.3**、**插入节点类型** 和 **基础节点排序**,并同步透传到订阅转换后端。
10-
- **Trojan 回退代理(Fallback)**:Trojan 协议现在支持设置备用代理地址。当主连接不通时,可以自动切换到备用代理继续工作,让连接更稳定可靠。
10+
- 新增 **反代并发拨号数**:可自行调整反代连接的并发数量。并发数越高,连接速度越快,但 IP 切换也越频繁;并发数越低,连接过程则更加稳定。
11+
- 新增 **订阅转换配置**:更多功能选项,包括 **UDP**、**XUDP**、**TLS 1.3**、**插入节点类型** 和 **基础节点排序**,并同步透传到订阅转换后端。
12+
- 新增 **Trojan 回退代理(Fallback)**:Trojan 协议现在支持设置备用代理地址。当主连接不通时,可以自动切换到备用代理继续工作,让连接更稳定可靠。
1113

1214
## [2.1.20260617014121] - 2026-06-17 01:41:21
1315

_worker.js

Lines changed: 38 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
1-
const Version = '2026-07-09 00:18:15';
1+
const Version = '2026-07-11 02:23:18';
22
let config_JSON, 缓存SOCKS5白名单 = null, 调试日志打印 = false;
33
let SOCKS5白名单 = ['*tapecontent.net', '*cloudatacdn.com', '*loadshare.org', '*cdn-centaurus.com', 'scholar.google.com'];
44
const Pages静态页面 = 'https://edt-pages.github.io';
55
///////////////////////////////////////////////////////全局常量和工具函数///////////////////////////////////////////////
66
const WS早期数据最大字节 = 8 * 1024, WS早期数据最大头长度 = Math.ceil(WS早期数据最大字节 * 4 / 3) + 4;
77
const 上行合包目标字节 = 16 * 1024, 上行队列最大字节 = 16 * 1024 * 1024, 上行队列最大条目 = 4096;
88
const 下行Grain包字节 = 32 * 1024, 下行Grain尾部阈值 = 512, 下行Grain静默毫秒 = 0;
9-
let TCP并发拨号数 = 2, 预加载竞速拨号 = false;
9+
let TCP并发拨号数 = 2, 反代并发拨号数 = 1, 预加载竞速拨号 = false;
1010
///////////////////////////////////////////////////////查杀特征码///////////////////////////////////////////////
1111
const 特征码字典 = [
1212
(Proxy.name + "IP").toUpperCase(),
@@ -2084,9 +2084,10 @@ async function forwardataTCP(host, portNum, rawData, ws, respHeader, remoteConnW
20842084

20852085
async function connectProxyIP(address, port, data = null, 所有反代数组 = null, 启用反代失败兜底 = true) {
20862086
if (所有反代数组 && 所有反代数组.length > 0) {
2087-
for (let i = 0; i < 所有反代数组.length; i += TCP并发拨号数) {
2087+
const 实际并发数 = Math.max(1, Math.floor(Number(反代并发拨号数) || 1));
2088+
for (let i = 0; i < 所有反代数组.length; i += 实际并发数) {
20882089
const 候选列表 = [];
2089-
for (let j = 0; j < TCP并发拨号数 && i + j < 所有反代数组.length; j++) {
2090+
for (let j = 0; j < 实际并发数 && i + j < 所有反代数组.length; j++) {
20902091
const 索引 = (反代数组索引 + i + j) % 所有反代数组.length;
20912092
const [反代地址, 反代端口] = 所有反代数组[索引];
20922093
候选列表.push({ hostname: 反代地址, port: 反代端口, index: 索引 });
@@ -4901,14 +4902,24 @@ function 替换星号为随机字符(内容) {
49014902
});
49024903
}
49034904

4905+
const DoH缓存 = {};
4906+
const DoH缓存最大条目 = 256;
4907+
const DoH记录类型映射 = { A: 1, NS: 2, CNAME: 5, MX: 15, TXT: 16, AAAA: 28, SRV: 33, HTTPS: 65 };
49044908
async function DoH查询(域名, 记录类型, DoH解析服务 = "https://cloudflare-dns.com/dns-query") {
4909+
const 规范化域名 = String(域名 || '').trim().toLowerCase().replace(/\.$/, '');
4910+
const 规范化记录类型 = String(记录类型 || '').trim().toUpperCase();
4911+
const 缓存键 = `${规范化域名}:${规范化记录类型}`;
4912+
const qtype = DoH记录类型映射[规范化记录类型] || 1;
4913+
const 当前时间戳 = Date.now();
4914+
const 现缓存项 = DoH缓存[缓存键];
4915+
if (现缓存项 && 当前时间戳 < 现缓存项.过期时间) {
4916+
log(`[DoH查询] 命中缓存 ${域名} ${记录类型} via ${DoH解析服务}`);
4917+
return 现缓存项.data.map(data => ({ type: qtype, data }));
4918+
}
49054919
const 开始时间 = performance.now();
49064920
log(`[DoH查询] 开始查询 ${域名} ${记录类型} via ${DoH解析服务}`);
49074921
try {
49084922
// 记录类型字符串转数值
4909-
const 类型映射 = { 'A': 1, 'NS': 2, 'CNAME': 5, 'MX': 15, 'TXT': 16, 'AAAA': 28, 'SRV': 33, 'HTTPS': 65 };
4910-
const qtype = 类型映射[记录类型.toUpperCase()] || 1;
4911-
49124923
// 编码域名为 DNS wire format labels
49134924
const 编码域名 = (name) => {
49144925
const parts = name.endsWith('.') ? name.slice(0, -1).split('.') : name.split('.');
@@ -4926,7 +4937,7 @@ async function DoH查询(域名, 记录类型, DoH解析服务 = "https://cloudf
49264937
};
49274938

49284939
// 构建 DNS 查询报文
4929-
const qname = 编码域名(域名);
4940+
const qname = 编码域名(规范化域名);
49304941
const query = new Uint8Array(12 + qname.length + 4);
49314942
const qview = new DataView(query.buffer);
49324943
qview.setUint16(0, crypto.getRandomValues(new Uint16Array(1))[0]); // ID (random per RFC 1035)
@@ -5027,6 +5038,25 @@ async function DoH查询(域名, 记录类型, DoH解析服务 = "https://cloudf
50275038
}
50285039
const 耗时 = (performance.now() - 开始时间).toFixed(2);
50295040
log(`[DoH查询] 查询完成 ${域名} ${记录类型} via ${DoH解析服务} ${耗时}ms 共${answers.length}条结果${answers.length > 0 ? '\n' + answers.map((a, i) => ` ${i + 1}. ${a.name} type=${a.type} TTL=${a.TTL} data=${a.data}`).join('\n') : ''}`);
5041+
// DoH 缓存至少保留 5 分钟,响应 TTL 更长时尊重响应 TTL;空响应使用 5 分钟负缓存
5042+
const 相关记录 = answers.filter(answer => answer.type === qtype);
5043+
const 最小TTL = 相关记录.length > 0 ? Math.min(...相关记录.map(a => a.TTL)) : 0;
5044+
const 缓存TTL = Math.max(最小TTL, 5 * 60);
5045+
const 缓存过期时间 = Date.now() + 缓存TTL * 1000;
5046+
const 缓存数据 = 相关记录.map(answer => answer.data);
5047+
if (缓存数据.length > 0 || answers.length === 0) {
5048+
if (Object.keys(DoH缓存).length >= DoH缓存最大条目) {
5049+
const 清理时间戳 = Date.now();
5050+
for (const [缓存条目键, 缓存条目] of Object.entries(DoH缓存)) {
5051+
if (清理时间戳 >= 缓存条目.过期时间) delete DoH缓存[缓存条目键];
5052+
}
5053+
if (Object.keys(DoH缓存).length >= DoH缓存最大条目) {
5054+
delete DoH缓存[Object.keys(DoH缓存)[0]];
5055+
}
5056+
}
5057+
DoH缓存[缓存键] = { data: 缓存数据, 过期时间: 缓存过期时间 };
5058+
log(`[DoH查询] 写入缓存 ${域名} ${记录类型} TTL=${缓存TTL}s${缓存数据.length === 0 ? '(空结果)' : ''}`);
5059+
}
50305060
return answers;
50315061
} catch (error) {
50325062
const 耗时 = (performance.now() - 开始时间).toFixed(2);

0 commit comments

Comments
 (0)