差别

这里会显示出您选择的修订版和当前版本之间的差别。

到此差别页面的链接

两侧同时换到之前的修订记录前一修订版
后一修订版
前一修订版
工具:编辑:herokuv2ray [2023-07-22 07:23] – [CloudFlare 免费翻墙工具] goldentianya工具:编辑:herokuv2ray [2025-12-30 11:23] (当前版本) – [七合一一键脚本] goldentianya
行 66: 行 66:
 ====== X-UI 搭建 ====== ====== X-UI 搭建 ======
 [[https://luori.xyz/index.php/45/|教程一]] [[https://5best1s.com/%E5%8F%AF%E8%A7%86%E5%8C%96%E7%AE%A1%E7%90%86%E9%9D%A2%E6%9D%BFx-ui/|教程二]] {{fa>angellist}} [[https://luori.xyz/index.php/45/|教程一]] [[https://5best1s.com/%E5%8F%AF%E8%A7%86%E5%8C%96%E7%AE%A1%E7%90%86%E9%9D%A2%E6%9D%BFx-ui/|教程二]] {{fa>angellist}}
 +
 +[[https://github.com/vaxilu/x-ui|Github 项目地址]] ([[https://seakfind.github.io/2021/10/10/X-UI/|Document]])
  
 x-ui 一键安装 x-ui 一键安装
行 115: 行 117:
  
 [[https://www.v2fly.org/config/overview.html|v2ray 使用文档]] [[https://www.v2fly.org/config/overview.html|v2ray 使用文档]]
 +
 +更新分流文件的命令,需要每年执行一次。
 +  wget https://github.com/v2fly/domain-list-community/releases/latest/download/dlc.dat -O /usr/local/x-ui/bin/geosite.dat
  
 ++++ 路由设置 |  ++++ 路由设置 | 
行 133: 行 138:
 ++++ ++++
  
-====== 七合一一键脚本 ====== 
-<code > 
-wget -P /root -N –no-check-certificate "https://raw.githubusercontent.com/mack-a/v2ray-agent/9ae23c13a56460d8c14f27c8eb65efc73b173f46/install.sh" && chmod 700 /root/install.sh && /root/install.sh 
-</code> 
- 
-  - cloudflare 的小云朵要灰色 
-  - 证书放在 <color #7092be>/etc/v2ray-agent/tls/ali.simperator.top.crt</color>,已有证书的话先保存到这个路径。 
-====== CloudFlare 免费翻墙工具 ====== 
-每秒的IP都变化。采用 simpinvest.eu.org 域名来实现这个机场。 
- 
-1. 进入 CF => Worker and Pages => create Worker 
- 
-2. 打开v2ray 添加vlessf服务器,点击生成一个用户id,并复制到脚本的 userID 中去。选择下面其中一个域名,添加到 proxy 中去 
- 
-五个加速地址 
-<code | download> 
-       cdn.anycast.eu.org 
-edgetunnel.anycast.eu.org 
-cdn-b100.xn--b6gac.eu.org 
-     cdn.xn--b6gac.eu.org 
- cdn-all.xn--b6gac.eu.org 
-</code> 
- 
-3. 保存并部署。然后返回到worker,选择查看,添加一个自定义域名 2207.simpinvest.eu.org (二级域名) 
- 
-4. 打开地址 <color #ff7f27>''%%2207.simpinvest.eu.org/<userID>%%''</color> 就出现了自己的配置文件 
- 
-5. 选择网页上的订阅地址,打开v2ray, 从粘贴板导入 
- 
- 
-++++ worker.js | 
- 
-<code | download> 
-// <!--GAMFC-->version base on commit 43fad05dcdae3b723c53c226f8181fc5bd47223e, time is 2023-06-22 15:20:02 UTC<!--GAMFC-END-->. 
-// @ts-ignore 
-import { connect } from 'cloudflare:sockets'; 
- 
-// How to generate your own UUID: 
-// [Windows] Press "Win + R", input cmd and run:  Powershell -NoExit -Command "[guid]::NewGuid()" 
-let userID = 'd342d11e-d424-4583-b36e-524ab1f0afa4'; 
- 
-let proxyIP = ''; 
- 
- 
-if (!isValidUUID(userID)) { 
- throw new Error('uuid is not valid'); 
-} 
- 
-export default { 
- /** 
- * @param {import("@cloudflare/workers-types").Request} request 
- * @param {{UUID: string, PROXYIP: string}} env 
- * @param {import("@cloudflare/workers-types").ExecutionContext} ctx 
- * @returns {Promise<Response>} 
- */ 
- async fetch(request, env, ctx) { 
- try { 
- userID = env.UUID || userID; 
- proxyIP = env.PROXYIP || proxyIP; 
- const upgradeHeader = request.headers.get('Upgrade'); 
- if (!upgradeHeader || upgradeHeader !== 'websocket') { 
- const url = new URL(request.url); 
- switch (url.pathname) { 
- case '/': 
- return new Response(JSON.stringify(request.cf), { status: 200 }); 
- case `/${userID}`: { 
- const vlessConfig = getVLESSConfig(userID, request.headers.get('Host')); 
- return new Response(`${vlessConfig}`, { 
- status: 200, 
- headers: { 
- "Content-Type": "text/plain;charset=utf-8", 
- } 
- }); 
- } 
- default: 
- return new Response('Not found', { status: 404 }); 
- } 
- } else { 
- return await vlessOverWSHandler(request); 
- } 
- } catch (err) { 
- /** @type {Error} */ let e = err; 
- return new Response(e.toString()); 
- } 
- }, 
-}; 
- 
- 
- 
- 
-/** 
-  
- * @param {import("@cloudflare/workers-types").Request} request 
- */ 
-async function vlessOverWSHandler(request) { 
- 
- /** @type {import("@cloudflare/workers-types").WebSocket[]} */ 
- // @ts-ignore 
- const webSocketPair = new WebSocketPair(); 
- const [client, webSocket] = Object.values(webSocketPair); 
- 
- webSocket.accept(); 
- 
- let address = ''; 
- let portWithRandomLog = ''; 
- const log = (/** @type {string} */ info, /** @type {string | undefined} */ event) => { 
- console.log(`[${address}:${portWithRandomLog}] ${info}`, event || ''); 
- }; 
- const earlyDataHeader = request.headers.get('sec-websocket-protocol') || ''; 
- 
- const readableWebSocketStream = makeReadableWebSocketStream(webSocket, earlyDataHeader, log); 
- 
- /** @type {{ value: import("@cloudflare/workers-types").Socket | null}}*/ 
- let remoteSocketWapper = { 
- value: null, 
- }; 
- let udpStreamWrite = null; 
- let isDns = false; 
- 
- // ws --> remote 
- readableWebSocketStream.pipeTo(new WritableStream({ 
- async write(chunk, controller) { 
- if (isDns && 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 = '', 
- rawDataIndex, 
- vlessVersion = new Uint8Array([0, 0]), 
- isUDP, 
- } = processVlessHeader(chunk, userID); 
- address = addressRemote; 
- portWithRandomLog = `${portRemote}--${Math.random()} ${isUDP ? 'udp ' : 'tcp ' 
- } `; 
- if (hasError) { 
- // controller.error(message); 
- throw new Error(message); // cf seems has bug, controller.error will not end stream 
- // webSocket.close(1000, message); 
- return; 
- } 
- // if UDP but port not DNS port, close it 
- if (isUDP) { 
- if (portRemote === 53) { 
- isDns = true; 
- } else { 
- // controller.error('UDP proxy only enable for DNS which is port 53'); 
- throw new Error('UDP proxy only enable for DNS which is port 53'); // cf seems has bug, controller.error will not end stream 
- return; 
- } 
- } 
- // ["version", "附加信息长度 N"] 
- const vlessResponseHeader = new Uint8Array([vlessVersion[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); 
- udpStreamWrite = write; 
- udpStreamWrite(rawClientData); 
- return; 
- } 
- handleTCPOutBound(remoteSocketWapper, addressRemote, portRemote, rawClientData, webSocket, vlessResponseHeader, log); 
- }, 
- close() { 
- log(`readableWebSocketStream is close`); 
- }, 
- abort(reason) { 
- log(`readableWebSocketStream is abort`, JSON.stringify(reason)); 
- }, 
- })).catch((err) => { 
- log('readableWebSocketStream pipeTo error', err); 
- }); 
- 
- return new Response(null, { 
- status: 101, 
- // @ts-ignore 
- webSocket: client, 
- }); 
-} 
- 
-/** 
- * Handles outbound TCP connections. 
- * 
- * @param {any} remoteSocket  
- * @param {string} addressRemote The remote address to connect to. 
- * @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 {function} log The logging function. 
- * @returns {Promise<void>} The remote socket. 
- */ 
-async function handleTCPOutBound(remoteSocket, addressRemote, portRemote, rawClientData, webSocket, vlessResponseHeader, log,) { 
- async function connectAndWrite(address, port) { 
- /** @type {import("@cloudflare/workers-types").Socket} */ 
- const tcpSocket = connect({ 
- hostname: address, 
- port: port, 
- }); 
- remoteSocket.value = tcpSocket; 
- log(`connected to ${address}:${port}`); 
- const writer = tcpSocket.writable.getWriter(); 
- await writer.write(rawClientData); // first write, nomal is tls client hello 
- writer.releaseLock(); 
- return tcpSocket; 
- } 
- 
- // if the cf connect tcp socket have no incoming data, we retry to redirect ip 
- async function retry() { 
- const tcpSocket = await connectAndWrite(proxyIP || addressRemote, portRemote) 
- // no matter retry success or not, close websocket 
- tcpSocket.closed.catch(error => { 
- console.log('retry tcpSocket closed error', error); 
- }).finally(() => { 
- safeCloseWebSocket(webSocket); 
- }) 
- remoteSocketToWS(tcpSocket, webSocket, vlessResponseHeader, null, log); 
- } 
- 
- const tcpSocket = await connectAndWrite(addressRemote, portRemote); 
- 
- // when remoteSocket is ready, pass to websocket 
- // remote--> ws 
- remoteSocketToWS(tcpSocket, webSocket, vlessResponseHeader, retry, log); 
-} 
- 
-/** 
-  
- * @param {import("@cloudflare/workers-types").WebSocket} webSocketServer 
- * @param {string} earlyDataHeader for ws 0rtt 
- * @param {(info: string)=> void} log for ws 0rtt 
- */ 
-function makeReadableWebSocketStream(webSocketServer, earlyDataHeader, log) { 
- let readableStreamCancel = false; 
- const stream = new ReadableStream({ 
- start(controller) { 
- webSocketServer.addEventListener('message', (event) => { 
- if (readableStreamCancel) { 
- return; 
- } 
- const message = event.data; 
- controller.enqueue(message); 
- }); 
- 
- // The event means that the client closed the client -> server stream. 
- // However, the server -> client stream is still open until you call close() on the server side. 
- // The WebSocket protocol says that a separate close message must be sent in each direction to fully close the socket. 
- webSocketServer.addEventListener('close', () => { 
- // client send close, need close server 
- // if stream is cancel, skip controller.close 
- safeCloseWebSocket(webSocketServer); 
- if (readableStreamCancel) { 
- return; 
- } 
- controller.close(); 
- } 
- ); 
- webSocketServer.addEventListener('error', (err) => { 
- log('webSocketServer has error'); 
- controller.error(err); 
- } 
- ); 
- // for ws 0rtt 
- const { earlyData, error } = base64ToArrayBuffer(earlyDataHeader); 
- if (error) { 
- controller.error(error); 
- } else if (earlyData) { 
- controller.enqueue(earlyData); 
- } 
- }, 
- 
- pull(controller) { 
- // if ws can stop read if stream is full, we can implement backpressure 
- // https://streams.spec.whatwg.org/#example-rs-push-backpressure 
- }, 
- cancel(reason) { 
- // 1. pipe WritableStream has error, this cancel will called, so ws handle server close into here 
- // 2. if readableStream is cancel, all controller.close/enqueue need skip, 
- // 3. but from testing controller.error still work even if readableStream is cancel 
- if (readableStreamCancel) { 
- return; 
- } 
- log(`ReadableStream was canceled, due to ${reason}`) 
- readableStreamCancel = true; 
- safeCloseWebSocket(webSocketServer); 
- } 
- }); 
- 
- return stream; 
- 
-} 
- 
-// https://xtls.github.io/development/protocols/vless.html 
-// https://github.com/zizifn/excalidraw-backup/blob/main/v2ray-protocol.excalidraw 
- 
-/** 
-  
- * @param { ArrayBuffer} vlessBuffer  
- * @param {string} userID  
- * @returns  
- */ 
-function processVlessHeader( 
- vlessBuffer, 
- userID 
-) { 
- if (vlessBuffer.byteLength < 24) { 
- return { 
- hasError: true, 
- message: 'invalid data', 
- }; 
- } 
- const version = new Uint8Array(vlessBuffer.slice(0, 1)); 
- let isValidUser = false; 
- let isUDP = false; 
- if (stringify(new Uint8Array(vlessBuffer.slice(1, 17))) === userID) { 
- isValidUser = true; 
- } 
- if (!isValidUser) { 
- return { 
- hasError: true, 
- message: 'invalid user', 
- }; 
- } 
- 
- const optLength = new Uint8Array(vlessBuffer.slice(17, 18))[0]; 
- //skip opt for now 
- 
- const command = new Uint8Array( 
- vlessBuffer.slice(18 + optLength, 18 + optLength + 1) 
- )[0]; 
- 
- // 0x01 TCP 
- // 0x02 UDP 
- // 0x03 MUX 
- if (command === 1) { 
- } else if (command === 2) { 
- isUDP = true; 
- } else { 
- return { 
- hasError: true, 
- message: `command ${command} is not support, command 01-tcp,02-udp,03-mux`, 
- }; 
- } 
- const portIndex = 18 + optLength + 1; 
- const portBuffer = vlessBuffer.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) 
- ); 
- 
- // 1--> ipv4  addressLength =4 
- // 2--> domain name addressLength=addressBuffer[1] 
- // 3--> ipv6  addressLength =16 
- const addressType = addressBuffer[0]; 
- let addressLength = 0; 
- let addressValueIndex = addressIndex + 1; 
- let addressValue = ''; 
- switch (addressType) { 
- case 1: 
- addressLength = 4; 
- addressValue = new Uint8Array( 
- vlessBuffer.slice(addressValueIndex, addressValueIndex + addressLength) 
- ).join('.'); 
- break; 
- case 2: 
- addressLength = new Uint8Array( 
- vlessBuffer.slice(addressValueIndex, addressValueIndex + 1) 
- )[0]; 
- addressValueIndex += 1; 
- addressValue = new TextDecoder().decode( 
- vlessBuffer.slice(addressValueIndex, addressValueIndex + addressLength) 
- ); 
- break; 
- case 3: 
- addressLength = 16; 
- const dataView = new DataView( 
- vlessBuffer.slice(addressValueIndex, addressValueIndex + addressLength) 
- ); 
- // 2001:0db8:85a3:0000:0000:8a2e:0370:7334 
- const ipv6 = []; 
- for (let i = 0; i < 8; i++) { 
- ipv6.push(dataView.getUint16(i * 2).toString(16)); 
- } 
- addressValue = ipv6.join(':'); 
- // seems no need add [] for ipv6 
- break; 
- default: 
- return { 
- hasError: true, 
- message: `invild  addressType is ${addressType}`, 
- }; 
- } 
- if (!addressValue) { 
- return { 
- hasError: true, 
- message: `addressValue is empty, addressType is ${addressType}`, 
- }; 
- } 
- 
- return { 
- hasError: false, 
- addressRemote: addressValue, 
- addressType, 
- portRemote, 
- rawDataIndex: addressValueIndex + addressLength, 
- vlessVersion: version, 
- isUDP, 
- }; 
-} 
- 
- 
-/** 
-  
- * @param {import("@cloudflare/workers-types").Socket} remoteSocket  
- * @param {import("@cloudflare/workers-types").WebSocket} webSocket  
- * @param {ArrayBuffer} vlessResponseHeader  
- * @param {(() => Promise<void>) | null} retry 
- * @param {*} log  
- */ 
-async function remoteSocketToWS(remoteSocket, webSocket, vlessResponseHeader, retry, log) { 
- // remote--> ws 
- let remoteChunkCount = 0; 
- let chunks = []; 
- /** @type {ArrayBuffer | null} */ 
- let vlessHeader = vlessResponseHeader; 
- let hasIncomingData = false; // check if remoteSocket has incoming data 
- await remoteSocket.readable 
- .pipeTo( 
- new WritableStream({ 
- start() { 
- }, 
- /** 
- 
- * @param {Uint8Array} chunk  
- * @param {*} controller  
- */ 
- async write(chunk, controller) { 
- hasIncomingData = true; 
- // remoteChunkCount++; 
- if (webSocket.readyState !== WS_READY_STATE_OPEN) { 
- controller.error( 
- 'webSocket.readyState is not open, maybe close' 
- ); 
- } 
- if (vlessHeader) { 
- webSocket.send(await new Blob([vlessHeader, chunk]).arrayBuffer()); 
- vlessHeader = null; 
- } else { 
- // seems no need rate limit this, CF seems fix this??.. 
- // if (remoteChunkCount > 20000) { 
- // // cf one package is 4096 byte(4kb),  4096 * 20000 = 80M 
- // await delay(1); 
- // } 
- webSocket.send(chunk); 
- } 
- }, 
- close() { 
- log(`remoteConnection!.readable is close with hasIncomingData is ${hasIncomingData}`); 
- // safeCloseWebSocket(webSocket); // no need server close websocket frist for some case will casue HTTP ERR_CONTENT_LENGTH_MISMATCH issue, client will send close event anyway. 
- }, 
- abort(reason) { 
- console.error(`remoteConnection!.readable abort`, reason); 
- }, 
- }) 
- ) 
- .catch((error) => { 
- console.error( 
- `remoteSocketToWS has exception `, 
- error.stack || error 
- ); 
- safeCloseWebSocket(webSocket); 
- }); 
- 
- // seems is cf connect socket have error, 
- // 1. Socket.closed will have error 
- // 2. Socket.readable will be close without any data coming 
- if (hasIncomingData === false && retry) { 
- log(`retry`) 
- retry(); 
- } 
-} 
- 
-/** 
-  
- * @param {string} base64Str  
- * @returns  
- */ 
-function base64ToArrayBuffer(base64Str) { 
- if (!base64Str) { 
- return { error: null }; 
- } 
- try { 
- // go use modified Base64 for URL rfc4648 which js atob not support 
- base64Str = base64Str.replace(/-/g, '+').replace(/_/g, '/'); 
- const decode = atob(base64Str); 
- const arryBuffer = Uint8Array.from(decode, (c) => c.charCodeAt(0)); 
- return { earlyData: arryBuffer.buffer, error: null }; 
- } catch (error) { 
- return { error }; 
- } 
-} 
- 
-/** 
- * This is not real UUID validation 
- * @param {string} uuid  
- */ 
-function isValidUUID(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; 
- return uuidRegex.test(uuid); 
-} 
- 
-const WS_READY_STATE_OPEN = 1; 
-const WS_READY_STATE_CLOSING = 2; 
-/** 
- * Normally, WebSocket will not has exceptions when close. 
- * @param {import("@cloudflare/workers-types").WebSocket} socket 
- */ 
-function safeCloseWebSocket(socket) { 
- try { 
- if (socket.readyState === WS_READY_STATE_OPEN || socket.readyState === WS_READY_STATE_CLOSING) { 
- socket.close(); 
- } 
- } catch (error) { 
- console.error('safeCloseWebSocket error', error); 
- } 
-} 
- 
-const byteToHex = []; 
-for (let i = 0; i < 256; ++i) { 
- byteToHex.push((i + 256).toString(16).slice(1)); 
-} 
-function unsafeStringify(arr, offset = 0) { 
- return (byteToHex[arr[offset + 0]] + byteToHex[arr[offset + 1]] + byteToHex[arr[offset + 2]] + byteToHex[arr[offset + 3]] + "-" + byteToHex[arr[offset + 4]] + byteToHex[arr[offset + 5]] + "-" + byteToHex[arr[offset + 6]] + byteToHex[arr[offset + 7]] + "-" + byteToHex[arr[offset + 8]] + byteToHex[arr[offset + 9]] + "-" + byteToHex[arr[offset + 10]] + byteToHex[arr[offset + 11]] + byteToHex[arr[offset + 12]] + byteToHex[arr[offset + 13]] + byteToHex[arr[offset + 14]] + byteToHex[arr[offset + 15]]).toLowerCase(); 
-} 
-function stringify(arr, offset = 0) { 
- const uuid = unsafeStringify(arr, offset); 
- if (!isValidUUID(uuid)) { 
- throw TypeError("Stringified UUID is invalid"); 
- } 
- return uuid; 
-} 
- 
- 
-/** 
-  
- * @param {import("@cloudflare/workers-types").WebSocket} webSocket  
- * @param {ArrayBuffer} vlessResponseHeader  
- * @param {(string)=> void} log  
- */ 
-async function handleUDPOutBound(webSocket, vlessResponseHeader, log) { 
- 
- let isVlessHeaderSent = 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('https://1.1.1.1/dns-query', 
- { 
- 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 (isVlessHeaderSent) { 
- webSocket.send(await new Blob([udpSizeBuffer, dnsQueryResult]).arrayBuffer()); 
- } else { 
- webSocket.send(await new Blob([vlessResponseHeader, udpSizeBuffer, dnsQueryResult]).arrayBuffer()); 
- isVlessHeaderSent = true; 
- } 
- } 
- } 
- })).catch((error) => { 
- log('dns udp has error' + error) 
- }); 
- 
- const writer = transformStream.writable.getWriter(); 
- 
- return { 
- /** 
- 
- * @param {Uint8Array} chunk  
- */ 
- write(chunk) { 
- writer.write(chunk); 
- } 
- }; 
-} 
- 
-/** 
-  
- * @param {string} userID  
- * @param {string | null} hostName 
- * @returns {string} 
- */ 
-function getVLESSConfig(userID, hostName) { 
- const vlessMain = `vless://${userID}@${hostName}:443?encryption=none&security=tls&sni=${hostName}&fp=randomized&type=ws&host=${hostName}&path=%2F%3Fed%3D2048#${hostName}` 
- return ` 
-################################################################ 
-v2ray 
---------------------------------------------------------------- 
-${vlessMain} 
---------------------------------------------------------------- 
-################################################################ 
-clash-meta 
---------------------------------------------------------------- 
-- type: vless 
-  name: ${hostName} 
-  server: ${hostName} 
-  port: 443 
-  uuid: ${userID} 
-  network: ws 
-  tls: true 
-  udp: false 
-  sni: ${hostName} 
-  client-fingerprint: chrome 
-  ws-opts: 
-    path: "/?ed=2048" 
-    headers: 
-      host: ${hostName} 
---------------------------------------------------------------- 
-################################################################ 
-`; 
-} 
- 
-</code> 
- 
-++++ 
  
  
-====== 夏时 Accelerator ====== 
  
-需要到淘宝买一个美区 APPLE ID 
  
-  * [[https://apps.apple.com/us/app/vpn-%E5%A4%8F%E6%97%B6-accelerator/id1544742935|夏时 Accelerator]] +{{tag>vpn}}
-  * [[https://play.google.com/store/apps/details?id=com.free.vpn.super.hotspot.open&hl=de&gl=US|VPN - Super Unlimited Proxy]] +
-  * [[https://hyperbeam.com/?c=zhY9a5nF|在线翻墙]] +
-  * [[https://www.onworks.net/zh-CN/|在线虚拟机]] +
-  * [[https://www.bxvv1.xyz|暴雪VPN]] 使用 ++ 推荐码 | 6993538623343247360 ++ 可免费长期使用+
  
  
工具/编辑/herokuv2ray.1690010598.txt.gz · 最后更改: 2023-07-22 07:23 由 goldentianya
回到顶部
CC Attribution-Share Alike 4.0 International
Driven by DokuWiki Recent changes RSS feed Valid CSS Valid XHTML 1.0