[网络技巧] CF Worker搭建vless协议代理
作者:观棋 日期:2023-08-02 11:27:50 浏览:9 分类:涨姿势
1、复制如下代码到worker中
注意自己可修改uuid 具体搜索
3e036e57-4d74-469a-b312-b97b59680ec3
// ../node_modules/uuid/dist/esm-browser/regex.js
var regex_default = /^(?:[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}|00000000-0000-0000-0000-000000000000)$/i;
// ../node_modules/uuid/dist/esm-browser/validate.js
function validate(uuid) {
return typeof uuid === "string" && regex_default.test(uuid);
}
var validate_default = validate;
// ../node_modules/uuid/dist/esm-browser/stringify.js
var 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 (!validate_default(uuid)) {
throw TypeError("Stringified UUID is invalid");
}
return uuid;
}
var stringify_default = stringify;
// vless-js/lib/vless-js.ts
var WS_READY_STATE_OPEN = 1;
function makeReadableWebSocketStream(ws, earlyDataHeader, log) {
let readableStreamCancel = false;
return new ReadableStream({
start(controller) {
ws.addEventListener("message", async (e) => {
if (readableStreamCancel) {
return;
}
const vlessBuffer = e.data;
controller.enqueue(vlessBuffer);
});
ws.addEventListener("error", (e) => {
log("socket has error");
readableStreamCancel = true;
controller.error(e);
});
ws.addEventListener("close", () => {
try {
log("webSocket is close");
if (readableStreamCancel) {
return;
}
controller.close();
} catch (error2) {
log(`websocketStream can't close DUE to `, error2);
}
});
const { earlyData, error } = base64ToArrayBuffer(earlyDataHeader);
if (error) {
log(`earlyDataHeader has invaild base64`);
safeCloseWebSocket(ws);
return;
}
if (earlyData) {
controller.enqueue(earlyData);
}
},
pull(controller) {
},
cancel(reason) {
log(`websocketStream is cancel DUE to `, reason);
if (readableStreamCancel) {
return;
}
readableStreamCancel = true;
safeCloseWebSocket(ws);
}
});
}
function base64ToArrayBuffer(base64Str) {
if (!base64Str) {
return { error: null };
}
try {
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 };
}
}
function safeCloseWebSocket(socket) {
try {
if (socket.readyState === WS_READY_STATE_OPEN) {
socket.close();
}
} catch (error) {
console.error("safeCloseWebSocket error", error);
}
}
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_default(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];
const command = new Uint8Array(
vlessBuffer.slice(18 + optLength, 18 + optLength + 1)
)[0];
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);
const portRemote = new DataView(portBuffer).getInt16(0);
let addressIndex = portIndex + 2;
const addressBuffer = new Uint8Array(
vlessBuffer.slice(addressIndex, addressIndex + 1)
);
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)
);
const ipv6 = [];
for (let i = 0; i < 8; i++) {
ipv6.push(dataView.getUint16(i * 2).toString(16));
}
addressValue = ipv6.join(":");
break;
default:
console.log(`invild addressType is ${addressType}`);
}
if (!addressValue) {
return {
hasError: true,
message: `addressValue is empty, addressType is ${addressType}`
};
}
return {
hasError: false,
addressType,
addressRemote: addressValue,
portRemote,
rawDataIndex: addressValueIndex + addressLength,
vlessVersion: version,
isUDP
};
}
// index.ts
import { connect } from "cloudflare:sockets";
// dns.ts
var doh = "https://cloudflare-dns.com/dns-query";
var dns = async (domain) => {
const response = await fetch(`${doh}?name=${domain}`, {
method: "GET",
headers: {
"Accept": "application/dns-json"
}
});
const data = await response.json();
const ans = data?.Answer;
return ans?.find((record) => record.type === 1)?.data;
};
var isCloudFlareIP = (ip) => {
const CFIP = [
[2918526976, -4096],
[1729491968, -1024],
[1729546240, -1024],
[1730085888, -1024],
[2372222976, -16384],
[1822605312, -16384],
[3193827328, -4096],
[3161612288, -4096],
[3320508416, -1024],
[3324608512, -32768],
[2728263680, -131072],
[1745879040, -524288],
[1746403328, -262144],
[2889875456, -524288],
[2197833728, -1024]
];
const isIp4InCidr = (ip2, cidr) => {
const [a, b, c, d] = ip2.split(".").map(Number);
ip2 = a << 24 | b << 16 | c << 8 | d;
const [range, mask] = cidr;
return (ip2 & mask) === range;
};
return CFIP.some((cidr) => isIp4InCidr(ip, cidr));
};
// index.ts
var HTML404 = "Script by zizifn, modified by MisakaNo";
function delay2(ms) {
return new Promise((resolve, rej) => {
setTimeout(resolve, ms);
});
}
var workers_default = {
async fetch(request, env, ctx) {
let address = "";
let portWithRandomLog = "";
const userID = env.UUID || "3e036e57-4d74-469a-b312-b97b59680ec3";
const log = (info, event) => {
console.log(`[${address}:${portWithRandomLog}] ${info}`, event || "");
};
const upgradeHeader = request.headers.get("Upgrade");
if (!upgradeHeader || upgradeHeader !== "websocket") {
return new Response(HTML404, {
status: 404,
headers: new Headers({ "Content-Type": "text/html" })
});
}
const webSocketPair = new WebSocketPair();
const [client, webSocket] = Object.values(webSocketPair);
const earlyDataHeader = request.headers.get("sec-websocket-protocol") || "";
let remoteSocket = null;
webSocket.accept();
const readableWebSocketStream = makeReadableWebSocketStream(
webSocket,
earlyDataHeader,
log
);
let vlessResponseHeader = new Uint8Array([0, 0]);
let remoteConnectionReadyResolve;
readableWebSocketStream.pipeTo(
new WritableStream({
async write(chunk, controller) {
if (remoteSocket) {
const writer2 = remoteSocket.writable.getWriter();
await writer2.write(chunk);
writer2.releaseLock();
return;
}
const {
hasError,
message,
portRemote,
addressType,
addressRemote,
rawDataIndex,
vlessVersion,
isUDP
} = processVlessHeader(chunk, userID);
address = addressRemote || "";
portWithRandomLog = `${portRemote} -- ${isUDP ? "udp " : "tcp "} `;
if (isUDP && portRemote != 53) {
controller.error("UDP proxy only enable for DNS which is port 53");
webSocket.close();
return;
}
if (hasError) {
controller.error(message);
webSocket.close();
return;
}
vlessResponseHeader = new Uint8Array([vlessVersion[0], 0]);
const rawClientData = chunk.slice(rawDataIndex);
let queryip = "";
if (addressType === 2) {
queryip = await dns(addressRemote);
if (queryip && isCloudFlareIP(queryip)) {
queryip = "64.68.192." + Math.floor(Math.random() * 255);
}
}
remoteSocket = connect({
hostname: queryip ? queryip : addressRemote,
port: portRemote
});
log(`connected`);
const writer = remoteSocket.writable.getWriter();
await writer.write(rawClientData);
writer.releaseLock();
remoteConnectionReadyResolve(remoteSocket);
},
close() {
console.log(
`[${address}:${portWithRandomLog}] readableWebSocketStream is close`
);
},
abort(reason) {
console.log(
`[${address}:${portWithRandomLog}] readableWebSocketStream is abort`,
JSON.stringify(reason)
);
}
})
);
(async () => {
await new Promise((resolve) => remoteConnectionReadyResolve = resolve);
let count = 0;
remoteSocket.readable.pipeTo(
new WritableStream({
start() {
if (webSocket.readyState === WebSocket.READY_STATE_OPEN) {
webSocket.send(vlessResponseHeader);
}
},
async write(chunk, controller) {
if (webSocket.readyState === WebSocket.READY_STATE_OPEN) {
if (count++ > 2e4) {
await delay2(1);
}
webSocket.send(chunk);
} else {
controller.error(
"webSocket.readyState is not open, maybe close"
);
}
},
close() {
console.log(
`[${address}:${portWithRandomLog}] remoteConnection!.readable is close`
);
},
abort(reason) {
console.error(
`[${address}:${portWithRandomLog}] remoteConnection!.readable abort`,
reason
);
}
})
).catch((error) => {
console.error(
`[${address}:${portWithRandomLog}] processWebSocket has exception `,
error.stack || error
);
safeCloseWebSocket2(webSocket);
});
})();
return new Response(null, {
status: 101,
webSocket: client
});
}
};
function safeCloseWebSocket2(ws) {
try {
if (ws.readyState !== WebSocket.READY_STATE_CLOSED) {
ws.close();
}
} catch (error) {
console.error("safeCloseWebSocket error", error);
}
}
export {
workers_default as default
};
//# sourceMappingURL=index.js.map2、节点配置如下
协议:Vless 地址:CF优选IP / 域名 端口:80 或 CF 支持的 HTTPS 端口 UUID/密码:设置的UUID(如未设置则为 `3e036e57-4d74-469a-b312-b97b59680ec3`) 传输协议:ws 伪装域名:设置的 Workers 自定义域名 路径:/
由于目前worker自带域名已被X,建议使用自己的域名
协议:Vless 地址:CF优选IP / 自己的域名 端口:443 或 CF 支持的 HTTPS 端口 UUID/密码:设置的UUID(如未设置则为 `3e036e57-4d74-469a-b312-b97b59680ec3`) 传输协议:ws 伪装域名:自己的域名 路径:/ 传输安全:TLS 跳过证书验证:true 或 false 都可以
参考文章
https://web.archive.org/web/20230526070655/https://blog.misaka.rest/2023/05/26/cf-wkrs-vless/
参考githun相关项目
https://github.com/zizifn/edgetunnel
The text was updated successfully, but these errors were encountered: |
猜你还喜欢
- 11-10 城阳电工电路:家庭电路问题频出,一路寻找发电厂的奇怪之旅!
- 11-03 雀儿满天飞:品酒聊人生,倾听初恋回忆,探索小仙女的爱情价值观
- 08-02 [网络技巧] CF Worker搭建vless协议代理
- 08-02 [web] CloudFlare通过SaaS免费使用CNAME接入域名解析
- 08-01 [经验分享] 使用金山文档的每日定时任务实现阿里云盘自动每日签到,无需部署,无需服务器
- 07-07 [教程] Wise激活全流程教学详解(全程丝滑)
- 06-22 [涨姿势] 空调省电的秘密,我后悔现在才知道
- 05-09 [电脑技巧] 连接ftp的三种方式
- 04-25 [玩手机] 手机一直在提示更新,你们觉得更新好还是不好呢?
- 04-25 [福利教程] 基于ChatGPT4.0免费,保姆级教你申请注册自己的NewBing账号
- 04-24 [玩网络] 优化你的网络线路(高级篇)——选购租赁哪款VPN或者VPS
- 04-24 [玩网络] 优化你的网络线路(进阶篇)——为什么要使用VPN或者VPS
取消回复欢迎 你 发表评论:
-
- 最新文章
- 热门文章
- 热评文章
![[翻译识别] Pot v2.7.9 跨平台划词翻译和OCR工具](https://www.yuanjudao.com/zb_users/upload/2024/04/20240404173358171222323898322.jpeg)
[翻译识别] Pot v2.7.9 跨平台划词翻译和OCR工具
![[素材资源] 短视频剪辑配音音效库(9000+)](https://www.yuanjudao.com/zb_users/upload/2024/04/20240404171827171222230789292.png)
[素材资源] 短视频剪辑配音音效库(9000+)
![[笔刷] 337期全中文笔刷大合集,全网分类最精准,iPad手绘强推!](https://www.yuanjudao.com/zb_users/upload/2024/04/20240404161420171221846074126.png)
[笔刷] 337期全中文笔刷大合集,全网分类最精准,iPad手绘强推!
![[英语教育] 新概念英语视频教程](https://www.yuanjudao.com/zb_users/upload/2024/04/20240404104614171219877474998.jpeg)
[英语教育] 新概念英语视频教程

樱花妹攻略

2-7更新《幻兽帕鲁》v0.1.4.1中文版下载+建立服务器+steam联机教程
![[上传下载] 比特彗星(BitComet) v2.05 解锁全功能豪华版](https://www.yuanjudao.com/zb_users/upload/2023/12/20231206190554170186075460545.jpeg)
[上传下载] 比特彗星(BitComet) v2.05 解锁全功能豪华版
![[复制加速] FastCopy汉化破解版(文件快速复制工具)5.4.3](https://www.yuanjudao.com/zb_users/upload/2023/12/20231201152411170141545147522.jpeg)
[复制加速] FastCopy汉化破解版(文件快速复制工具)5.4.3
![[资料] 创业必备手册资料大全](https://www.yuanjudao.com/zb_users/upload/2023/11/20231129220939170126697935122.jpg)
[资料] 创业必备手册资料大全
![[资源] 销售那点事儿--高建华(完结)](https://www.yuanjudao.com/zb_users/upload/2023/11/20231129164930170124777036286.webp)
[资源] 销售那点事儿--高建华(完结)

【12-11暂停更新】SSR更新分享,老司机懂的,滴滴!

ai明星同人换脸,《极乐神教》1-5部合集

极品番号动图推荐一波12-28

上原亚衣(上原亜衣)作品番号合集

酒井千波(酒井ちなみ)作品番号合集
![[3D漫画] [3D全彩/合集]同人画师—大D 2020年12月步兵整合+游戏插画[210MB]](https://www.yuanjudao.com/zb_users/upload/2021/01/20210108033214_39763.jpg)
[3D漫画] [3D全彩/合集]同人画师—大D 2020年12月步兵整合+游戏插画[210MB]

SWAG最美女演员“chinhbaby”,SWAG里演过圣诞麋鹿妹的新片

越南少女“Erica hand”回归P站更名为“Xiao e”

教你如何搜索AV字幕,中文字幕爱好者的福利

白咲碧(香椎みなみ)作品番号合集

【12-11暂停更新】SSR更新分享,老司机懂的,滴滴!
![[PC+安卓]表姐1.6完结版 汉化作弊版|我的性感表姐 Ver1.60 精修汉化作弊版,新增全程攻略](https://www.yuanjudao.com/zb_users/upload/2019/07/201907061562411242172298.jpg)
[PC+安卓]表姐1.6完结版 汉化作弊版|我的性感表姐 Ver1.60 精修汉化作弊版,新增全程攻略

2021科幻动作《永恒族》4K.HD中英双字
![[动画] [铃芽之旅 Suzume no Tojimari][铃芽户缔][Trial Version]【正式流媒体版】外挂中字 正式版](https://www.yuanjudao.com/zb_users/upload/2023/04/20230403003810168045349041554.jpeg)
[动画] [铃芽之旅 Suzume no Tojimari][铃芽户缔][Trial Version]【正式流媒体版】外挂中字 正式版

全国大保健狼友资源,全部验证过,老司机数据库
![[公告]必看!关于充值、资源等问题](https://www.yuanjudao.com/zb_users/plugin/tx_side/img/nopic.png)
[公告]必看!关于充值、资源等问题
![[资料] 1~12年级奥数教程](https://www.yuanjudao.com/zb_users/upload/2023/01/20230116233416167388325675216.jpeg)
[资料] 1~12年级奥数教程
![[美剧] [西部世界][1-4 季合集][英语双字][无删减][MP4][BD1080p]](https://www.yuanjudao.com/zb_users/upload/2022/08/20220817021932166067397269827.jpeg)
[美剧] [西部世界][1-4 季合集][英语双字][无删减][MP4][BD1080p]
![[极品国模] 刘亦雯2021.03.28(S)无水印,明星颜值极品身材国模大尺度私拍[765P/5.12G]](https://www.yuanjudao.com/zb_users/upload/2022/10/20221004030632166482399262690.jpeg)
[极品国模] 刘亦雯2021.03.28(S)无水印,明星颜值极品身材国模大尺度私拍[765P/5.12G]

极品美女好身材可爱面容带你爱爱,美颜撸管必备-更新链接
- 最新评论
-

有意思的片子sdssds3 评论于:03-22 
很久就想看啦。谢谢楼主sdssds3 评论于:03-22 
经典永留存bantiaomin 评论于:02-08 
看看在说四个眼 评论于:02-03 
gooooooodflyingmoon 评论于:01-04 
コメント我喜双中国、万分感谢t3taira 评论于:08-30 
好评推荐bbaa365 评论于:08-28 
加油很好啊军子混混 评论于:08-20 
感谢分享123yaonie 评论于:08-19 
不知道算不算,毕竟这集早就有了,今年莫名又被拿出来播观棋 评论于:08-16
- 热门tag

