diff --git a/README-fa.md b/README-fa.md index 6fc2334..7c2f483 100644 --- a/README-fa.md +++ b/README-fa.md @@ -59,14 +59,14 @@ ## درباره متغیر ها -> برای مشاهده توضیحات بیشتر درباره چگونگی ایجاد متغییر‌ها به [این لینک](https://github.com/bia-pain-bache/BPB-Worker-Panel/blob/main/docs/pages_installation_fa.md#3--%D8%AA%D8%BA%DB%8C%DB%8C%D8%B1-%D9%BE%D8%B3%D9%88%D8%B1%D8%AF%D9%87%D8%A7%DB%8C-trojan) مراجعه کنید. +> برای مشاهده توضیحات بیشتر درباره چگونگی ایجاد متغییر‌ها به [این لینک](https://github.com/NiREvil/bia-pain-bache/blob/main/docs/pages_installation_fa.md#3--%D8%AA%D8%BA%DB%8C%DB%8C%D8%B1-%D9%BE%D8%B3%D9%88%D8%B1%D8%AF%D9%87%D8%A7%DB%8C-trojan) مراجعه کنید. ![rainbow](https://github.com/NiREvil/vless/assets/126243832/1aca7f5d-6495-44b7-aced-072bae52f256) | نام متغیر | مثال | الزام | توضیحات| |-----|----|--|------------| | UUID | `90cd4a77-141a-43c9-991b-08263cfe9c10` |✅|برای ایجاد آی‌دی خود به [این لینک](https://www.uuidgenerator.net/)مراجعه کنید. | -| PROXYIP | `bpp.radically.pro` |❌|برای دسترسی به سایت‌هایی که از سی‌دی‌ان کلادفلر استفاده می‌کنند باید از پروکسی‌ آی‌پی‌ها استفاده کنیم، پشتیبانی از چند پروکسی آی‌پی، برای مثال : ```['bpb.radically.pro', 'bpb.yousef.isegaro.com'];```برای پیدا کردن پروکسی‌های بیشتر به [این لینک](https://github.com/NiREvil/vless/blob/main/sub/ProxyIP.md) مراجعه کنید. | +| PROXYIP | `bpb.radically.pro` |❌|برای دسترسی به سایت‌هایی که از سی‌دی‌ان کلادفلر استفاده می‌کنند باید از پروکسی‌ آی‌پی‌ها استفاده کنیم، پشتیبانی از چند پروکسی آی‌پی، برای مثال : ```['bpb.radically.pro', 'bpb.yousef.isegaro.com'];```برای پیدا کردن پروکسی‌های بیشتر به [این لینک](https://github.com/NiREvil/vless/blob/main/sub/ProxyIP.md) مراجعه کنید. | | TROJAN_PASS | `REvil` |✅|پسوورد دلخواه شما برای کانفیگ‌های تروجان | | HASH_PASS | `6dfd0e8e67ad3230498f80938cb924bc767b7` |✅| پسوورد تروجان دلخواه شما باید به رشته‌های هش SHA-224 به منزله ذخیره ایمن رمز عبور و تأیید صحت داده ها تبدیل شود، برای انجام تبدیل به [این لینک](https://emn178.github.io/online-tools/sha224.html) مراجعه کنید. | @@ -91,6 +91,18 @@

+ +

+ +

+ + + +

+ +

+ +

diff --git a/README.md b/README.md index e7e8588..a8161ff 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -## $$\color{silver} \Large \text{BPB v2.5.5}$$ +## $$\color{silver} \Large \text{BPB v2.6}$$ > __[🇮🇷Persian](README-fa.md)__ __[🇬🇧English](README.md)__ @@ -55,13 +55,13 @@ HUGE THANKS TO ## Variable description -> For further information on how to create variables, please refer to [this link](https://github.com/bia-pain-bache/BPB-Worker-Panel/blob/main/docs/pages_installation_fa.md#3--%D8%AA%D8%BA%DB%8C%DB%8C%D8%B1-%D9%BE%D8%B3%D9%88%D8%B1%D8%AF%D9%87%D8%A7%DB%8C-trojan). +> For further information on how to create variables, please refer to [this link](https://github.com/NiREvil/bia-pain-bache/blob/main/docs/pages_installation_fa.md#3--%D8%AA%D8%BA%DB%8C%DB%8C%D8%B1-%D9%BE%D8%B3%D9%88%D8%B1%D8%AF%D9%87%D8%A7%DB%8C-trojan). ![rainbow](https://github.com/NiREvil/vless/assets/126243832/1aca7f5d-6495-44b7-aced-072bae52f256) | Variable Name | Example | Required | Remark | |-----|----|--|------------| | UUID | `90cd4a77-141a-43c9-991b-08263cfe9c10` |✅| To generate your own UUID refer to [this link](https://www.uuidgenerator.net/) | -| PROXYIP | `bpp.radically.pro` |❌| Alternative as a proxy node for accessing CloudFlareCDN site (supports multiple ProxyIPs, ex: ```['bpb.radically.pro', 'bpb.yousef.isegaro.com'];``` To find proxyIP [check here](https://github.com/NiREvil/vless/blob/main/sub/ProxyIP.md) | +| PROXYIP | `bpb.radically.pro` |❌| Alternative as a proxy node for accessing CloudFlareCDN site (supports multiple ProxyIPs, ex: ```['bpb.radically.pro', 'bpb.yousef.isegaro.com'];``` To find proxyIP [check here](https://github.com/NiREvil/vless/blob/main/sub/ProxyIP.md) | | TROJAN_PASS | `REvil` |✅| Your preferred password | | HASH_PASS | `6dfd0e8e67ad3230498f80938cb924bc767b7` |✅| Your preferred trojan password should be converted to SHA-224 Hash string to securely store password and verify data integrity, To perform this conversion refer to [this link](https://emn178.github.io/online-tools/sha224.html) | @@ -87,6 +87,16 @@ HUGE THANKS TO

+

+ +

+ +

+ +

+ +

+

--- diff --git a/_worker.js b/_worker.js index d28c5c1..efe7f98 100644 --- a/_worker.js +++ b/_worker.js @@ -1,6 +1,6 @@ /** * @ts-nocheck version base on commit 43fad05dcdae3b723c53c226f8181fc5bd47223e, time is 2023-06-22 15:20:02 UTC. -* Last Update: 4:20 UTC - Thursday, 19 September 2024, By @Sahar-KM , @Diana-Cl & Nesa @nescafetor +* Last Update: 4:20 UTC - Sunday, 29 September 2024, By @Sahar-KM , @Diana-Cl , Nesa @EEvanescence * Many thanks to github.com/bia-pain-bache */ import { connect } from 'cloudflare:sockets'; @@ -19,15 +19,10 @@ let trojanPassword = `REvil`; // https://emn178.github.io/online-tools/sha224.html // https://www.atatus.com/tools/sha224-to-hash let hashPassword = '6dfd0e8e67ad3230498f80938cb924bc767b7db65eb4c9545fbe4ad7'; -let panelVersion = 'v2.5.5'; +let panelVersion = 'V2.6'; -if (!isValidUUID(userID)) { - throw new Error('UUID is not valid'); -} - -if (!isValidSHA224(hashPassword)) { - throw new Error('Hash Password is not valid'); -} +if (!isValidUUID(userID)) throw new Error(`Invalid UUID: ${userID}`); +if (!isValidSHA224(hashPassword)) throw new Error(`Invalid Hash password: ${hashPassword}`); export default { /** @@ -92,7 +87,9 @@ export default { return new Response(JSON.stringify(BestPingSFA, null, 4), { status: 200, headers: { - "Content-Type": "text/plain;charset=utf-8", + 'Content-Type': 'application/json;charset=utf-8', + 'Cache-Control': 'no-store, no-cache, must-revalidate, proxy-revalidate', + 'Surrogate-Control': 'no-store' } }); } @@ -102,7 +99,9 @@ export default { return new Response(JSON.stringify(BestPingClash, null, 4), { status: 200, headers: { - "Content-Type": "text/plain;charset=utf-8", + 'Content-Type': 'application/json;charset=utf-8', + 'Cache-Control': 'no-store, no-cache, must-revalidate, proxy-revalidate', + 'Surrogate-Control': 'no-store' } }); } @@ -111,19 +110,24 @@ export default { return new Response(normalConfigs, { status: 200, headers: { - "Content-Type": "text/plain;charset=utf-8", + 'Content-Type': 'text/plain;charset=utf-8', + 'Cache-Control': 'no-store, no-cache, must-revalidate, proxy-revalidate', + 'Surrogate-Control': 'no-store' } }); case `/fragsub/${userID}`: - - let fragConfigs = await getFragmentConfigs(env, host, 'v2ray'); - fragConfigs = fragConfigs.map(config => config.config); + + let fragConfigs = client === 'hiddify' + ? await getSingboxConfig(env, host, client, false, true) + : (await getFragmentConfigs(env, host)); return new Response(JSON.stringify(fragConfigs, null, 4), { status: 200, headers: { - "Content-Type": "text/plain;charset=utf-8", + 'Content-Type': 'application/json;charset=utf-8', + 'Cache-Control': 'no-store, no-cache, must-revalidate, proxy-revalidate', + 'Surrogate-Control': 'no-store' } }); @@ -134,7 +138,9 @@ export default { return new Response(JSON.stringify(clashWarpConfigs, null, 4), { status: 200, headers: { - "Content-Type": "text/plain;charset=utf-8", + 'Content-Type': 'application/json;charset=utf-8', + 'Cache-Control': 'no-store, no-cache, must-revalidate, proxy-revalidate', + 'Surrogate-Control': 'no-store' } }); } @@ -144,7 +150,9 @@ export default { return new Response(JSON.stringify(singboxWarpConfigs, null, 4), { status: 200, headers: { - "Content-Type": "text/plain;charset=utf-8", + 'Content-Type': 'application/json;charset=utf-8', + 'Cache-Control': 'no-store, no-cache, must-revalidate, proxy-revalidate', + 'Surrogate-Control': 'no-store' } }); } @@ -153,7 +161,9 @@ export default { return new Response(JSON.stringify(warpConfig, null, 4), { status: 200, headers: { - "Content-Type": "text/plain;charset=utf-8", + 'Content-Type': 'application/json;charset=utf-8', + 'Cache-Control': 'no-store, no-cache, must-revalidate, proxy-revalidate', + 'Surrogate-Control': 'no-store' } }); @@ -168,9 +178,12 @@ export default { const isAuth = await Authenticate(request, env); if (request.method === 'POST') { - if (!isAuth) return new Response('Unauthorized', { status: 401 }); + if (!isAuth) return new Response('Unauthorized', { status: 401 }); const formData = await request.formData(); - await updateDataset(env, formData); + const isReset = formData.get('resetSettings') === 'true'; + isReset + ? await updateDataset(env, null, true) + : await updateDataset(env, formData); return new Response('Success', { status: 200 }); } @@ -179,8 +192,7 @@ export default { const proxySettings = await env.bpb.get('proxySettings', {type: 'json'}); const isUpdated = panelVersion === proxySettings?.panelVersion; if (!proxySettings || !isUpdated) await updateDataset(env); - const fragConfs = await getFragmentConfigs(env, host, 'nekoray'); - const homePage = await renderHomePage(env, host, fragConfs); + const homePage = await renderHomePage(env, host); return new Response(homePage, { status: 200, @@ -639,7 +651,7 @@ async function handleTCPOutBound( vlessResponseHeader ? vlessRemoteSocketToWS(tcpSocket, webSocket, vlessResponseHeader, null, log) - : trojanRemoteSocketToWS(tcpSocket2, webSocket, null, log); + : trojanRemoteSocketToWS(tcpSocket, webSocket, null, log); } const tcpSocket = await connectAndWrite(addressRemote, portRemote); @@ -1110,42 +1122,65 @@ async function handleUDPOutBound(webSocket, vlessResponseHeader, log) { * @returns {string} */ -function generateRemark(index, port, protocol, fragType) { +function generateRemark(index, port, address, cleanIPs, protocol, configType) { let remark = ''; - const type = fragType ? ' ⇢F' : ''; - switch (index) { - case 0: - case 1: - remark = `⇢${protocol}${type} ⇢Ðoϻɑiͷ ${index + 1} ⇢${port}`; - break; - case 2: - case 3: - remark = `⇢${protocol}${type} ⇢IPV4 ${index - 1} ⇢${port}`; - break; - case 4: - case 5: - remark = `⇢${protocol}${type} ⇢IPV6 ${index - 3} ⇢${port}`; - break; - default: - remark = `⇢${protocol}${type} ⇢CLEAN IP ${index - 5} ⇢${port}`; - break; - } + let addressType; + const type = configType ? ` ${configType}` : ''; + + cleanIPs.includes(address) + ? addressType = 'CLEAN IP' + : addressType = isDomain(address) ? 'Ðoϻɑiͷ': isIPv4(address) ? 'IPV4' : isIPv6(address) ? 'IPV6' : ''; - return remark; + return `⇢${protocol}${type} ⇢${addressType} : ${port} ¦${index}¦`; } -async function extractVlessParams(vlessConfig) { - const url = new URL(vlessConfig.replace('vless', 'http')); - const params = new URLSearchParams(url.search); - let configParams = { - uuid : url.username, - hostName : url.hostname, - port : url.port - }; +function isDomain(address) { + const domainPattern = /^(?!\-)(?:[A-Za-z0-9\-]{1,63}\.?)+[A-Za-z]{2,}$/; + return domainPattern.test(address); +} - params.forEach( (value, key) => { - configParams[key] = value; - }) +function isIPv4(address) { + const ipv4Pattern = /^(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/; + return ipv4Pattern.test(address); +} + +function isIPv6(address) { + const ipv6Pattern = /^\[(?:(?:[a-fA-F0-9]{1,4}:){7}[a-fA-F0-9]{1,4}|(?:[a-fA-F0-9]{1,4}:){1,7}:|::(?:[a-fA-F0-9]{1,4}:){0,7}|(?:[a-fA-F0-9]{1,4}:){1,6}:[a-fA-F0-9]{1,4}|(?:[a-fA-F0-9]{1,4}:){1,5}(?::[a-fA-F0-9]{1,4}){1,2}|(?:[a-fA-F0-9]{1,4}:){1,4}(?::[a-fA-F0-9]{1,4}){1,3}|(?:[a-fA-F0-9]{1,4}:){1,3}(?::[a-fA-F0-9]{1,4}){1,4}|(?:[a-fA-F0-9]{1,4}:){1,2}(?::[a-fA-F0-9]{1,4}){1,5}|[a-fA-F0-9]{1,4}:(?::[a-fA-F0-9]{1,4}){1,6})\]$/; + return ipv6Pattern.test(address); +} + +function extractChainProxyParams(chainProxy) { + let configParams = {}; + + if (chainProxy.startsWith('vless')) { + const url = new URL(chainProxy.replace('vless', 'http')); + const params = new URLSearchParams(url.search); + configParams = { + uuid : url.username, + hostName : url.hostname, + port : url.port + }; + + params.forEach( (value, key) => { + configParams[key] = value; + }); + } else { + const regex = /^(http|socks):\/\/(?:([^:@]+):([^:@]+)@)?([^:@]+):(\d+)$/; + const matches = chainProxy.match(regex); + const protocol = matches[1]; + const user = matches[2] || ''; + const pass = matches[3] || ''; + const host = matches[4]; + const port = matches[5]; + + configParams = { + protocol: protocol, + user : user, + pass : pass, + host : host, + port : port + }; + } return JSON.stringify(configParams); } @@ -1157,50 +1192,58 @@ function base64ToDecimal (base64) { return decimalArray; } -async function updateDataset (env, Settings) { - let currentProxySettings = {}; +async function updateDataset (env, Settings, resetSettings) { + let currentProxySettings; - try { - currentProxySettings = await env.bpb.get("proxySettings", {type: 'json'}); - } catch (error) { - console.log(error); - throw new Error(`An error occurred while getting current values - ${error}`); + if (!resetSettings) { + try { + currentProxySettings = await env.bpb.get("proxySettings", {type: 'json'}); + } catch (error) { + console.log(error); + throw new Error(`An error occurred while getting current values - ${error}`); + } + } else { + await env.bpb.delete('warpConfigs'); } - const vlessConfig = Settings?.get('outProxy'); - + const chainProxy = Settings?.get('outProxy'); const proxySettings = { - remoteDNS: Settings ? Settings.get('remoteDNS') : currentProxySettings?.remoteDNS || 'https://cloudflare-dns.com/dns-query', - localDNS: Settings ? Settings.get('localDNS') : currentProxySettings?.localDNS || '8.8.8.8', - lengthMin: Settings ? Settings.get('fragmentLengthMin') : currentProxySettings?.lengthMin || '10', - lengthMax: Settings ? Settings.get('fragmentLengthMax') : currentProxySettings?.lengthMax || '30', - intervalMin: Settings ? Settings.get('fragmentIntervalMin') : currentProxySettings?.intervalMin || '1', - intervalMax: Settings ? Settings.get('fragmentIntervalMax') : currentProxySettings?.intervalMax || '2', - fragmentPackets: Settings ? Settings.get('fragmentPackets') : currentProxySettings?.fragmentPackets || 'tlshello', - blockAds: Settings ? Settings.get('block-ads') : currentProxySettings?.blockAds || false, - bypassIran: Settings ? Settings.get('bypass-iran') : currentProxySettings?.bypassIran || false, - blockPorn: Settings ? Settings.get('block-porn') : currentProxySettings?.blockPorn || false, - bypassLAN: Settings ? Settings.get('bypass-lan') : currentProxySettings?.bypassLAN || false, - bypassChina: Settings ? Settings.get('bypass-china') : currentProxySettings?.bypassChina || false, - blockUDP443: Settings ? Settings.get('block-udp-443') : currentProxySettings?.blockUDP443 || false, - cleanIPs: Settings ? Settings.get('cleanIPs')?.replaceAll(' ', '') : currentProxySettings?.cleanIPs || '', - proxyIP: Settings ? Settings.get('proxyIP') : currentProxySettings?.proxyIP || '', - ports: Settings ? Settings.getAll('ports[]') : currentProxySettings?.ports || ['443'], - vlessConfigs: Settings ? Settings.get('vlessConfigs') : currentProxySettings?.vlessConfigs || true, - trojanConfigs: Settings ? Settings.get('trojanConfigs') : currentProxySettings?.trojanConfigs || false, - outProxy: Settings ? vlessConfig : currentProxySettings?.outProxy || '', - outProxyParams: vlessConfig ? await extractVlessParams(vlessConfig) : currentProxySettings?.outProxyParams || '', - wowEndpoint: Settings ? Settings.get('wowEndpoint')?.replaceAll?.(' ', '') : currentProxySettings?.wowEndpoint || '188.114.98.1:1010,162.159.192.100:1018,162.159.192.0:955,188.114.97.170:2371,162.159.192.1:988', - warpEndpoints: Settings ? Settings.get('warpEndpoints')?.replaceAll?.(' ', '') : currentProxySettings?.warpEndpoints || '188.114.98.1:1010,162.159.192.100:1018,162.159.192.0:955,188.114.97.170:2371,162.159.192.1:988', - hiddifyNoiseMode: Settings ? Settings.get('hiddifyNoiseMode') : currentProxySettings?.hiddifyNoiseMode || 'm4', - nikaNGNoiseMode: Settings ? Settings.get('nikaNGNoiseMode') : currentProxySettings?.nikaNGNoiseMode || 'quic', - noiseCountMin: Settings ? Settings.get('noiseCountMin') : currentProxySettings?.noiseCountMin || '10', - noiseCountMax: Settings ? Settings.get('noiseCountMax') : currentProxySettings?.noiseCountMax || '30', - noiseSizeMin: Settings ? Settings.get('noiseSizeMin') : currentProxySettings?.noiseSizeMin || '5', - noiseSizeMax: Settings ? Settings.get('noiseSizeMax') : currentProxySettings?.noiseSizeMax || '10', - noiseDelayMin: Settings ? Settings.get('noiseDelayMin') : currentProxySettings?.noiseDelayMin || '1', - noiseDelayMax: Settings ? Settings.get('noiseDelayMax') : currentProxySettings?.noiseDelayMax || '1', - warpPlusLicense: Settings ? Settings.get('warpPlusLicense') : currentProxySettings?.warpPlusLicense || '', + remoteDNS: (Settings ? Settings.get('remoteDNS') : currentProxySettings?.remoteDNS) || 'https://dns.google/dns-query', + localDNS: (Settings ? Settings.get('localDNS') : currentProxySettings?.localDNS) || '8.8.8.8', + lengthMin: (Settings ? Settings.get('fragmentLengthMin') : currentProxySettings?.lengthMin) || '10', + lengthMax: (Settings ? Settings.get('fragmentLengthMax') : currentProxySettings?.lengthMax) || '30', + intervalMin: (Settings ? Settings.get('fragmentIntervalMin') : currentProxySettings?.intervalMin) || '1', + intervalMax: (Settings ? Settings.get('fragmentIntervalMax') : currentProxySettings?.intervalMax) || '2', + fragmentPackets: (Settings ? Settings.get('fragmentPackets') : currentProxySettings?.fragmentPackets) || 'tlshello', + blockAds: (Settings ? Settings.get('block-ads') : currentProxySettings?.blockAds) || false, + bypassIran: (Settings ? Settings.get('bypass-iran') : currentProxySettings?.bypassIran) || false, + blockPorn: (Settings ? Settings.get('block-porn') : currentProxySettings?.blockPorn) || false, + bypassLAN: (Settings ? Settings.get('bypass-lan') : currentProxySettings?.bypassLAN) || false, + bypassChina: (Settings ? Settings.get('bypass-china') : currentProxySettings?.bypassChina) || false, + blockUDP443: (Settings ? Settings.get('block-udp-443') : currentProxySettings?.blockUDP443) || false, + cleanIPs: (Settings ? Settings.get('cleanIPs')?.replaceAll(' ', '') : currentProxySettings?.cleanIPs) || '', + proxyIP: (Settings ? Settings.get('proxyIP')?.trim() : currentProxySettings?.proxyIP) || '', + ports: (Settings ? Settings.getAll('ports[]') : currentProxySettings?.ports) || ['443'], + vlessConfigs: (Settings ? Settings.get('vlessConfigs') : currentProxySettings?.vlessConfigs) || true, + trojanConfigs: (Settings ? Settings.get('trojanConfigs') : currentProxySettings?.trojanConfigs) || false, + outProxy: (Settings ? chainProxy : currentProxySettings?.outProxy) || '', + outProxyParams: (chainProxy ? extractChainProxyParams(chainProxy) : currentProxySettings?.outProxyParams) || '', + wowEndpoint: (Settings ? Settings.get('wowEndpoint')?.replaceAll(' ', '') : currentProxySettings?.wowEndpoint) || '162.159.192.175:891,188.114.98.1:1010,162.159.192.100:1018,162.159.192.0:955,188.114.97.170:2371,162.159.192.101:864', + warpEndpoints: (Settings ? Settings.get('warpEndpoints')?.replaceAll(' ', '') : currentProxySettings?.warpEndpoints) || '162.159.192.175:891,188.114.98.1:1010,162.159.192.100:1018,162.159.192.0:955,188.114.97.170:2371,162.159.192.101:864', + hiddifyNoiseMode: (Settings ? Settings.get('hiddifyNoiseMode') : currentProxySettings?.hiddifyNoiseMode) || 'm4', + nikaNGNoiseMode: (Settings ? Settings.get('nikaNGNoiseMode') : currentProxySettings?.nikaNGNoiseMode) || 'quic', + noiseCountMin: (Settings ? Settings.get('noiseCountMin') : currentProxySettings?.noiseCountMin) || '10', + noiseCountMax: (Settings ? Settings.get('noiseCountMax') : currentProxySettings?.noiseCountMax) || '15', + noiseSizeMin: (Settings ? Settings.get('noiseSizeMin') : currentProxySettings?.noiseSizeMin) || '5', + noiseSizeMax: (Settings ? Settings.get('noiseSizeMax') : currentProxySettings?.noiseSizeMax) || '10', + noiseDelayMin: (Settings ? Settings.get('noiseDelayMin') : currentProxySettings?.noiseDelayMin) || '1', + noiseDelayMax: (Settings ? Settings.get('noiseDelayMax') : currentProxySettings?.noiseDelayMax) || '2', + warpPlusLicense: (Settings ? Settings.get('warpPlusLicense') : currentProxySettings?.warpPlusLicense) || '', + customCdnAddrs: (Settings ? Settings.get('customCdnAddrs')?.replaceAll(' ', '') : currentProxySettings?.customCdnAddrs) || '', + customCdnHost: (Settings ? Settings.get('customCdnHost')?.trim() : currentProxySettings?.customCdnHost) || '', + customCdnSni: (Settings ? Settings.get('customCdnSni')?.trim() : currentProxySettings?.customCdnSni) || '', + bestVLESSTrojanInterval: (Settings ? Settings.get('bestVLESSTrojanInterval') : currentProxySettings?.bestVLESSTrojanInterval) || '30', + bestWarpInterval: (Settings ? Settings.get('bestWarpInterval') : currentProxySettings?.bestWarpInterval) || '30', panelVersion: panelVersion }; @@ -1257,6 +1300,17 @@ async function resolveDNS (domain) { } } +async function getConfigAddresses(hostName, cleanIPs) { + const resolved = await resolveDNS(hostName); + return [ + hostName, + 'www.speedtest.net', + ...resolved.ipv4, + ...resolved.ipv6.map((ip) => `[${ip}]`), + ...(cleanIPs ? cleanIPs.split(',') : []) + ]; +} + function generateJWTToken (password, secretKey) { const header = { alg: 'HS256', @@ -1358,7 +1412,12 @@ async function renderHomePage (env, hostName, fragConfigs) { noiseSizeMax, noiseDelayMin, noiseDelayMax, - warpPlusLicense + warpPlusLicense, + customCdnAddrs, + customCdnHost, + customCdnSni, + bestVLESSTrojanInterval, + bestWarpInterval } = proxySettings; const isWarpReady = warpConfigs ? true : false; @@ -1366,33 +1425,6 @@ async function renderHomePage (env, hostName, fragConfigs) { const isWarpPlus = warpPlusLicense ? true : false; let activeProtocols = (vlessConfigs ? 1 : 0) + (trojanConfigs ? 1 : 0); - const genCustomConfRow = async (configs) => { - let tableBlock = ""; - configs.forEach(config => { - tableBlock += ` - - - ${config.address === 'Best-Ping' - ? `
speed  Fragment Best Ping
` - : config.address === 'WorkerLess' - ? `
cloud  WorkerLess Config
` - : config.address === 'Best-Fragment' - ? `
hotel_class  Fragment Best Values
` - : config.address - } - - - - - `; - }); - - return tableBlock; - } - const buildPortsBlock = async () => { let httpPortsBlock = ''; let httpsPortsBlock = ''; @@ -1416,7 +1448,7 @@ async function renderHomePage (env, hostName, fragConfigs) { - BpB panel ${panelVersion} + BPB Panel ${panelVersion}