|
1 | | -import //crypto from "node:crypto"; |
2 | | -/*How can we utilize the*/ { connect } |
3 | | -/*function*/ from /*the*/ "cloudflare:sockets";// library in this Worker? |
| 1 | +/*In our project workflow, we first*/ import //the necessary modules, |
| 2 | +/*then*/ { connect }//to the central server, |
| 3 | +/*and all data flows*/ from//this single source. |
| 4 | + 'cloudflare\u003asockets'; |
4 | 5 | let config_JSON, 反代IP = '', 启用SOCKS5反代 = null, 启用SOCKS5全局反代 = false, 我的SOCKS5账号 = '', parsedSocks5Address = {}; |
5 | 6 | let 缓存反代IP, 缓存反代解析数组, 缓存反代数组索引 = 0, 启用反代兜底 = true; |
6 | 7 | let SOCKS5白名单 = ['*tapecontent.net', '*cloudatacdn.com', '*loadshare.org', '*cdn-centaurus.com', 'scholar.google.com']; |
@@ -1358,9 +1359,8 @@ async function getECH(host) { |
1358 | 1359 |
|
1359 | 1360 | async function 读取config_JSON(env, hostname, userID, 重置配置 = false) { |
1360 | 1361 | //const host = 随机替换通配符(hostname); |
1361 | | - const host = hostname, CM_DoH = "https://doh.cmliussss.net/CMLiussss"; |
1362 | | - const 初始化开始时间 = performance.now(); |
1363 | | - const 默认配置JSON = { |
| 1362 | + const _p = atob("UFJPWFlJUA=="); |
| 1363 | + const host = hostname, CM_DoH = "https://doh.cmliussss.net/CMLiussss", 占位符 = '{{IP:PORT}}', 初始化开始时间 = performance.now(), 默认配置JSON = { |
1364 | 1364 | TIME: new Date().toISOString(), |
1365 | 1365 | HOST: host, |
1366 | 1366 | HOSTS: [hostname], |
@@ -1396,13 +1396,24 @@ async function 读取config_JSON(env, hostname, userID, 重置配置 = false) { |
1396 | 1396 | SUBEMOJI: false, |
1397 | 1397 | }, |
1398 | 1398 | 反代: { |
1399 | | - PROXYIP: "auto", |
| 1399 | + [_p]: "auto", |
1400 | 1400 | SOCKS5: { |
1401 | 1401 | 启用: 启用SOCKS5反代, |
1402 | 1402 | 全局: 启用SOCKS5全局反代, |
1403 | 1403 | 账号: 我的SOCKS5账号, |
1404 | 1404 | 白名单: SOCKS5白名单, |
1405 | 1405 | }, |
| 1406 | + 路径模板: { |
| 1407 | + [_p]: "proxyip=" + 占位符, |
| 1408 | + SOCKS5: { |
| 1409 | + 全局: "socks5://" + 占位符, |
| 1410 | + 标准: "socks5=" + 占位符 |
| 1411 | + }, |
| 1412 | + HTTP: { |
| 1413 | + 全局: "http://" + 占位符, |
| 1414 | + 标准: "http=" + 占位符 |
| 1415 | + }, |
| 1416 | + }, |
1406 | 1417 | }, |
1407 | 1418 | TG: { |
1408 | 1419 | 启用: false, |
@@ -1448,15 +1459,39 @@ async function 读取config_JSON(env, hostname, userID, 重置配置 = false) { |
1448 | 1459 | if (env.PATH) config_JSON.PATH = env.PATH.startsWith('/') ? env.PATH : '/' + env.PATH; |
1449 | 1460 | else if (!config_JSON.PATH) config_JSON.PATH = '/'; |
1450 | 1461 |
|
1451 | | - const { SOCKS5: 袜子五, PROXYIP: 反代挨批 } = config_JSON.反代; |
1452 | | - const 路径反代参数 = 袜子五.启用 |
1453 | | - ? `${袜子五.启用}${袜子五.全局 ? '://' : '='}${袜子五.账号}` |
1454 | | - : 反代挨批 !== 'auto' ? `proxyip=${反代挨批}` : ''; |
| 1462 | + if (!config_JSON.反代.路径模板?.[_p]) { |
| 1463 | + config_JSON.反代.路径模板 = { |
| 1464 | + [_p]: "proxyip=" + 占位符, |
| 1465 | + SOCKS5: { |
| 1466 | + 全局: "socks5://" + 占位符, |
| 1467 | + 标准: "socks5=" + 占位符 |
| 1468 | + }, |
| 1469 | + HTTP: { |
| 1470 | + 全局: "http://" + 占位符, |
| 1471 | + 标准: "http=" + 占位符 |
| 1472 | + }, |
| 1473 | + }; |
| 1474 | + } |
| 1475 | + |
| 1476 | + const 代理配置 = config_JSON.反代.路径模板[config_JSON.反代.SOCKS5.启用?.toUpperCase()]; |
| 1477 | + |
| 1478 | + let 路径反代参数 = ''; |
| 1479 | + if (代理配置 && config_JSON.反代.SOCKS5.账号) 路径反代参数 = (config_JSON.反代.SOCKS5.全局 ? 代理配置.全局 : 代理配置.标准).replace(占位符, config_JSON.反代.SOCKS5.账号); |
| 1480 | + else if (config_JSON.反代[_p] !== 'auto') 路径反代参数 = config_JSON.反代.路径模板[_p].replace(占位符, config_JSON.反代[_p]); |
| 1481 | + |
| 1482 | + let 反代查询参数 = ''; |
| 1483 | + if (路径反代参数.includes('?')) { |
| 1484 | + const [反代路径部分, 反代查询部分] = 路径反代参数.split('?'); |
| 1485 | + 路径反代参数 = 反代路径部分; |
| 1486 | + 反代查询参数 = 反代查询部分; |
| 1487 | + } |
| 1488 | + |
1455 | 1489 | config_JSON.PATH = config_JSON.PATH.replace(路径反代参数, '').replace('//', '/'); |
1456 | 1490 | const normalizedPath = config_JSON.PATH === '/' ? '' : config_JSON.PATH.replace(/\/+(?=\?|$)/, '').replace(/\/+$/, ''); |
1457 | 1491 | const [路径部分, ...查询数组] = normalizedPath.split('?'); |
1458 | 1492 | const 查询部分 = 查询数组.length ? '?' + 查询数组.join('?') : ''; |
1459 | | - config_JSON.完整节点路径 = (路径部分 || '/') + (路径部分 && 路径反代参数 ? '/' : '') + 路径反代参数 + 查询部分 + (config_JSON.启用0RTT ? (查询部分 ? '&' : '?') + 'ed=2560' : ''); |
| 1493 | + const 最终查询部分 = 反代查询参数 ? (查询部分 ? 查询部分 + '&' + 反代查询参数 : '?' + 反代查询参数) : 查询部分; |
| 1494 | + config_JSON.完整节点路径 = (路径部分 || '/') + (路径部分 && 路径反代参数 ? '/' : '') + 路径反代参数 + 最终查询部分 + (config_JSON.启用0RTT ? (最终查询部分 ? '&' : '?') + 'ed=2560' : ''); |
1460 | 1495 |
|
1461 | 1496 | if (!config_JSON.TLS分片 && config_JSON.TLS分片 !== null) config_JSON.TLS分片 = null; |
1462 | 1497 | 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 +1738,86 @@ async function 反代参数获取(request) { |
1703 | 1738 | 我的SOCKS5账号 = searchParams.get('socks5') || searchParams.get('http') || null; |
1704 | 1739 | 启用SOCKS5全局反代 = searchParams.has('globalproxy') || false; |
1705 | 1740 |
|
1706 | | - // 统一处理反代IP参数 (优先级最高,使用正则一次匹配) |
1707 | | - const proxyMatch = pathLower.match(/\/(proxyip[.=]|pyip=|ip=)([^/?]+)/); |
| 1741 | + // 辅助函数:解析代理协议URL (socks5://... 或 http://...) |
| 1742 | + const 解析代理URL = (proxyUrl, 默认全局 = true) => { |
| 1743 | + const protocolMatch = proxyUrl.match(/^(socks5|http):\/\/(.+)$/i); |
| 1744 | + if (!protocolMatch) return false; |
| 1745 | + 启用SOCKS5反代 = protocolMatch[1].toLowerCase(); |
| 1746 | + 我的SOCKS5账号 = protocolMatch[2].split('/')[0]; |
| 1747 | + 启用SOCKS5全局反代 = 默认全局 || 启用SOCKS5全局反代; |
| 1748 | + return true; |
| 1749 | + }; |
| 1750 | + |
| 1751 | + // 辅助函数:从路径值中提取干净的地址(移除后续路径段) |
| 1752 | + const 提取路径值 = (rawValue) => { |
| 1753 | + if (rawValue.includes('://')) { |
| 1754 | + // 协议URL:保留 protocol://user:pass@host:port,移除后续路径 |
| 1755 | + const protocolPart = rawValue.split('://'); |
| 1756 | + if (protocolPart.length === 2) { |
| 1757 | + const [protocol, afterProtocol] = protocolPart; |
| 1758 | + const firstSlashIndex = afterProtocol.indexOf('/'); |
| 1759 | + if (firstSlashIndex > 0) { |
| 1760 | + return protocol + '://' + afterProtocol.substring(0, firstSlashIndex); |
| 1761 | + } |
| 1762 | + } |
| 1763 | + } else { |
| 1764 | + // 普通IP:PORT:只保留到第一个 / |
| 1765 | + const firstSlashIndex = rawValue.indexOf('/'); |
| 1766 | + if (firstSlashIndex > 0) { |
| 1767 | + return rawValue.substring(0, firstSlashIndex); |
| 1768 | + } |
| 1769 | + } |
| 1770 | + return rawValue; |
| 1771 | + }; |
| 1772 | + |
| 1773 | + // ==================== 第一步:处理 query 参数 ==================== |
| 1774 | + // 优先级最高:?proxyip=, ?socks5=, ?http= |
| 1775 | + let socksMatch, proxyMatch; |
1708 | 1776 | if (searchParams.has('proxyip')) { |
1709 | 1777 | 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; |
| 1778 | + // proxyip 值以 socks5:// 或 http:// 开头,视为对应协议处理 |
| 1779 | + if (解析代理URL(路参IP)) { /* 继续到下方统一解析 */ } |
| 1780 | + else { |
| 1781 | + // 否则作为 IP 反代 |
| 1782 | + 反代IP = 路参IP.includes(',') ? 路参IP.split(',')[Math.floor(Math.random() * 路参IP.split(',').length)] : 路参IP; |
| 1783 | + 启用反代兜底 = false; |
| 1784 | + return; |
| 1785 | + } |
1718 | 1786 | } |
| 1787 | + // query 中的 ?socks5= 和 ?http= 已在初始化时由 searchParams.get 处理 |
1719 | 1788 |
|
1720 | | - // 处理SOCKS5/HTTP代理参数 |
1721 | | - let socksMatch; |
1722 | | - if ((socksMatch = pathname.match(/\/(socks5?|http):\/?\/?([^/?#]+)/i))) { |
1723 | | - // 格式: /socks5://... 或 /http://... |
| 1789 | + // ==================== 第二步:处理路径中的 SOCKS5/HTTP 协议关键词 ==================== |
| 1790 | + // 匹配:/socks5://..., /socks://.., /http://... |
| 1791 | + else if ((socksMatch = pathname.match(/\/(socks5?|http):\/?\/?([^/?#\s]+)/i))) { |
1724 | 1792 | 启用SOCKS5反代 = socksMatch[1].toLowerCase() === 'http' ? 'http' : 'socks5'; |
1725 | | - 我的SOCKS5账号 = socksMatch[2]; |
| 1793 | + 我的SOCKS5账号 = socksMatch[2].split('/')[0]; |
1726 | 1794 | 启用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=... |
| 1795 | + } |
| 1796 | + // 匹配:/socks5=..., /s5=..., /gs5=..., /http=..., /ghttp=... |
| 1797 | + else if ((socksMatch = pathname.match(/\/(g?s5|socks5|g?http)=([^/?#\s]+)/i))) { |
1739 | 1798 | const type = socksMatch[1].toLowerCase(); |
1740 | | - 我的SOCKS5账号 = socksMatch[2]; |
| 1799 | + 我的SOCKS5账号 = socksMatch[2].split('/')[0]; |
1741 | 1800 | 启用SOCKS5反代 = type.includes('http') ? 'http' : 'socks5'; |
1742 | | - 启用SOCKS5全局反代 = type.startsWith('g') || 启用SOCKS5全局反代; // gs5 或 ghttp 开头启用全局 |
| 1801 | + 启用SOCKS5全局反代 = type.startsWith('g') || 启用SOCKS5全局反代; |
| 1802 | + } |
| 1803 | + |
| 1804 | + // ==================== 第三步:处理路径中的 proxyip/pyip/ip ==================== |
| 1805 | + else if ((proxyMatch = pathLower.match(/\/(proxyip[.=]|pyip=|ip=)([^?#\s]+)/))) { |
| 1806 | + let 路参IP = 提取路径值(proxyMatch[2]); |
| 1807 | + // proxyip 值以 socks5:// 或 http:// 开头,视为对应协议处理 |
| 1808 | + if (!解析代理URL(路参IP)) { |
| 1809 | + // 否则作为 IP 反代 |
| 1810 | + 反代IP = 路参IP.includes(',') ? 路参IP.split(',')[Math.floor(Math.random() * 路参IP.split(',').length)] : 路参IP; |
| 1811 | + 启用反代兜底 = false; |
| 1812 | + return; |
| 1813 | + } |
1743 | 1814 | } |
1744 | 1815 |
|
1745 | | - // 解析SOCKS5地址 |
| 1816 | + // 统一解析SOCKS5地址 |
1746 | 1817 | if (我的SOCKS5账号) { |
1747 | 1818 | try { |
1748 | 1819 | parsedSocks5Address = await 获取SOCKS5账号(我的SOCKS5账号); |
1749 | | - 启用SOCKS5反代 = searchParams.get('http') ? 'http' : 启用SOCKS5反代; |
| 1820 | + 启用SOCKS5反代 = searchParams.get('http') ? 'http' : (启用SOCKS5反代 || 'socks5'); |
1750 | 1821 | } catch (err) { |
1751 | 1822 | console.error('解析SOCKS5地址失败:', err.message); |
1752 | 1823 | 启用SOCKS5反代 = null; |
|
0 commit comments