树洞剪藏#剪藏#树洞剪藏

🪜 白嫖Cloudflare Workers搭建Vless代理 - 开发调优 / 开发调优, Lv1 - LINUX DO

2024 年 11 月 15 日1 分钟
分享Twitter / XTelegram微博
🪜 白嫖Cloudflare Workers搭建Vless代理 - 开发调优 / 开发调优, Lv1 - LINUX DO 封面

同步来源:树洞剪藏 源站剪藏 ID:76 原文地址:https://linux.do/t/topic/5669

打开原文 · 打开源站剪藏快照


🪜 白嫖Cloudflare Workers搭建Vless代理 - 开发调优 / 开发调优, Lv1 - LINUX DO

跳到主要内容

话题

我的帖子

关于

友链

文档

更多

外部链接

Status

Connect

Channel

Telegram

Shared Chat

类别

开发调优

资源荟萃

文档共建

跳蚤市场

前沿快讯

福利羊毛

搞七捻三

运营反馈

深海幽域

所有类别

标签

抽奖

公告

精华神帖

快问快答

人工智能

所有标签

消息

收件箱

频道

常规频道

直接消息

聊天

真诚 、 友善 、 团结 、 专业 ,共建你我引以为荣之社区。 《常见问题解答》

白嫖 Cloudflare Workers 搭建 Vless 代理

开发调优 开发调优, Lv1

1月 30 日

1 / 264

1月 30 日

返回

7月 3 日

热门回复

前排围观支持一下 感谢分享大佬厉害啊 有点厉害支持~~

坐和放宽 peanut996 种子用户

9 1月 30 日 #1

前置准备

域名

cloudflare 账号

准备工作是需要一个能够管理域名的 cloudflare 账号。

Workers 简介

Workers 是 Cloudflare 推出的一项 serverless 产品,无需配置或维护基础架构即可创建全新的应用程序或扩充现有的应用程序。它允许开发者在全球分布的 Cloudflare 数据中心运行 JavaScript/C/C++/Rust 代码。这个服务使开发者能够在离用户更近的地方执行代码,从而提高网站性能和响应速度。

目前 Free 版本的账号提供每天 10w 次的调用,对于普通用户来说,完全够用!(不愧是你,活菩萨 Cloudflare!)

搭建教程

首先需要感谢大佬的辛勤付出,目前因为害怕滥用违反 TOS 政策作者已经 删库 (cf 论坛有人讨论这件事,但是官方貌似不是很在意),走过路过的可以给大佬点个 star

代码仓库: https://github.com/zizifn/edgetunnel 383

创建 Worker

登陆 cloudflare 创建一个新的 worker

Untitled 1906×752 97.6 KB

然后回要求输入 worker 名称和代码,这里代码我们直接保留可以先不做改动,名称可以随便取。

生成 UUID

因为 vless 要求一个独特的 uuid,这里我们需要事先准备一个 uuid,随便生成一个即可。生成的 uuid 需要保留横线,如 15ba0eff-e227-4e94-9b2a-76d93d858865 即可

填充代码

下方粘贴了一个完整的代码块,但是仍然需要修改两个变量即可使用:

userID 这里直接填写刚刚生成的 uuid 即可

proxyIP 目前 worker 仍然存在 bug,对于 host 在 cf 的网站访问会出现问题,所以对于这部分网站需要通过中转服务器实现正常访问,代码注释中已经列举了一些常用的 IP,如需寻找中转 IP 可以前去 https://t.me/cf_push 216 频道中获取。

// version base on commit 43fad05dcdae3b723c53c226f8181fc5bd47223e, time is 2023-06-22 15:20:02 UTC. // @ts-ignore import { connect } from 'cloudflare:sockets' ;

// 修改这里的userID为刚刚生成的uuid let userID = 'd04fe0f8-bd1f-403a-9fc7-22dd254bb715' ;

// 下面地址选一个填写 // edgetunnel.anycast.eu.org(美国的加速CDN) // cdn.anycast.eu.org(香港日本新加坡加速CDN) // 香港优选IP: 20.187.89.16 // 韩国高速优选IP: 129.154.199.251 // 日本高速优选IP: 146.56.149.205 // cdn-all.xn--b6gac.eu.org // cdn.xn--b6gac.eu.org // cdn-b100.xn--b6gac.eu.org // edgetunnel.anycast.eu.org // cdn.anycast.eu.org // let proxyIP = '47.74.51.138'; // let proxyIP = '130.61.20.4'; let proxyIP = '43.157.17.4' ;

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 } / 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 } 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) | 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}

################################################################ ` ; }

找到刚刚创建的 worker 点击 quick edit,将刚刚修改完毕的代码粘贴,点击 save and deploy 即可部署成功。

Untitled 1 1355×396 21.9 KB

Untitled 2 1912×581 133 KB

绑定自定义域名

因为 worker 的默认生成域名已经被墙,所以需要绑定一个自定义域名,实现直连访问

Untitled 3 1344×756 42.2 KB

输入自定义二级域名,如 vless.yourdomain.com ,这里需要把后面的 yourdomain.com 换成已在 cf 托管的域名。

接下来直接浏览器访问 https://vless.yourdomain.com/填写的userID 如果能正确显示 vless 链接信息则搭建成功,直接导入 v2ray/shadowrocket/sing-box 使用即可。

优选 IP

因为 worker 是搭建在 cf 边缘计算网络上的,所以仍然可以通过优选 IP 的方式加速访问:

直接访问 https://stock.hostmonit.com/CloudFlareYes 407

找到相同运营商和延迟最低的 ip,在 vless 使用的地方将服务器地址改为刚刚找到的 ip,保存连接即可。

优选 IP 可能需要使用 80 端口并且关闭 tls 加密使用

目前测试出来的效果是比 WARP 好很多的,推荐长期使用!

2 个回复

heart

+1

clap

210

回复

使用 Cloudflare 的 Worker 来搭建Vless代理 可oai,奈菲等 61 【Cloudflare系列教程】汇总帖 34 佬友们平时都用什么vpn 26 完全使用cloudflare worker搭建tg的代理是否可行? 22 Cloudflare WARP提取WireGuard配置文件 12 其他 7 个

9.6k

浏览量

576

25

链接

134

用户

51

7

6

5

5

阅读时间

23 分钟

热门回复

talefu towelong 海纳百川

1月 30 日 #2

优选 IP 为啥不显示端口号呀 1 个回复

3 回复

Zhile 龙行龘龘

1月 30 日 #3

用过一段时间 比 warp 强 至少能够连上 2 个回复

heart

+1

4

回复

坐和放宽 peanut996 种子用户

1 talefu 1月 30 日 #4

直接 443 就行 不用换 1 个回复

2 回复

类别 1月 30 日 更新

从 常规话题 到 软件开发

talefu towelong 海纳百川 坐和放宽 1月 30 日 #6

ok

2 回复

坐和放宽 peanut996 种子用户

Zhile 1月 30 日 #7

比 WARP 快很多,唯一的点就是代理 IP 的安全性。。反正两个混着用 1 个回复

1 回复

Zhile 龙行龘龘 坐和放宽 1月 30 日 #8

还有用 worker 搭的 vless ip 好像是每秒都变 1 个回复

heart

+1

4

回复

想请教一下大家关于谷歌学术使用频繁导致vps的ip被ban的解决方法 4

坐和放宽 peanut996 种子用户

Zhile 1月 30 日 #9

是的 因为是 serverless, 但是之前测试的情况是他会在一个 ip 范围内反复横跳,不稳定。日常使用没大问题,但是特殊场景需要注意。

3 回复

Ink 🌌 inker 浴火重生

1月 30 日 #10

用这个部署的完全访问不了网页的 ChatGPT,不知道是哪里截断了这个请求 hh 2 个回复

3 回复

坐和放宽 peanut996 种子用户

Ink 🌌 1月 30 日 #11

因为 open ai 也用的 cf 做防御啊。。。肯定不能用这个访问 GPT 了 1 个回复

1 回复

Ink 🌌 inker 浴火重生 坐和放宽 1月 30 日 #12

但是这个论坛也是呀,访问却一切正常,那估计是 oai 做了一些策略 3 个回复

1 回复

坐和放宽 peanut996 种子用户

Ink 🌌 1月 30 日 #13

一般的反代 ip 可能都被 oai 封禁了

1 回复

Zhile 龙行龘龘 Ink 🌌 1月 30 日 #14

oai 把 cf ip 段屏蔽了 3 个回复

4 回复

Ink 🌌 inker 浴火重生 Zhile 1月 30 日 #15

好家伙,好吧,有点东西

2 回复

Ink 🌌 inker 浴火重生

1月 30 日 #16

不过这个部署的拿来做匿名代理还是挺好的,完全没有支付的牵连,唯一涉及的就是一个 cf 账号,溯源 ip 难度还挺大 hh 2 个回复

2 回复

liuweiqing 14790897 银笔杆

Ink 🌌 1月 30 日 #17

因为这种代理的 IP 会一直变,不合格 1 个回复

30 回复

坐和放宽 peanut996 种子用户

Ink 🌌 1月 30 日 #18

就我一个天天把它当成主力梯子吗( 2 个回复

1 回复

Ink 🌌 inker 浴火重生 liuweiqing 1月 30 日 #19

哈哈不需要它稳定 ip,只要不能溯源就挺有用了其实

2 回复

标签 1月 30 日 更新

Removed 小工具

开始阅读 启用自动点赞

楼主

等级

相关文章