diff --git "a/\346\230\216\346\226\207\346\272\220\347\240\201.js" "b/\346\230\216\346\226\207\346\272\220\347\240\201.js" index 19691c05d8..fddffda11b 100644 --- "a/\346\230\216\346\226\207\346\272\220\347\240\201.js" +++ "b/\346\230\216\346\226\207\346\272\220\347\240\201.js" @@ -9,12 +9,12 @@ let subConfig = "https://raw.githubusercontent.com/ACL4SSR/ACL4SSR/master/Clash/ let subProtocol = 'https'; let subEmoji = 'true'; let socks5Address = ''; -let parsedSocks5Address = {}; +let parsedSocks5Address = {}; let enableSocks = false; -let fakeUserID ; -let fakeHostName ; -let noTLS = 'false'; +let fakeUserID; +let fakeHostName; +let noTLS = 'false'; const expire = 4102329600;//2099-12-31 let proxyIPs; let socks5s; @@ -33,11 +33,11 @@ let DLS = 8; let remarkIndex = 1;//CSV备注所在列偏移量 let FileName = atob('ZWRnZXR1bm5lbA=='); let BotToken; -let ChatID; +let ChatID; let proxyhosts = []; let proxyhostsURL = ''; let RproxyIP = 'false'; -let httpsPorts = ["2053","2083","2087","2096","8443"]; +let httpsPorts = ["2053", "2083", "2087", "2096", "8443"]; let 有效时间 = 7; let 更新时间 = 3; let userIDLow; @@ -63,7 +63,7 @@ export default { } if (!userID) { - return new Response('请设置你的UUID变量,或尝试重试部署,检查变量是否生效?', { + return new Response('请设置你的UUID变量,或尝试重试部署,检查变量是否生效?', { status: 404, headers: { "Content-Type": "text/plain;charset=utf-8", @@ -71,7 +71,7 @@ export default { }); } const currentDate = new Date(); - currentDate.setHours(0, 0, 0, 0); + currentDate.setHours(0, 0, 0, 0); const timestamp = Math.ceil(currentDate.getTime() / 1000); const fakeUserIDMD5 = await 双重哈希(`${userID}${timestamp}`); fakeUserID = [ @@ -81,7 +81,7 @@ export default { fakeUserIDMD5.slice(16, 20), fakeUserIDMD5.slice(20) ].join('-'); - + fakeHostName = `${fakeUserIDMD5.slice(6, 9)}.${fakeUserIDMD5.slice(13, 19)}`; proxyIP = env.PROXYIP || env.proxyip || proxyIP; @@ -121,14 +121,14 @@ export default { DLS = Number(env.DLS) || DLS; remarkIndex = Number(env.CSVREMARK) || remarkIndex; BotToken = env.TGTOKEN || BotToken; - ChatID = env.TGID || ChatID; + ChatID = env.TGID || ChatID; FileName = env.SUBNAME || FileName; subEmoji = env.SUBEMOJI || env.EMOJI || subEmoji; if (subEmoji == '0') subEmoji = 'false'; - if (env.LINK) link = await 整理(env.LINK) ; + if (env.LINK) link = await 整理(env.LINK); sub = env.SUB || sub; subConverter = env.SUBAPI || subConverter; - if (subConverter.includes("http://") ){ + if (subConverter.includes("http://")) { subConverter = subConverter.split("//")[1]; subProtocol = 'http'; } else { @@ -172,12 +172,12 @@ export default { //const timestamp = Math.floor(now / 1000); const today = new Date(now); today.setHours(0, 0, 0, 0); - const UD = Math.floor(((now - today.getTime())/86400000) * 24 * 1099511627776 / 2); + const UD = Math.floor(((now - today.getTime()) / 86400000) * 24 * 1099511627776 / 2); let pagesSum = UD; let workersSum = UD; - let total = 24 * 1099511627776 ; + let total = 24 * 1099511627776; - if (userAgent && userAgent.includes('mozilla')){ + if (userAgent && userAgent.includes('mozilla')) { return new Response(`
${维列斯Config}
`, { status: 200, headers: { @@ -208,7 +208,7 @@ export default { if (new RegExp('/socks5=', 'i').test(url.pathname)) socks5Address = url.pathname.split('5=')[1]; else if (new RegExp('/socks://', 'i').test(url.pathname) || new RegExp('/socks5://', 'i').test(url.pathname)) { socks5Address = url.pathname.split('://')[1].split('#')[0]; - if (socks5Address.includes('@')){ + if (socks5Address.includes('@')) { let userPassword = socks5Address.split('@')[0]; const base64Regex = /^(?:[A-Z0-9+/]{4})*(?:[A-Z0-9+/]{2}==|[A-Z0-9+/]{3}=)?$/i; if (base64Regex.test(userPassword) && !userPassword.includes(':')) userPassword = atob(userPassword); @@ -229,7 +229,7 @@ export default { enableSocks = false; } - if (url.searchParams.has('proxyip')){ + if (url.searchParams.has('proxyip')) { proxyIP = url.searchParams.get('proxyip'); enableSocks = false; } else if (new RegExp('/proxyip=', 'i').test(url.pathname)) { @@ -360,7 +360,7 @@ async function 维列斯OverWSHandler(request) { async function handleTCPOutBound(remoteSocket, addressType, addressRemote, portRemote, rawClientData, webSocket, 维列斯ResponseHeader, log,) { async function useSocks5Pattern(address) { - if ( go2Socks5s.includes(atob('YWxsIGlu')) || go2Socks5s.includes(atob('Kg==')) ) return true; + if (go2Socks5s.includes(atob('YWxsIGlu')) || go2Socks5s.includes(atob('Kg=='))) return true; return go2Socks5s.some(pattern => { let regexPattern = pattern.replace(/\*/g, '.*'); let regex = new RegExp(`^${regexPattern}$`, 'i'); @@ -419,7 +419,7 @@ async function handleTCPOutBound(remoteSocket, addressType, addressRemote, portR } let useSocks = false; - if (go2Socks5s.length > 0 && enableSocks ) useSocks = await useSocks5Pattern(addressRemote); + if (go2Socks5s.length > 0 && enableSocks) useSocks = await useSocks5Pattern(addressRemote); // 首次尝试连接远程服务器 let tcpSocket = await connectAndWrite(addressRemote, portRemote, useSocks); @@ -750,15 +750,15 @@ function base64ToArrayBuffer(base64Str) { // 这种变体使用 '-' 和 '_' 来代替标准 Base64 中的 '+' 和 '/' // JavaScript 的 atob 函数不直接支持这种变体,所以我们需要先转换 base64Str = base64Str.replace(/-/g, '+').replace(/_/g, '/'); - + // 使用 atob 函数解码 Base64 字符串 // atob 将 Base64 编码的 ASCII 字符串转换为原始的二进制字符串 const decode = atob(base64Str); - + // 将二进制字符串转换为 Uint8Array // 这是通过遍历字符串中的每个字符并获取其 Unicode 编码值(0-255)来完成的 const arryBuffer = Uint8Array.from(decode, (c) => c.charCodeAt(0)); - + // 返回 Uint8Array 的底层 ArrayBuffer // 这是实际的二进制数据,可以用于网络传输或其他二进制操作 return { earlyData: arryBuffer.buffer, error: null }; @@ -776,7 +776,7 @@ function base64ToArrayBuffer(base64Str) { function isValidUUID(uuid) { // 定义一个正则表达式来匹配 UUID 格式 const uuidRegex = /^[0-9a-f]{8}-[0-9a-f]{4}-[4][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i; - + // 使用正则表达式测试 UUID 字符串 return uuidRegex.test(uuid); } @@ -839,7 +839,7 @@ function stringify(arr, offset = 0) { // 验证生成的 UUID 是否有效 if (!isValidUUID(uuid)) { // 原:throw TypeError("Stringified UUID is invalid"); - throw TypeError(`生成的 UUID 不符合规范 ${uuid}`); + throw TypeError(`生成的 UUID 不符合规范 ${uuid}`); //uuid = userID; } return uuid; @@ -1108,14 +1108,14 @@ function socks5AddressParser(address) { */ function 恢复伪装信息(content, userID, hostName, isBase64) { if (isBase64) content = atob(content); // 如果内容是Base64编码的,先解码 - + // 使用正则表达式全局替换('g'标志) // 将所有出现的假用户ID和假主机名替换为真实的值 content = content.replace(new RegExp(fakeUserID, 'g'), userID) - .replace(new RegExp(fakeHostName, 'g'), hostName); - + .replace(new RegExp(fakeHostName, 'g'), hostName); + if (isBase64) content = btoa(content); // 如果原内容是Base64编码的,处理完后再次编码 - + return content; } @@ -1137,7 +1137,7 @@ async function 双重哈希(文本) { const 第二次哈希 = await crypto.subtle.digest('MD5', 编码器.encode(第一次十六进制.slice(7, 27))); const 第二次哈希数组 = Array.from(new Uint8Array(第二次哈希)); const 第二次十六进制 = 第二次哈希数组.map(字节 => 字节.toString(16).padStart(2, '0')).join(''); - + return 第二次十六进制.toLowerCase(); } @@ -1184,34 +1184,34 @@ async function 代理URL(代理网址, 目标网址) { const 啥啥啥_写的这是啥啊 = atob('ZG14bGMzTT0='); function 配置信息(UUID, 域名地址) { const 协议类型 = atob(啥啥啥_写的这是啥啊); - + const 别名 = FileName; let 地址 = 域名地址; let 端口 = 443; const 用户ID = UUID; const 加密方式 = 'none'; - + const 传输层协议 = 'ws'; const 伪装域名 = 域名地址; const 路径 = path; - - let 传输层安全 = ['tls',true]; + + let 传输层安全 = ['tls', true]; const SNI = 域名地址; const 指纹 = 'randomized'; - if (域名地址.includes('.workers.dev')){ + if (域名地址.includes('.workers.dev')) { 地址 = atob('dmlzYS5jbg=='); - 端口 = 80 ; - 传输层安全 = ['',false]; + 端口 = 80; + 传输层安全 = ['', false]; } - const 威图瑞 = `${协议类型}://${用户ID}@${地址}:${端口}\u003f\u0065\u006e\u0063\u0072\u0079`+'p'+`${atob('dGlvbj0=') + 加密方式}\u0026\u0073\u0065\u0063\u0075\u0072\u0069\u0074\u0079\u003d${传输层安全[0]}&sni=${SNI}&fp=${指纹}&type=${传输层协议}&host=${伪装域名}&path=${encodeURIComponent(路径)}#${encodeURIComponent(别名)}`; + const 威图瑞 = `${协议类型}://${用户ID}@${地址}:${端口}\u003f\u0065\u006e\u0063\u0072\u0079` + 'p' + `${atob('dGlvbj0=') + 加密方式}\u0026\u0073\u0065\u0063\u0075\u0072\u0069\u0074\u0079\u003d${传输层安全[0]}&sni=${SNI}&fp=${指纹}&type=${传输层协议}&host=${伪装域名}&path=${encodeURIComponent(路径)}#${encodeURIComponent(别名)}`; const 猫猫猫 = `- {name: ${FileName}, server: ${地址}, port: ${端口}, type: ${协议类型}, uuid: ${用户ID}, tls: ${传输层安全[1]}, alpn: [h3], udp: false, sni: ${SNI}, tfo: false, skip-cert-verify: true, servername: ${伪装域名}, client-fingerprint: ${指纹}, network: ${传输层协议}, ws-opts: {path: "${路径}", headers: {${伪装域名}}}}`; - return [威图瑞,猫猫猫]; + return [威图瑞, 猫猫猫]; } -let subParams = ['sub','base64','b64','clash','singbox','sb']; +let subParams = ['sub', 'base64', 'b64', 'clash', 'singbox', 'sb']; const cmad = decodeURIComponent(atob('dGVsZWdyYW0lMjAlRTQlQkElQTQlRTYlQjUlODElRTclQkUlQTQlMjAlRTYlOEElODAlRTYlOUMlQUYlRTUlQTQlQTclRTQlQkQlQUMlN0UlRTUlOUMlQTglRTclQkElQkYlRTUlOEYlOTElRTclODklOEMhJTNDYnIlM0UKJTNDYSUyMGhyZWYlM0QlMjdodHRwcyUzQSUyRiUyRnQubWUlMkZDTUxpdXNzc3MlMjclM0VodHRwcyUzQSUyRiUyRnQubWUlMkZDTUxpdXNzc3MlM0MlMkZhJTNFJTNDYnIlM0UKLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tJTNDYnIlM0UKZ2l0aHViJTIwJUU5JUExJUI5JUU3JTlCJUFFJUU1JTlDJUIwJUU1JTlEJTgwJTIwU3RhciFTdGFyIVN0YXIhISElM0NiciUzRQolM0NhJTIwaHJlZiUzRCUyN2h0dHBzJTNBJTJGJTJGZ2l0aHViLmNvbSUyRmNtbGl1JTJGZWRnZXR1bm5lbCUyNyUzRWh0dHBzJTNBJTJGJTJGZ2l0aHViLmNvbSUyRmNtbGl1JTJGZWRnZXR1bm5lbCUzQyUyRmElM0UlM0NiciUzRQotLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0lM0NiciUzRQolMjMlMjMlMjMlMjMlMjMlMjMlMjMlMjMlMjMlMjMlMjMlMjMlMjMlMjMlMjMlMjMlMjMlMjMlMjMlMjMlMjMlMjMlMjMlMjMlMjMlMjMlMjMlMjMlMjMlMjMlMjMlMjMlMjMlMjMlMjMlMjMlMjMlMjMlMjMlMjMlMjMlMjMlMjMlMjMlMjMlMjMlMjMlMjMlMjMlMjMlMjMlMjMlMjMlMjMlMjMlMjMlMjMlMjMlMjMlMjMlMjMlMjMlMjMlMjM=')); /** * @param {string} userID @@ -1229,7 +1229,7 @@ async function 生成配置信息(userID, hostName, sub, UA, RproxyIP, _url, env const subs = await 整理(sub); if (subs.length > 1) sub = subs[0]; } else { - if (env.KV){ + if (env.KV) { await 迁移地址列表(env); const 优选地址列表 = await env.KV.get('ADD.txt'); if (优选地址列表) { @@ -1239,7 +1239,7 @@ async function 生成配置信息(userID, hostName, sub, UA, RproxyIP, _url, env 链接地址: new Set(), 优选地址: new Set() }; - + for (const 元素 of 优选地址数组) { if (元素.startsWith('https://')) { 分类地址.接口地址.add(元素); @@ -1249,14 +1249,14 @@ async function 生成配置信息(userID, hostName, sub, UA, RproxyIP, _url, env 分类地址.优选地址.add(元素); } } - + addressesapi = [...分类地址.接口地址]; link = [...分类地址.链接地址]; addresses = [...分类地址.优选地址]; } } - - if ((addresses.length + addressesapi.length + addressesnotls.length + addressesnotlsapi.length + addressescsv.length) == 0){ + + if ((addresses.length + addressesapi.length + addressesnotls.length + addressesnotlsapi.length + addressescsv.length) == 0) { // 定义 Cloudflare IP 范围的 CIDR 列表 let cfips = [ '103.21.244.0/23', @@ -1271,7 +1271,7 @@ async function 生成配置信息(userID, hostName, sub, UA, RproxyIP, _url, env '188.114.96.0/21', '190.93.240.0/21', ]; - + // 生成符合给定 CIDR 范围的随机 IP 地址 function generateRandomIPFromCIDR(cidr) { const [base, mask] = cidr.split('/'); @@ -1279,13 +1279,13 @@ async function 生成配置信息(userID, hostName, sub, UA, RproxyIP, _url, env const subnetMask = 32 - parseInt(mask, 10); const maxHosts = Math.pow(2, subnetMask) - 1; const randomHost = Math.floor(Math.random() * maxHosts); - + const randomIP = baseIP.map((octet, index) => { if (index < 2) return octet; if (index === 2) return (octet & (255 << (subnetMask - 8))) + ((randomHost >> 8) & 255); return (octet & (255 << subnetMask)) + (randomHost & 255); }); - + return randomIP.join('.'); } addresses = addresses.concat('127.0.0.1:1234#CFnat'); @@ -1299,30 +1299,30 @@ async function 生成配置信息(userID, hostName, sub, UA, RproxyIP, _url, env const uuid = (_url.pathname == `/${动态UUID}`) ? 动态UUID : userID; const userAgent = UA.toLowerCase(); - const Config = 配置信息(userID , hostName); + const Config = 配置信息(userID, hostName); const v2ray = Config[0]; const clash = Config[1]; let proxyhost = ""; - if(hostName.includes(".workers.dev")){ - if ( proxyhostsURL && (!proxyhosts || proxyhosts.length == 0)) { + if (hostName.includes(".workers.dev")) { + if (proxyhostsURL && (!proxyhosts || proxyhosts.length == 0)) { try { - const response = await fetch(proxyhostsURL); - + const response = await fetch(proxyhostsURL); + if (!response.ok) { console.error('获取地址时出错:', response.status, response.statusText); return; // 如果有错误,直接返回 } - + const text = await response.text(); const lines = text.split('\n'); // 过滤掉空行或只包含空白字符的行 const nonEmptyLines = lines.filter(line => line.trim() !== ''); - + proxyhosts = proxyhosts.concat(nonEmptyLines); } catch (error) { //console.error('获取地址时出错:', error); } - } + } if (proxyhosts.length != 0) proxyhost = proxyhosts[Math.floor(Math.random() * proxyhosts.length)] + "/"; } @@ -1334,9 +1334,9 @@ async function 生成配置信息(userID, hostName, sub, UA, RproxyIP, _url, env }); let socks5List = ''; - if (go2Socks5s.length > 0 && enableSocks ) { + if (go2Socks5s.length > 0 && enableSocks) { socks5List = `${decodeURIComponent('SOCKS5%EF%BC%88%E7%99%BD%E5%90%8D%E5%8D%95%EF%BC%89%3A%20')}`; - if (go2Socks5s.includes(atob('YWxsIGlu'))||go2Socks5s.includes(atob('Kg=='))) socks5List += `${decodeURIComponent('%E6%89%80%E6%9C%89%E6%B5%81%E9%87%8F')}
`; + if (go2Socks5s.includes(atob('YWxsIGlu')) || go2Socks5s.includes(atob('Kg=='))) socks5List += `${decodeURIComponent('%E6%89%80%E6%9C%89%E6%B5%81%E9%87%8F')}
`; else socks5List += `
  ${go2Socks5s.join('
  ')}
`; } @@ -1366,23 +1366,20 @@ async function 生成配置信息(userID, hostName, sub, UA, RproxyIP, _url, env const 动态UUID信息 = (uuid != userID) ? `TOKEN: ${uuid}
UUIDNow: ${userID}
UUIDLow: ${userIDLow}
${userIDTime}TIME(动态UUID有效时间): ${有效时间} 天
UPTIME(动态UUID更新时间): ${更新时间} 时(北京时间)

` : `${userIDTime}`; const 节点配置页 = ` ################################################################
- Subscribe / sub 订阅地址, 支持 Base64、clash-meta、sing-box 订阅格式
+ Subscribe / sub 订阅地址, 点击链接自动 复制订阅链接生成订阅二维码
---------------------------------------------------------------
自适应订阅地址:
- https://${proxyhost}${hostName}/${uuid}
- https://${proxyhost}${hostName}/${uuid}?sub
-
+ https://${proxyhost}${hostName}/${uuid}
+
Base64订阅地址:
- https://${proxyhost}${hostName}/${uuid}?b64
- https://${proxyhost}${hostName}/${uuid}?base64
-
+ https://${proxyhost}${hostName}/${uuid}?b64
+
clash订阅地址:
- https://${proxyhost}${hostName}/${uuid}?clash
-
+ https://${proxyhost}${hostName}/${uuid}?clash
+
singbox订阅地址:
- https://${proxyhost}${hostName}/${uuid}?sb
- https://${proxyhost}${hostName}/${uuid}?singbox
-
+ https://${proxyhost}${hostName}/${uuid}?sb
+
实用订阅技巧∨
+