From 696792f3f76f27aab0e988a665b5f737452ece62 Mon Sep 17 00:00:00 2001 From: 3Kmfi6HP Date: Mon, 21 Oct 2024 22:07:24 +0700 Subject: [PATCH] add DrivePage --- index.js | 595 +++++++++++++++++--------------------------------- wrangler.toml | 12 +- 2 files changed, 200 insertions(+), 407 deletions(-) diff --git a/index.js b/index.js index 3845527..c15b72a 100644 --- a/index.js +++ b/index.js @@ -107,31 +107,203 @@ export default { }; async function handleDefaultPath(url, request) { - const randomHostname = hostnames[Math.floor(Math.random() * hostnames.length)]; - const newHeaders = new Headers(request.headers); - newHeaders.set('cf-connecting-ip', '1.2.3.4'); - newHeaders.set('x-forwarded-for', '1.2.3.4'); - newHeaders.set('x-real-ip', '1.2.3.4'); - newHeaders.set('referer', 'https://www.google.com/search?q=edtunnel'); - - const proxyUrl = 'https://' + randomHostname + url.pathname + url.search; - const modifiedRequest = new Request(proxyUrl, { - method: request.method, - headers: newHeaders, - body: request.body, - redirect: 'manual', + const host = request.headers.get('Host'); + const DrivePage = ` + + + + + + ${host} - Cloud Drive + + + +
+

Cloud Drive

+

Welcome to your personal cloud storage. Here are your uploaded files:

+ +
+
πŸ“
+

Upload a File

+

Drag and drop a file here or click to select

+ +
+
+
+ + + + `; + + // θΏ”ε›žδΌͺθ£…ηš„η½‘η›˜ι‘΅ι’ + return new Response(DrivePage, { + headers: { + "content-type": "text/html;charset=UTF-8", + }, }); - - const proxyResponse = await fetch(modifiedRequest, { redirect: 'manual' }); - if ([301, 302].includes(proxyResponse.status)) { - return new Response(`Redirects to ${randomHostname} are not allowed.`, { - status: 403, - statusText: 'Forbidden', - }); - } - return proxyResponse; } - /** * Handles protocol over WebSocket requests by creating a WebSocket pair, accepting the WebSocket connection, and processing the protocol header. * @param {import("@cloudflare/workers-types").Request} request The incoming request object. @@ -226,63 +398,6 @@ async function ProtocolOverWSHandler(request) { }); } -async function trojanOverWSHandler(request) { - const webSocketPair = new WebSocketPair(); - const [client, webSocket] = Object.values(webSocketPair); - webSocket.accept(); - let address = ""; - let portWithRandomLog = ""; - const log = (info, event) => { - console.log(`[${address}:${portWithRandomLog}] ${info}`, event || ""); - }; - const earlyDataHeader = request.headers.get("sec-websocket-protocol") || ""; - const readableWebSocketStream = makeReadableWebSocketStream(webSocket, earlyDataHeader, log); - let remoteSocketWapper = { - value: null - }; - let udpStreamWrite = null; - readableWebSocketStream.pipeTo(new WritableStream({ - async write(chunk, controller) { - if (udpStreamWrite) { - return udpStreamWrite(chunk); - } - if (remoteSocketWapper.value) { - const writer = remoteSocketWapper.value.writable.getWriter(); - await writer.write(chunk); - writer.releaseLock(); - return; - } - const { - hasError, - message, - portRemote = 443, - addressRemote = "", - rawClientData, - addressType - } = await parseTrojanHeader(chunk); - address = addressRemote; - portWithRandomLog = `${portRemote}--${Math.random()} tcp`; - if (hasError) { - throw new Error(message); - } - handleTCPOutBound(remoteSocketWapper, addressRemote, portRemote, rawClientData, webSocket, log, addressType); - }, - close() { - log(`readableWebSocketStream is closed`); - }, - abort(reason) { - log(`readableWebSocketStream is aborted`, JSON.stringify(reason)); - } - })).catch((err) => { - log("readableWebSocketStream pipeTo error", err); - }); - return new Response(null, { - status: 101, - // @ts-ignore - webSocket: client - }); -} - /** * Handles outbound TCP connections. * @@ -608,80 +723,6 @@ function stringify(arr, offset = 0) { return uuid; } - -/** - * 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} protocolResponseHeader The protocol 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, protocolResponseHeader, log) { - - let isprotocolHeaderSent = false; - const transformStream = new TransformStream({ - start(_controller) { - - }, - transform(chunk, controller) { - // udp message 2 byte is the the length of udp data - // TODO: this should have bug, beacsue maybe udp chunk can be in two websocket message - for (let index = 0; index < chunk.byteLength;) { - const lengthBuffer = chunk.slice(index, index + 2); - const udpPakcetLength = new DataView(lengthBuffer).getUint16(0); - const udpData = new Uint8Array( - chunk.slice(index + 2, index + 2 + udpPakcetLength) - ); - index = index + 2 + udpPakcetLength; - controller.enqueue(udpData); - } - }, - flush(_controller) { - } - }); - - // only handle dns udp for now - transformStream.readable.pipeTo(new WritableStream({ - async write(chunk) { - const resp = await fetch(dohURL, // dns server url - { - method: 'POST', - headers: { - 'content-type': 'application/dns-message', - }, - body: chunk, - }) - const dnsQueryResult = await resp.arrayBuffer(); - const udpSize = dnsQueryResult.byteLength; - // console.log([...new Uint8Array(dnsQueryResult)].map((x) => x.toString(16))); - 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 (isprotocolHeaderSent) { - webSocket.send(await new Blob([udpSizeBuffer, dnsQueryResult]).arrayBuffer()); - } else { - webSocket.send(await new Blob([protocolResponseHeader, udpSizeBuffer, dnsQueryResult]).arrayBuffer()); - isprotocolHeaderSent = true; - } - } - } - })).catch((error) => { - log('dns udp has error' + error) - }); - - const writer = transformStream.writable.getWriter(); - - return { - /** - * - * @param {Uint8Array} chunk - */ - write(chunk) { - writer.write(chunk); - } - }; -} - /** * * @param {ArrayBuffer} udpChunk @@ -964,175 +1005,6 @@ async function parseTrojanHeader(buffer) { }; } - -const VlessCmd = { - TCP: 1, - UDP: 2, - MUX: 3, -}; - -const VlessAddrType = { - IPv4: 1, // 4-bytes - DomainName: 2, // The first byte indicates the length of the following domain name - IPv6: 3, // 16-bytes -}; - -/** - * Generate a vless request header. - * @param {number} command - The command to execute (see VlessCmd). - * @param {number} destType - The type of destination address (see VlessAddrType). - * @param {string} destAddr - The destination address. - * @param {number} destPort - The destination port. - * @param {string} uuid - The UUID of the request. - * @returns {Uint8Array} - The vless request header as a Uint8Array. - * @throws {Error} - If the address type is unknown. - */ -function makeVlessReqHeader(command, destType, destAddr, destPort, uuid) { - /** @type {number} */ - let addressFieldLength; - /** @type {Uint8Array | undefined} */ - let addressEncoded; - switch (destType) { - case VlessAddrType.IPv4: - addressFieldLength = 4; - break; - case VlessAddrType.DomainName: - addressEncoded = new TextEncoder().encode(destAddr); - addressFieldLength = addressEncoded.length + 1; - break; - case VlessAddrType.IPv6: - addressFieldLength = 16; - break; - default: - throw new Error(`Unknown address type: ${destType}`); - } - - const uuidString = uuid.replace(/-/g, ''); - const uuidOffset = 1; - const vlessHeader = new Uint8Array(22 + addressFieldLength); - - // Protocol Version = 0 - vlessHeader[0] = 0x00; - - for (let i = 0; i < uuidString.length; i += 2) { - vlessHeader[uuidOffset + i / 2] = parseInt(uuidString.substr(i, 2), 16); - } - - // Additional Information Length M = 0 - vlessHeader[17] = 0x00; - - // Instruction - vlessHeader[18] = command; - - // Port, 2-byte big-endian - vlessHeader[19] = destPort >> 8; - vlessHeader[20] = destPort & 0xFF; - - // Address Type - // 1--> ipv4 addressLength =4 - // 2--> domain name addressLength=addressBuffer[1] - // 3--> ipv6 addressLength =16 - vlessHeader[21] = destType; - - // Address - switch (destType) { - case VlessAddrType.IPv4: - const octetsIPv4 = destAddr.split('.'); - for (let i = 0; i < 4; i++) { - vlessHeader[22 + i] = parseInt(octetsIPv4[i]); - } - break; - case VlessAddrType.DomainName: - vlessHeader[22] = addressEncoded.length; - vlessHeader.set(addressEncoded, 23); - break; - case VlessAddrType.IPv6: - const groupsIPv6 = ipv6.split(':'); - for (let i = 0; i < 8; i++) { - const hexGroup = parseInt(groupsIPv6[i], 16); - vlessHeader[i * 2 + 22] = hexGroup >> 8; - vlessHeader[i * 2 + 23] = hexGroup & 0xFF; - } - break; - default: - throw new Error(`Unknown address type: ${destType}`); - } - - return vlessHeader; -} - -/** - * Checks if the provided VLESS configuration is valid for the given address and stream settings. - * @param {string} address - The address to check against. - * @param {Object} streamSettings - The stream settings to check. - * @throws {Error} If the outbound stream method is not 'ws'. - * @throws {Error} If the security layer is not 'none' or 'tls'. - * @throws {Error} If the Host field in the http header is different from the server address. - * @throws {Error} If the SNI is different from the server address. - */ -function checkVlessConfig(address, streamSettings) { - if (streamSettings.network !== 'ws') { - throw new Error(`Unsupported outbound stream method: ${streamSettings.network}, has to be ws (Websocket)`); - } - - if (streamSettings.security !== 'tls' && streamSettings.security !== 'none') { - throw new Error(`Usupported security layer: ${streamSettings.network}, has to be none or tls.`); - } - - if (streamSettings.wsSettings && streamSettings.wsSettings.headers && streamSettings.wsSettings.headers.Host !== address) { - throw new Error(`The Host field in the http header is different from the server address, this is unsupported due to Cloudflare API restrictions`); - } - - if (streamSettings.tlsSettings && streamSettings.tlsSettings.serverName !== address) { - throw new Error(`The SNI is different from the server address, this is unsupported due to Cloudflare API restrictions`); - } -} - - -/** - * Parses a VLESS URL string into its components. - * @param {string} url The VLESS URL string in the format "vless://uuid@remoteHost:remotePort?queryParams#descriptiveText". - * @returns {{ -* protocol: string, -* uuid: string, -* remoteHost: string, -* remotePort: number, -* descriptiveText: string, -* queryParams: Object -* }} An object containing the parsed components of the VLESS URL string. -* @throws {Error} If the URL string is in an invalid format. -*/ -function parseVlessString(url) { - const regex = /^(.+):\/\/(.+?)@(.+?):(\d+)(\?[^#]*)?(#.*)?$/; - const match = url.match(regex); - - if (!match) { - throw new Error('Invalid URL format'); - } - - const [, protocol, uuid, remoteHost, remotePort, query, descriptiveText] = match; - - const json = { - protocol, - uuid, - remoteHost, - remotePort: parseInt(remotePort), - descriptiveText: descriptiveText ? descriptiveText.substring(1) : '', - queryParams: {} - }; - - if (query) { - const queryFields = query.substring(1).split('&'); - queryFields.forEach(field => { - const [key, value] = field.split('='); - json.queryParams[key] = value; - }); - } - - return json; -} - - const at = 'QA=='; const pt = 'dmxlc3M='; const ed = 'RUR0dW5uZWw='; @@ -1394,80 +1266,3 @@ function GenSub(userID_path, hostname) { return result.join('\n'); } - -const hostnames = [ - 'weibo.com', // Weibo - A popular social media platform - 'www.baidu.com', // Baidu - The largest search engine in China - 'www.qq.com', // QQ - A widely used instant messaging platform - 'www.taobao.com', // Taobao - An e-commerce website owned by Alibaba Group - 'www.jd.com', // JD.com - One of the largest online retailers in China - 'www.sina.com.cn', // Sina - A Chinese online media company - 'www.sohu.com', // Sohu - A Chinese internet service provider - 'www.tmall.com', // Tmall - An online retail platform owned by Alibaba Group - 'www.163.com', // NetEase Mail - One of the major email providers in China - 'www.zhihu.com', // Zhihu - A popular question-and-answer website - 'www.youku.com', // Youku - A Chinese video sharing platform - 'www.xinhuanet.com', // Xinhua News Agency - Official news agency of China - 'www.douban.com', // Douban - A Chinese social networking service - 'www.meituan.com', // Meituan - A Chinese group buying website for local services - 'www.toutiao.com', // Toutiao - A news and information content platform - 'www.ifeng.com', // iFeng - A popular news website in China - 'www.autohome.com.cn', // Autohome - A leading Chinese automobile online platform - 'www.360.cn', // 360 - A Chinese internet security company - 'www.douyin.com', // Douyin - A Chinese short video platform - 'www.kuaidi100.com', // Kuaidi100 - A Chinese express delivery tracking service - 'www.wechat.com', // WeChat - A popular messaging and social media app - 'www.csdn.net', // CSDN - A Chinese technology community website - 'www.imgo.tv', // ImgoTV - A Chinese live streaming platform - 'www.aliyun.com', // Alibaba Cloud - A Chinese cloud computing company - 'www.eyny.com', // Eyny - A Chinese multimedia resource-sharing website - 'www.mgtv.com', // MGTV - A Chinese online video platform - 'www.xunlei.com', // Xunlei - A Chinese download manager and torrent client - 'www.hao123.com', // Hao123 - A Chinese web directory service - 'www.bilibili.com', // Bilibili - A Chinese video sharing and streaming platform - 'www.youth.cn', // Youth.cn - A China Youth Daily news portal - 'www.hupu.com', // Hupu - A Chinese sports community and forum - 'www.youzu.com', // Youzu Interactive - A Chinese game developer and publisher - 'www.panda.tv', // Panda TV - A Chinese live streaming platform - 'www.tudou.com', // Tudou - A Chinese video-sharing website - 'www.zol.com.cn', // ZOL - A Chinese electronics and gadgets website - 'www.toutiao.io', // Toutiao - A news and information app - 'www.tiktok.com', // TikTok - A Chinese short-form video app - 'www.netease.com', // NetEase - A Chinese internet technology company - 'www.cnki.net', // CNKI - China National Knowledge Infrastructure, an information aggregator - 'www.zhibo8.cc', // Zhibo8 - A website providing live sports streams - 'www.zhangzishi.cc', // Zhangzishi - Personal website of Zhang Zishi, a public intellectual in China - 'www.xueqiu.com', // Xueqiu - A Chinese online social platform for investors and traders - 'www.qqgongyi.com', // QQ Gongyi - Tencent's charitable foundation platform - 'www.ximalaya.com', // Ximalaya - A Chinese online audio platform - 'www.dianping.com', // Dianping - A Chinese online platform for finding and reviewing local businesses - 'www.suning.com', // Suning - A leading Chinese online retailer - 'www.zhaopin.com', // Zhaopin - A Chinese job recruitment platform - 'www.jianshu.com', // Jianshu - A Chinese online writing platform - 'www.mafengwo.cn', // Mafengwo - A Chinese travel information sharing platform - 'www.51cto.com', // 51CTO - A Chinese IT technical community website - 'www.qidian.com', // Qidian - A Chinese web novel platform - 'www.ctrip.com', // Ctrip - A Chinese travel services provider - 'www.pconline.com.cn', // PConline - A Chinese technology news and review website - 'www.cnzz.com', // CNZZ - A Chinese web analytics service provider - 'www.telegraph.co.uk', // The Telegraph - A British newspaper website - 'www.ynet.com', // Ynet - A Chinese news portal - 'www.ted.com', // TED - A platform for ideas worth spreading - 'www.renren.com', // Renren - A Chinese social networking service - 'www.pptv.com', // PPTV - A Chinese online video streaming platform - 'www.liepin.com', // Liepin - A Chinese online recruitment website - 'www.881903.com', // 881903 - A Hong Kong radio station website - 'www.aipai.com', // Aipai - A Chinese online video sharing platform - 'www.ttpaihang.com', // Ttpaihang - A Chinese celebrity popularity ranking website - 'www.quyaoya.com', // Quyaoya - A Chinese online ticketing platform - 'www.91.com', // 91.com - A Chinese software download website - 'www.dianyou.cn', // Dianyou - A Chinese game information website - 'www.tmtpost.com', // TMTPost - A Chinese technology media platform - 'www.douban.com', // Douban - A Chinese social networking service - 'www.guancha.cn', // Guancha - A Chinese news and commentary website - 'www.so.com', // So.com - A Chinese search engine - 'www.58.com', // 58.com - A Chinese classified advertising website - 'www.cnblogs.com', // Cnblogs - A Chinese technology blog community - 'www.cntv.cn', // CCTV - China Central Television official website - 'www.secoo.com', // Secoo - A Chinese luxury e-commerce platform -]; diff --git a/wrangler.toml b/wrangler.toml index 51c3b31..05ac53c 100644 --- a/wrangler.toml +++ b/wrangler.toml @@ -1,13 +1,11 @@ -name = "cf-worker-ws-dev" # todo -#name = "cf-worker-connect-test" # todo -#main = "test/worker/cf-cdn-cgi-trace2.js" -#main = "test/worker/worker-connect-test.js" +name = "cf-worker-ws-dev" main = "_worker.js" compatibility_date = "2023-05-26" -node_compat = true +# node_compat = true workers_dev = true [vars] -# UUID = "d342d11e-d424-4583-b36e-524ab1f0afa4" -PROXYIP = "211.230.110.231:50008" +# PROXYIP = "211.230.110.231:50008" UUID = "1b6c1745-992e-4aac-8685-266c090e50ea" +# SOCKS5 = "127.0.0.1:1080" +# SOCKS5_RELAY = "true"