🪜 白嫖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 小工具
开始阅读 启用自动点赞
楼主
等级