Andy的百宝箱
HOME
ABOUT ME
CONTACT ME
DISCLAIMER
PRIVACY POLICY
工具||机场||出金
VPS评测与推荐
ChatGPT Prompt
CF Worker Vless 优选域名
VPS和VPN和机场
白鲸加速器-无限白嫖
两元店(季付仅7元)
极速云(价格超低)
1元100G+流媒体解锁
spcloud-秒速云
自用跨境电商机场
12元一年--杜卡迪机场
红杏加速器
25元年付-领航机场
快冲云:独享带宽、全天4K、高速稳定
2024年8月17日星期六
HiN VPN: 永久免费的多协议订阅链接,完全免费科学上网、VPN,部分节点支持4k、8k视频,大部分支持解锁流媒体、与ChatGPT,免费翻墙!!
网站地址:
https://itsyebekhe.github.io/HiN-VPN/
2024年5月5日星期日
永久免费翻墙,永久免费节点,使用Cloudflare Worker 搭建免费Trojan协议节点!
大佬项目:
https://github.com/ca110us/epeius
worker.js
// src/worker.js
import
{ connect } from
"cloudflare:sockets"
;
const
proxyIPs = [
'cdn.xn--b6gac.eu.org'
,
'cdn-all.xn--b6gac.eu.org'
,
'workers.cloudflare.cyou'
];
let proxyIP = proxyIPs[Math.floor(Math.random() * proxyIPs.length)];
let sha224Password =
'xxxx'
;
const
worker_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
{
proxyIP = env.PROXYIP || proxyIP;
const
upgradeHeader = request.headers.get(
"Upgrade"
);
if
(!upgradeHeader || upgradeHeader !==
"websocket"
) {
const
url =
new
URL(request.url);
switch
(url.pathname) {
case
"/link"
:
const
host = request.headers.get(
'Host'
);
return
new
Response(`trojan:
//ca110us@${host}:443/?type=ws&host=${host}&security=tls`, {
status: 200,
headers: {
"Content-Type"
:
"text/plain;charset=utf-8"
,
}
});
default
:
return
new
Response(
"404 Not found"
, { status: 404 });
}
}
else
{
return
await trojanOverWSHandler(request);
}
}
catch
(err) {
let e = err;
return
new
Response(e.toString());
}
}
};
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
} = await parseTrojanHeader(chunk);
address = addressRemote;
portWithRandomLog = `${portRemote}--${Math.random()} tcp`;
if
(hasError) {
throw
new
Error(message);
return
;
}
handleTCPOutBound(remoteSocketWapper, addressRemote, portRemote, rawClientData, webSocket, log);
},
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
});
}
async
function
parseTrojanHeader(buffer) {
if
(buffer.byteLength < 56) {
return
{
hasError:
true
,
message:
"invalid data"
};
}
let crLfIndex = 56;
if
(
new
Uint8Array(buffer.slice(56, 57))[0] !== 0x0d ||
new
Uint8Array(buffer.slice(57, 58))[0] !== 0x0a) {
return
{
hasError:
true
,
message:
"invalid header format (missing CR LF)"
};
}
const
password =
new
TextDecoder().decode(buffer.slice(0, crLfIndex));
if
(password !== sha224Password) {
return
{
hasError:
true
,
message:
"invalid password"
};
}
const
socks5DataBuffer = buffer.slice(crLfIndex + 2);
if
(socks5DataBuffer.byteLength < 6) {
return
{
hasError:
true
,
message:
"invalid SOCKS5 request data"
};
}
const
view =
new
DataView(socks5DataBuffer);
const
cmd = view.getUint8(0);
if
(cmd !== 1) {
return
{
hasError:
true
,
message:
"unsupported command, only TCP (CONNECT) is allowed"
};
}
const
atype = view.getUint8(1);
// 0x01: IPv4 address
// 0x03: Domain name
// 0x04: IPv6 address
let addressLength = 0;
let addressIndex = 2;
let address =
""
;
switch
(atype) {
case
1:
addressLength = 4;
address =
new
Uint8Array(
socks5DataBuffer.slice(addressIndex, addressIndex + addressLength)
).join(
"."
);
break
;
case
3:
addressLength =
new
Uint8Array(
socks5DataBuffer.slice(addressIndex, addressIndex + 1)
)[0];
addressIndex += 1;
address =
new
TextDecoder().decode(
socks5DataBuffer.slice(addressIndex, addressIndex + addressLength)
);
break
;
case
4:
addressLength = 16;
const
dataView =
new
DataView(socks5DataBuffer.slice(addressIndex, addressIndex + addressLength));
const
ipv6 = [];
for
(let i = 0; i < 8; i++) {
ipv6.push(dataView.getUint16(i * 2).toString(16));
}
address = ipv6.join(
":"
);
break
;
default
:
return
{
hasError:
true
,
message: `invalid addressType is ${atype}`
};
}
if
(!address) {
return
{
hasError:
true
,
message: `address is empty, addressType is ${atype}`
};
}
const
portIndex = addressIndex + addressLength;
const
portBuffer = socks5DataBuffer.slice(portIndex, portIndex + 2);
const
portRemote =
new
DataView(portBuffer).getUint16(0);
return
{
hasError:
false
,
addressRemote: address,
portRemote,
rawClientData: socks5DataBuffer.slice(portIndex + 4)
};
}
async
function
handleTCPOutBound(remoteSocket, addressRemote, portRemote, rawClientData, webSocket, log) {
async
function
connectAndWrite(address, port) {
const
tcpSocket2 = connect({
hostname: address,
port
});
remoteSocket.value = tcpSocket2;
log(`connected to ${address}:${port}`);
const
writer = tcpSocket2.writable.getWriter();
await writer.write(rawClientData);
writer.releaseLock();
return
tcpSocket2;
}
async
function
retry() {
const
tcpSocket2 = await connectAndWrite(proxyIP || addressRemote, portRemote);
tcpSocket2.closed.
catch
((error) => {
console.log(
"retry tcpSocket closed error"
, error);
}).
finally
(() => {
safeCloseWebSocket(webSocket);
});
remoteSocketToWS(tcpSocket2, webSocket,
null
, log);
}
const
tcpSocket = await connectAndWrite(addressRemote, portRemote);
remoteSocketToWS(tcpSocket, webSocket, retry, log);
}
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);
});
webSocketServer.addEventListener(
"close"
, () => {
safeCloseWebSocket(webSocketServer);
if
(readableStreamCancel) {
return
;
}
controller.close();
});
webSocketServer.addEventListener(
"error"
, (err) => {
log(
"webSocketServer error"
);
controller.error(err);
});
const
{ earlyData, error } = base64ToArrayBuffer(earlyDataHeader);
if
(error) {
controller.error(error);
}
else
if
(earlyData) {
controller.enqueue(earlyData);
}
},
pull(controller) {},
cancel(reason) {
if
(readableStreamCancel) {
return
;
}
log(`readableStream was canceled, due to ${reason}`);
readableStreamCancel =
true
;
safeCloseWebSocket(webSocketServer);
}
});
return
stream;
}
async
function
remoteSocketToWS(remoteSocket, webSocket, retry, log) {
let hasIncomingData =
false
;
await remoteSocket.readable.pipeTo(
new
WritableStream({
start() {},
/**
*
* @param {Uint8Array} chunk
* @param {*} controller
*/
async write(chunk, controller) {
hasIncomingData =
true
;
if
(webSocket.readyState !== WS_READY_STATE_OPEN) {
controller.error(
"webSocket connection is not open"
);
}
webSocket.send(chunk);
},
close() {
log(`remoteSocket.readable is closed, hasIncomingData: ${hasIncomingData}`);
},
abort(reason) {
console.error(
"remoteSocket.readable abort"
, reason);
}
})
).
catch
((error) => {
console.error(
`remoteSocketToWS error:`,
error.stack || error
);
safeCloseWebSocket(webSocket);
});
if
(hasIncomingData ===
false
&& retry) {
log(`retry`);
retry();
}
}
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 };
}
}
let WS_READY_STATE_OPEN = 1;
let WS_READY_STATE_CLOSING = 2;
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);
}
}
export
{
worker_default as
default
};
//# sourceMappingURL=worker.js.map
较新的博文
较旧的博文
主页
订阅:
博文 (Atom)