Skip to content

Commit aeed643

Browse files
authored
Merge pull request #959 from cmliu/beta2.0
Beta2.0
2 parents ed0ee5a + 745409c commit aeed643

1 file changed

Lines changed: 97 additions & 36 deletions

File tree

_worker.js

Lines changed: 97 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -1403,6 +1403,11 @@ async function 读取config_JSON(env, hostname, userID, 重置配置 = false) {
14031403
账号: 我的SOCKS5账号,
14041404
白名单: SOCKS5白名单,
14051405
},
1406+
路径模板: {
1407+
PROXYIP: "proxyip={{IP:PORT}}",
1408+
SOCKS5: { 全局: "socks5://{{IP:PORT}}", 标准: "socks5={{IP:PORT}}" },
1409+
HTTP: { 全局: "http://{{IP:PORT}}", 标准: "http={{IP:PORT}}" },
1410+
},
14061411
},
14071412
TG: {
14081413
启用: false,
@@ -1448,15 +1453,35 @@ async function 读取config_JSON(env, hostname, userID, 重置配置 = false) {
14481453
if (env.PATH) config_JSON.PATH = env.PATH.startsWith('/') ? env.PATH : '/' + env.PATH;
14491454
else if (!config_JSON.PATH) config_JSON.PATH = '/';
14501455

1451-
const { SOCKS5: 袜子五, PROXYIP: 反代挨批 } = config_JSON.反代;
1452-
const 路径反代参数 = 袜子五.启用
1453-
? `${袜子五.启用}${袜子五.全局 ? '://' : '='}${袜子五.账号}`
1454-
: 反代挨批 !== 'auto' ? `proxyip=${反代挨批}` : '';
1456+
if (!config_JSON.反代.路径模板?.PROXYIP) {
1457+
config_JSON.反代.路径模板 = {
1458+
PROXYIP: "proxyip={{IP:PORT}}",
1459+
SOCKS5: { 全局: "socks5://{{IP:PORT}}", 标准: "socks5={{IP:PORT}}" },
1460+
HTTP: { 全局: "http://{{IP:PORT}}", 标准: "http={{IP:PORT}}" },
1461+
};
1462+
}
1463+
1464+
const { SOCKS5: 袜子五, PROXYIP: 反代挨批, 路径模板 } = config_JSON.反代;
1465+
const 代理配置 = 路径模板[袜子五.启用?.toUpperCase()];
1466+
const 占位符 = '{{IP:PORT}}';
1467+
1468+
let 路径反代参数 = '';
1469+
if (代理配置 && 袜子五.账号) 路径反代参数 = (袜子五.全局 ? 代理配置.全局 : 代理配置.标准).replace(占位符, 袜子五.账号);
1470+
else if (反代挨批 !== 'auto') 路径反代参数 = 路径模板.PROXYIP.replace(占位符, 反代挨批);
1471+
1472+
let 反代查询参数 = '';
1473+
if (路径反代参数.includes('?')) {
1474+
const [反代路径部分, 反代查询部分] = 路径反代参数.split('?');
1475+
路径反代参数 = 反代路径部分;
1476+
反代查询参数 = 反代查询部分;
1477+
}
1478+
14551479
config_JSON.PATH = config_JSON.PATH.replace(路径反代参数, '').replace('//', '/');
14561480
const normalizedPath = config_JSON.PATH === '/' ? '' : config_JSON.PATH.replace(/\/+(?=\?|$)/, '').replace(/\/+$/, '');
14571481
const [路径部分, ...查询数组] = normalizedPath.split('?');
14581482
const 查询部分 = 查询数组.length ? '?' + 查询数组.join('?') : '';
1459-
config_JSON.完整节点路径 = (路径部分 || '/') + (路径部分 && 路径反代参数 ? '/' : '') + 路径反代参数 + 查询部分 + (config_JSON.启用0RTT ? (查询部分 ? '&' : '?') + 'ed=2560' : '');
1483+
const 最终查询部分 = 反代查询参数 ? (查询部分 ? 查询部分 + '&' + 反代查询参数 : '?' + 反代查询参数) : 查询部分;
1484+
config_JSON.完整节点路径 = (路径部分 || '/') + (路径部分 && 路径反代参数 ? '/' : '') + 路径反代参数 + 最终查询部分 + (config_JSON.启用0RTT ? (最终查询部分 ? '&' : '?') + 'ed=2560' : '');
14601485

14611486
if (!config_JSON.TLS分片 && config_JSON.TLS分片 !== null) config_JSON.TLS分片 = null;
14621487
const TLS分片参数 = config_JSON.TLS分片 == 'Shadowrocket' ? `&fragment=${encodeURIComponent('1,40-60,30-50,tlshello')}` : config_JSON.TLS分片 == 'Happ' ? `&fragment=${encodeURIComponent('3,1,tlshello')}` : '';
@@ -1703,50 +1728,86 @@ async function 反代参数获取(request) {
17031728
我的SOCKS5账号 = searchParams.get('socks5') || searchParams.get('http') || null;
17041729
启用SOCKS5全局反代 = searchParams.has('globalproxy') || false;
17051730

1706-
// 统一处理反代IP参数 (优先级最高,使用正则一次匹配)
1707-
const proxyMatch = pathLower.match(/\/(proxyip[.=]|pyip=|ip=)([^/?]+)/);
1731+
// 辅助函数:解析代理协议URL (socks5://... 或 http://...)
1732+
const 解析代理URL = (proxyUrl, 默认全局 = true) => {
1733+
const protocolMatch = proxyUrl.match(/^(socks5|http):\/\/(.+)$/i);
1734+
if (!protocolMatch) return false;
1735+
启用SOCKS5反代 = protocolMatch[1].toLowerCase();
1736+
我的SOCKS5账号 = protocolMatch[2].split('/')[0];
1737+
启用SOCKS5全局反代 = 默认全局 || 启用SOCKS5全局反代;
1738+
return true;
1739+
};
1740+
1741+
// 辅助函数:从路径值中提取干净的地址(移除后续路径段)
1742+
const 提取路径值 = (rawValue) => {
1743+
if (rawValue.includes('://')) {
1744+
// 协议URL:保留 protocol://user:pass@host:port,移除后续路径
1745+
const protocolPart = rawValue.split('://');
1746+
if (protocolPart.length === 2) {
1747+
const [protocol, afterProtocol] = protocolPart;
1748+
const firstSlashIndex = afterProtocol.indexOf('/');
1749+
if (firstSlashIndex > 0) {
1750+
return protocol + '://' + afterProtocol.substring(0, firstSlashIndex);
1751+
}
1752+
}
1753+
} else {
1754+
// 普通IP:PORT:只保留到第一个 /
1755+
const firstSlashIndex = rawValue.indexOf('/');
1756+
if (firstSlashIndex > 0) {
1757+
return rawValue.substring(0, firstSlashIndex);
1758+
}
1759+
}
1760+
return rawValue;
1761+
};
1762+
1763+
// ==================== 第一步:处理 query 参数 ====================
1764+
// 优先级最高:?proxyip=, ?socks5=, ?http=
1765+
let socksMatch, proxyMatch;
17081766
if (searchParams.has('proxyip')) {
17091767
const 路参IP = searchParams.get('proxyip');
1710-
反代IP = 路参IP.includes(',') ? 路参IP.split(',')[Math.floor(Math.random() * 路参IP.split(',').length)] : 路参IP;
1711-
启用反代兜底 = false;
1712-
return;
1713-
} else if (proxyMatch) {
1714-
const 路参IP = proxyMatch[1] === 'proxyip.' ? `proxyip.${proxyMatch[2]}` : proxyMatch[2];
1715-
反代IP = 路参IP.includes(',') ? 路参IP.split(',')[Math.floor(Math.random() * 路参IP.split(',').length)] : 路参IP;
1716-
启用反代兜底 = false;
1717-
return;
1768+
// proxyip 值以 socks5:// 或 http:// 开头,视为对应协议处理
1769+
if (解析代理URL(路参IP)) { /* 继续到下方统一解析 */ }
1770+
else {
1771+
// 否则作为 IP 反代
1772+
反代IP = 路参IP.includes(',') ? 路参IP.split(',')[Math.floor(Math.random() * 路参IP.split(',').length)] : 路参IP;
1773+
启用反代兜底 = false;
1774+
return;
1775+
}
17181776
}
1777+
// query 中的 ?socks5= 和 ?http= 已在初始化时由 searchParams.get 处理
17191778

1720-
// 处理SOCKS5/HTTP代理参数
1721-
let socksMatch;
1722-
if ((socksMatch = pathname.match(/\/(socks5?|http):\/?\/?([^/?#]+)/i))) {
1723-
// 格式: /socks5://... 或 /http://...
1779+
// ==================== 第二步:处理路径中的 SOCKS5/HTTP 协议关键词 ====================
1780+
// 匹配:/socks5://..., /socks://.., /http://...
1781+
else if ((socksMatch = pathname.match(/\/(socks5?|http):\/?\/?([^/?#\s]+)/i))) {
17241782
启用SOCKS5反代 = socksMatch[1].toLowerCase() === 'http' ? 'http' : 'socks5';
1725-
我的SOCKS5账号 = socksMatch[2];
1783+
我的SOCKS5账号 = socksMatch[2].split('/')[0];
17261784
启用SOCKS5全局反代 = true;
1727-
1728-
// 处理Base64编码的用户名密码
1729-
if (我的SOCKS5账号.includes('@')) {
1730-
const atIndex = 我的SOCKS5账号.lastIndexOf('@');
1731-
let userPassword = 我的SOCKS5账号.substring(0, atIndex).replaceAll('%3D', '=');
1732-
if (/^(?:[A-Z0-9+/]{4})*(?:[A-Z0-9+/]{2}==|[A-Z0-9+/]{3}=)?$/i.test(userPassword) && !userPassword.includes(':')) {
1733-
userPassword = atob(userPassword);
1734-
}
1735-
我的SOCKS5账号 = `${userPassword}@${我的SOCKS5账号.substring(atIndex + 1)}`;
1736-
}
1737-
} else if ((socksMatch = pathname.match(/\/(g?s5|socks5|g?http)=([^/?#]+)/i))) {
1738-
// 格式: /socks5=... 或 /s5=... 或 /gs5=... 或 /http=... 或 /ghttp=...
1785+
}
1786+
// 匹配:/socks5=..., /s5=..., /gs5=..., /http=..., /ghttp=...
1787+
else if ((socksMatch = pathname.match(/\/(g?s5|socks5|g?http)=([^/?#\s]+)/i))) {
17391788
const type = socksMatch[1].toLowerCase();
1740-
我的SOCKS5账号 = socksMatch[2];
1789+
我的SOCKS5账号 = socksMatch[2].split('/')[0];
17411790
启用SOCKS5反代 = type.includes('http') ? 'http' : 'socks5';
1742-
启用SOCKS5全局反代 = type.startsWith('g') || 启用SOCKS5全局反代; // gs5 或 ghttp 开头启用全局
1791+
启用SOCKS5全局反代 = type.startsWith('g') || 启用SOCKS5全局反代;
1792+
}
1793+
1794+
// ==================== 第三步:处理路径中的 proxyip/pyip/ip ====================
1795+
else if ((proxyMatch = pathLower.match(/\/(proxyip[.=]|pyip=|ip=)([^?#\s]+)/))) {
1796+
let 路参IP = 提取路径值(proxyMatch[2]);
1797+
// proxyip 值以 socks5:// 或 http:// 开头,视为对应协议处理
1798+
if (!解析代理URL(路参IP)) {
1799+
// 否则作为 IP 反代
1800+
反代IP = 路参IP.includes(',') ? 路参IP.split(',')[Math.floor(Math.random() * 路参IP.split(',').length)] : 路参IP;
1801+
启用反代兜底 = false;
1802+
return;
1803+
}
17431804
}
17441805

1745-
// 解析SOCKS5地址
1806+
// 统一解析SOCKS5地址
17461807
if (我的SOCKS5账号) {
17471808
try {
17481809
parsedSocks5Address = await 获取SOCKS5账号(我的SOCKS5账号);
1749-
启用SOCKS5反代 = searchParams.get('http') ? 'http' : 启用SOCKS5反代;
1810+
启用SOCKS5反代 = searchParams.get('http') ? 'http' : (启用SOCKS5反代 || 'socks5');
17501811
} catch (err) {
17511812
console.error('解析SOCKS5地址失败:', err.message);
17521813
启用SOCKS5反代 = null;

0 commit comments

Comments
 (0)