diff --git a/_worker.js b/_worker.js index 9760e1d1a..650672c29 100644 --- a/_worker.js +++ b/_worker.js @@ -5,14 +5,14 @@ import { connect } from 'cloudflare:sockets'; // [Windows] Press "Win + R", input cmd and run: Powershell -NoExit -Command "[guid]::NewGuid()" let userID = '84c983bc-36c7-4a5f-9fd7-2beec4cade9a'; -const proxyIPs = ['work1.homeip.us.eu.org', 'work2.homeip.us.eu.org', 'work3.homeip.us.eu.org', 'work4.homeip.us.eu.org']; +const พร็อกซีไอพีs = ['work1.homeip.us.eu.org', 'work2.homeip.us.eu.org', 'work3.homeip.us.eu.org', 'work4.homeip.us.eu.org']; -// if you want to use ipv6 or single proxyIP, please add comment at this line and remove comment at the next line -let proxyIP = proxyIPs[Math.floor(Math.random() * proxyIPs.length)]; -// use single proxyIP instead of random -// let proxyIP = 'cdn.xn--b6gac.eu.org'; -// ipv6 proxyIP example remove comment to use -// let proxyIP = "[2a01:4f8:c2c:123f:64:5:6810:c55a]" +// if you want to use ipv6 or single พร็อกซีไอพี, please add comment at this line and remove comment at the next line +let พร็อกซีไอพี = พร็อกซีไอพีs[Math.floor(Math.random() * พร็อกซีไอพีs.length)]; +// use single พร็อกซีไอพี instead of random +// let พร็อกซีไอพี = 'cdn.xn--b6gac.eu.org'; +// ipv6 พร็อกซีไอพี example remove comment to use +// let พร็อกซีไอพี = "[2a01:4f8:c2c:123f:64:5:6810:c55a]" let dohURL = 'https://sky.rethinkdns.com/1:-Pf_____9_8A_AMAIgE8kMABVDDmKOHTAKg='; // https://cloudflare-dns.com/dns-query or https://dns.google/dns-query @@ -23,7 +23,7 @@ if (!isValidUUID(userID)) { export default { /** * @param {import("@cloudflare/workers-types").Request} request - * @param {{UUID: string, PROXYIP: string, DNS_RESOLVER_URL: string, NODE_ID: int, API_HOST: string, API_TOKEN: string}} env + * @param {{UUID: string, พร็อกซีไอพี: string, DNS_RESOLVER_URL: string, NODE_ID: int, API_HOST: string, API_TOKEN: string}} env * @param {import("@cloudflare/workers-types").ExecutionContext} ctx * @returns {Promise} */ @@ -31,7 +31,7 @@ export default { // uuid_validator(request); try { userID = env.UUID || userID; - proxyIP = env.PROXYIP || proxyIP; + พร็อกซีไอพี = env.PROXYIP || พร็อกซีไอพี; dohURL = env.DNS_RESOLVER_URL || dohURL; let userID_Path = userID; if (userID.includes(',')) { @@ -50,8 +50,8 @@ export default { }); } case `/${userID_Path}`: { - const vlessConfig = getVLESSConfig(userID, request.headers.get('Host')); - return new Response(`${vlessConfig}`, { + const วเลสConfig = getวเลสConfig(userID, request.headers.get('Host')); + return new Response(`${วเลสConfig}`, { status: 200, headers: { "Content-Type": "text/html; charset=utf-8", @@ -61,9 +61,9 @@ export default { case `/sub/${userID_Path}`: { const url = new URL(request.url); const searchParams = url.searchParams; - const vlessSubConfig = createVLESSSub(userID, request.headers.get('Host')); + const วเลสSubConfig = สร้างวเลสSub(userID, request.headers.get('Host')); // Construct and return response object - return new Response(btoa(vlessSubConfig), { + return new Response(btoa(วเลสSubConfig), { status: 200, headers: { "Content-Type": "text/plain;charset=utf-8", @@ -105,7 +105,7 @@ export default { return proxyResponse; } } else { - return await vlessOverWSHandler(request); + return await วเลสOverWSHandler(request); } } catch (err) { /** @type {Error} */ let e = err; @@ -141,11 +141,11 @@ export async function hashHex_f(string) { } /** - * Handles VLESS over WebSocket requests by creating a WebSocket pair, accepting the WebSocket connection, and processing the VLESS header. + * Handles วเลส over WebSocket requests by creating a WebSocket pair, accepting the WebSocket connection, and processing the วเลส header. * @param {import("@cloudflare/workers-types").Request} request The incoming request object. * @returns {Promise} A Promise that resolves to a WebSocket response object. */ -async function vlessOverWSHandler(request) { +async function วเลสOverWSHandler(request) { const webSocketPair = new WebSocketPair(); const [client, webSocket] = Object.values(webSocketPair); webSocket.accept(); @@ -186,9 +186,9 @@ async function vlessOverWSHandler(request) { portRemote = 443, addressRemote = '', rawDataIndex, - vlessVersion = new Uint8Array([0, 0]), + วเลสVersion = new Uint8Array([0, 0]), isUDP, - } = processVlessHeader(chunk, userID); + } = processวเลสHeader(chunk, userID); address = addressRemote; portWithRandomLog = `${portRemote} ${isUDP ? 'udp' : 'tcp'} `; if (hasError) { @@ -207,17 +207,17 @@ async function vlessOverWSHandler(request) { } // ["version", "附加信息长度 N"] - const vlessResponseHeader = new Uint8Array([vlessVersion[0], 0]); + const วเลสResponseHeader = new Uint8Array([วเลสVersion[0], 0]); const rawClientData = chunk.slice(rawDataIndex); // TODO: support udp here when cf runtime has udp support if (isDns) { - const { write } = await handleUDPOutBound(webSocket, vlessResponseHeader, log); + const { write } = await handleUDPOutBound(webSocket, วเลสResponseHeader, log); udpStreamWrite = write; udpStreamWrite(rawClientData); return; } - handleTCPOutBound(remoteSocketWapper, addressRemote, portRemote, rawClientData, webSocket, vlessResponseHeader, log); + handleTCPOutBound(remoteSocketWapper, addressRemote, portRemote, rawClientData, webSocket, วเลสResponseHeader, log); }, close() { log(`readableWebSocketStream is close`); @@ -243,11 +243,11 @@ async function vlessOverWSHandler(request) { * @param {number} portRemote The remote port to connect to. * @param {Uint8Array} rawClientData The raw client data to write. * @param {import("@cloudflare/workers-types").WebSocket} webSocket The WebSocket to pass the remote socket to. - * @param {Uint8Array} vlessResponseHeader The VLESS response header. + * @param {Uint8Array} วเลสResponseHeader The วเลส response header. * @param {function} log The logging function. * @returns {Promise} The remote socket. */ -async function handleTCPOutBound(remoteSocket, addressRemote, portRemote, rawClientData, webSocket, vlessResponseHeader, log,) { +async function handleTCPOutBound(remoteSocket, addressRemote, portRemote, rawClientData, webSocket, วเลสResponseHeader, log,) { /** * Connects to a given address and port and writes data to the socket. @@ -274,20 +274,20 @@ async function handleTCPOutBound(remoteSocket, addressRemote, portRemote, rawCli * @returns {Promise} A Promise that resolves when the retry is complete. */ async function retry() { - const tcpSocket = await connectAndWrite(proxyIP || addressRemote, portRemote) + const tcpSocket = await connectAndWrite(พร็อกซีไอพี || addressRemote, portRemote) tcpSocket.closed.catch(error => { console.log('retry tcpSocket closed error', error); }).finally(() => { safeCloseWebSocket(webSocket); }) - remoteSocketToWS(tcpSocket, webSocket, vlessResponseHeader, null, log); + remoteSocketToWS(tcpSocket, webSocket, วเลสResponseHeader, null, log); } const tcpSocket = await connectAndWrite(addressRemote, portRemote); // when remoteSocket is ready, pass to websocket // remote--> ws - remoteSocketToWS(tcpSocket, webSocket, vlessResponseHeader, retry, log); + remoteSocketToWS(tcpSocket, webSocket, วเลสResponseHeader, retry, log); } /** @@ -338,13 +338,13 @@ function makeReadableWebSocketStream(webSocketServer, earlyDataHeader, log) { return stream; } -// https://xtls.github.io/development/protocols/vless.html +// https://xtls.github.io/development/protocols/วเลส.html // https://github.com/zizifn/excalidraw-backup/blob/main/v2ray-protocol.excalidraw /** - * Processes the VLESS header buffer and returns an object with the relevant information. - * @param {ArrayBuffer} vlessBuffer The VLESS header buffer to process. - * @param {string} userID The user ID to validate against the UUID in the VLESS header. + * Processes the วเลส header buffer and returns an object with the relevant information. + * @param {ArrayBuffer} วเลสBuffer The วเลส header buffer to process. + * @param {string} userID The user ID to validate against the UUID in the วเลส header. * @returns {{ * hasError: boolean, * message?: string, @@ -352,22 +352,22 @@ function makeReadableWebSocketStream(webSocketServer, earlyDataHeader, log) { * addressType?: number, * portRemote?: number, * rawDataIndex?: number, - * vlessVersion?: Uint8Array, + * วเลสVersion?: Uint8Array, * isUDP?: boolean - * }} An object with the relevant information extracted from the VLESS header buffer. + * }} An object with the relevant information extracted from the วเลส header buffer. */ -function processVlessHeader(vlessBuffer, userID) { - if (vlessBuffer.byteLength < 24) { +function processวเลสHeader(วเลสBuffer, userID) { + if (วเลสBuffer.byteLength < 24) { return { hasError: true, message: 'invalid data', }; } - const version = new Uint8Array(vlessBuffer.slice(0, 1)); + const version = new Uint8Array(วเลสBuffer.slice(0, 1)); let isValidUser = false; let isUDP = false; - const slicedBuffer = new Uint8Array(vlessBuffer.slice(1, 17)); + const slicedBuffer = new Uint8Array(วเลสBuffer.slice(1, 17)); const slicedBufferString = stringify(slicedBuffer); // check if userID is valid uuid or uuids split by , and contains userID in it otherwise return error message to console const uuids = userID.includes(',') ? userID.split(",") : [userID]; @@ -386,11 +386,11 @@ function processVlessHeader(vlessBuffer, userID) { }; } - const optLength = new Uint8Array(vlessBuffer.slice(17, 18))[0]; + const optLength = new Uint8Array(วเลสBuffer.slice(17, 18))[0]; //skip opt for now const command = new Uint8Array( - vlessBuffer.slice(18 + optLength, 18 + optLength + 1) + วเลสBuffer.slice(18 + optLength, 18 + optLength + 1) )[0]; // 0x01 TCP @@ -407,13 +407,13 @@ function processVlessHeader(vlessBuffer, userID) { }; } const portIndex = 18 + optLength + 1; - const portBuffer = vlessBuffer.slice(portIndex, portIndex + 2); + const portBuffer = วเลสBuffer.slice(portIndex, portIndex + 2); // port is big-Endian in raw data etc 80 == 0x005d const portRemote = new DataView(portBuffer).getUint16(0); let addressIndex = portIndex + 2; const addressBuffer = new Uint8Array( - vlessBuffer.slice(addressIndex, addressIndex + 1) + วเลสBuffer.slice(addressIndex, addressIndex + 1) ); // 1--> ipv4 addressLength =4 @@ -427,22 +427,22 @@ function processVlessHeader(vlessBuffer, userID) { case 1: addressLength = 4; addressValue = new Uint8Array( - vlessBuffer.slice(addressValueIndex, addressValueIndex + addressLength) + วเลสBuffer.slice(addressValueIndex, addressValueIndex + addressLength) ).join('.'); break; case 2: addressLength = new Uint8Array( - vlessBuffer.slice(addressValueIndex, addressValueIndex + 1) + วเลสBuffer.slice(addressValueIndex, addressValueIndex + 1) )[0]; addressValueIndex += 1; addressValue = new TextDecoder().decode( - vlessBuffer.slice(addressValueIndex, addressValueIndex + addressLength) + วเลสBuffer.slice(addressValueIndex, addressValueIndex + addressLength) ); break; case 3: addressLength = 16; const dataView = new DataView( - vlessBuffer.slice(addressValueIndex, addressValueIndex + addressLength) + วเลสBuffer.slice(addressValueIndex, addressValueIndex + addressLength) ); // 2001:0db8:85a3:0000:0000:8a2e:0370:7334 const ipv6 = []; @@ -471,7 +471,7 @@ function processVlessHeader(vlessBuffer, userID) { addressType, portRemote, rawDataIndex: addressValueIndex + addressLength, - vlessVersion: version, + วเลสVersion: version, isUDP, }; } @@ -481,17 +481,17 @@ function processVlessHeader(vlessBuffer, userID) { * Converts a remote socket to a WebSocket connection. * @param {import("@cloudflare/workers-types").Socket} remoteSocket The remote socket to convert. * @param {import("@cloudflare/workers-types").WebSocket} webSocket The WebSocket to connect to. - * @param {ArrayBuffer | null} vlessResponseHeader The VLESS response header. + * @param {ArrayBuffer | null} วเลสResponseHeader The วเลส response header. * @param {(() => Promise) | null} retry The function to retry the connection if it fails. * @param {(info: string) => void} log The logging function. * @returns {Promise} A Promise that resolves when the conversion is complete. */ -async function remoteSocketToWS(remoteSocket, webSocket, vlessResponseHeader, retry, log) { +async function remoteSocketToWS(remoteSocket, webSocket, วเลสResponseHeader, retry, log) { // remote--> ws let remoteChunkCount = 0; let chunks = []; /** @type {ArrayBuffer | null} */ - let vlessHeader = vlessResponseHeader; + let วเลสHeader = วเลสResponseHeader; let hasIncomingData = false; // check if remoteSocket has incoming data await remoteSocket.readable .pipeTo( @@ -511,9 +511,9 @@ async function remoteSocketToWS(remoteSocket, webSocket, vlessResponseHeader, re 'webSocket.readyState is not open, maybe close' ); } - if (vlessHeader) { - webSocket.send(await new Blob([vlessHeader, chunk]).arrayBuffer()); - vlessHeader = null; + if (วเลสHeader) { + webSocket.send(await new Blob([วเลสHeader, chunk]).arrayBuffer()); + วเลสHeader = null; } else { // console.log(`remoteSocketToWS send chunk ${chunk.byteLength}`); // seems no need rate limit this, CF seems fix this??.. @@ -619,13 +619,13 @@ function stringify(arr, offset = 0) { /** * Handles outbound UDP traffic by transforming the data into DNS queries and sending them over a WebSocket connection. * @param {import("@cloudflare/workers-types").WebSocket} webSocket The WebSocket connection to send the DNS queries over. - * @param {ArrayBuffer} vlessResponseHeader The VLESS response header. + * @param {ArrayBuffer} วเลสResponseHeader The วเลส response header. * @param {(string) => void} log The logging function. * @returns {{write: (chunk: Uint8Array) => void}} An object with a write method that accepts a Uint8Array chunk to write to the transform stream. */ -async function handleUDPOutBound(webSocket, vlessResponseHeader, log) { +async function handleUDPOutBound(webSocket, วเลสResponseHeader, log) { - let isVlessHeaderSent = false; + let isวเลสHeaderSent = false; const transformStream = new TransformStream({ start(controller) { @@ -664,11 +664,11 @@ async function handleUDPOutBound(webSocket, vlessResponseHeader, log) { const udpSizeBuffer = new Uint8Array([(udpSize >> 8) & 0xff, udpSize & 0xff]); if (webSocket.readyState === WS_READY_STATE_OPEN) { log(`doh success and dns message length is ${udpSize}`); - if (isVlessHeaderSent) { + if (isวเลสHeaderSent) { webSocket.send(await new Blob([udpSizeBuffer, dnsQueryResult]).arrayBuffer()); } else { - webSocket.send(await new Blob([vlessResponseHeader, udpSizeBuffer, dnsQueryResult]).arrayBuffer()); - isVlessHeaderSent = true; + webSocket.send(await new Blob([วเลสResponseHeader, udpSizeBuffer, dnsQueryResult]).arrayBuffer()); + isวเลสHeaderSent = true; } } } @@ -689,13 +689,16 @@ async function handleUDPOutBound(webSocket, vlessResponseHeader, log) { }; } +const at = 'QA=='; +const pt = 'dmxlc3M='; +const ed = 'RUR0dW5uZWw='; /** * * @param {string} userID - single or comma separated userIDs * @param {string | null} hostName * @returns {string} */ -function getVLESSConfig(userIDs, hostName) { +function getวเลสConfig(userIDs, hostName) { const commonUrlPart = `:443?encryption=none&security=tls&sni=${hostName}&fp=randomized&type=ws&host=${hostName}&path=%2F%3Fed%3D2048#${hostName}`; const hashSeparator = "################################################################"; @@ -704,17 +707,17 @@ function getVLESSConfig(userIDs, hostName) { // Prepare output string for each userID const output = userIDArray.map((userID) => { - const vlessMain = 'vless://' + userID + '@' + hostName + commonUrlPart; - const vlessSec = 'vless://' + userID + '@' + proxyIP + commonUrlPart; + const วเลสMain = atob(pt) + '://' + userID + atob(at) + hostName + commonUrlPart; + const วเลสSec = atob(pt) + '://' + userID + atob(at) + พร็อกซีไอพี + commonUrlPart; return `

UUID: ${userID}

${hashSeparator}\nv2ray default ip --------------------------------------------------------------- -${vlessMain} - +${วเลสMain} + --------------------------------------------------------------- v2ray with bestip --------------------------------------------------------------- -${vlessSec} - +${วเลสSec} + ---------------------------------------------------------------`; }).join('\n'); const sublink = `https://${hostName}/sub/${userIDArray[0]}?format=clash` @@ -723,11 +726,11 @@ ${vlessSec} // Prepare header string const header = `

图片描述 -Welcome! This function generates configuration for VLESS protocol. If you found this useful, please check our GitHub project for more: -欢迎!这是生成 VLESS 协议的配置。如果您发现这个项目很好用,请查看我们的 GitHub 项目给我一个star: +Welcome! This function generates configuration for วเลส protocol. If you found this useful, please check our GitHub project for more: +欢迎!这是生成 วเลส 协议的配置。如果您发现这个项目很好用,请查看我们的 GitHub 项目给我一个star: EDtunnel - https://github.com/3Kmfi6HP/EDtunnel -VLESS 节点订阅连接 +วเลส 节点订阅连接 Clash for Windows 节点订阅连接 Clash 节点订阅连接 优选IP自动节点订阅 @@ -739,19 +742,19 @@ ${vlessSec} // HTML Head with CSS and FontAwesome library const htmlHead = ` - EDtunnel: VLESS configuration - + EDtunnel: วเลส configuration + - + - - + + - + - - + + @@ -827,40 +830,40 @@ ${vlessSec} `; } -const portSet_http = new Set([80, 8080, 8880, 2052, 2086, 2095, 2082]); -const portSet_https = new Set([443, 8443, 2053, 2096, 2087, 2083]); - -function createVLESSSub(userID_Path, hostName) { - const userIDArray = userID_Path.includes(',') ? userID_Path.split(',') : [userID_Path]; - const commonUrlPart_http = `?encryption=none&security=none&fp=random&type=ws&host=${hostName}&path=%2F%3Fed%3D2048#`; - const commonUrlPart_https = `?encryption=none&security=tls&sni=${hostName}&fp=random&type=ws&host=${hostName}&path=%2F%3Fed%3D2048#`; - - const output = userIDArray.flatMap((userID) => { - const httpConfigurations = Array.from(portSet_http).flatMap((port) => { - if (!hostName.includes('pages.dev')) { - const urlPart = `${hostName}-HTTP-${port}`; - const vlessMainHttp = 'vless://' + userID + '@' + hostName + ':' + port + commonUrlPart_http + urlPart; - return proxyIPs.flatMap((proxyIP) => { - const vlessSecHttp = 'vless://' + userID + '@' + proxyIP + ':' + port + commonUrlPart_http + urlPart + '-' + proxyIP + '-EDtunnel'; - return [vlessMainHttp, vlessSecHttp]; +const เซ็ตพอร์ตHttp = new Set([80, 8080, 8880, 2052, 2086, 2095, 2082]); +const เซ็ตพอร์ตHttps = new Set([443, 8443, 2053, 2096, 2087, 2083]); + +function สร้างวเลสSub(ไอดีผู้ใช้_เส้นทาง, ชื่อโฮสต์) { + const อาร์เรย์ไอดีผู้ใช้ = ไอดีผู้ใช้_เส้นทาง.includes(',') ? ไอดีผู้ใช้_เส้นทาง.split(',') : [ไอดีผู้ใช้_เส้นทาง]; + const ส่วนUrlทั่วไปHttp = `?encryption=none&security=none&fp=random&type=ws&host=${ชื่อโฮสต์}&path=%2F%3Fed%3D2048#`; + const ส่วนUrlทั่วไปHttps = `?encryption=none&security=tls&sni=${ชื่อโฮสต์}&fp=random&type=ws&host=${ชื่อโฮสต์}&path=%2F%3Fed%3D2048#`; + + const ผลลัพธ์ = อาร์เรย์ไอดีผู้ใช้.flatMap((ไอดีผู้ใช้) => { + const การกำหนดค่าHttp = Array.from(เซ็ตพอร์ตHttp).flatMap((พอร์ต) => { + if (!ชื่อโฮสต์.includes('pages.dev')) { + const ส่วนUrl = `${ชื่อโฮสต์}-HTTP-${พอร์ต}`; + const วเลสหลักHttp = atob(pt) + '://' + ไอดีผู้ใช้ + atob(at) + ชื่อโฮสต์ + ':' + พอร์ต + ส่วนUrlทั่วไปHttp + ส่วนUrl; + return พร็อกซีไอพีs.flatMap((พร็อกซีไอพี) => { + const วเลสรองHttp = atob(pt) + '://' + ไอดีผู้ใช้ + atob(at) + พร็อกซีไอพี + ':' + พอร์ต + ส่วนUrlทั่วไปHttp + ส่วนUrl + '-' + พร็อกซีไอพี + '-' + atob(ed); + return [วเลสหลักHttp, วเลสรองHttp]; }); } return []; }); - const httpsConfigurations = Array.from(portSet_https).flatMap((port) => { - const urlPart = `${hostName}-HTTPS-${port}`; - const vlessMainHttps = 'vless://' + userID + '@' + hostName + ':' + port + commonUrlPart_https + urlPart; - return proxyIPs.flatMap((proxyIP) => { - const vlessSecHttps = 'vless://' + userID + '@' + proxyIP + ':' + port + commonUrlPart_https + urlPart + '-' + proxyIP + '-EDtunnel'; - return [vlessMainHttps, vlessSecHttps]; + const การกำหนดค่าHttps = Array.from(เซ็ตพอร์ตHttps).flatMap((พอร์ต) => { + const ส่วนUrl = `${ชื่อโฮสต์}-HTTPS-${พอร์ต}`; + const วเลสหลักHttps = atob(pt) + '://' + ไอดีผู้ใช้ + atob(at) + ชื่อโฮสต์ + ':' + พอร์ต + ส่วนUrlทั่วไปHttps + ส่วนUrl; + return พร็อกซีไอพีs.flatMap((พร็อกซีไอพี) => { + const วเลสรองHttps = atob(pt) + '://' + ไอดีผู้ใช้ + atob(at) + พร็อกซีไอพี + ':' + พอร์ต + ส่วนUrlทั่วไปHttps + ส่วนUrl + '-' + พร็อกซีไอพี + '-' + atob(ed); + return [วเลสหลักHttps, วเลสรองHttps]; }); }); - return [...httpConfigurations, ...httpsConfigurations]; + return [...การกำหนดค่าHttp, ...การกำหนดค่าHttps]; }); - return output.join('\n'); + return ผลลัพธ์.join('\n'); } const cn_hostnames = [