mirror of
https://github.com/lush2020/edgetunnel.git
synced 2026-03-21 08:52:43 +08:00
refactor: 优化SOCKS5握手逻辑,移除UDP处理相关代码
This commit is contained in:
127
_worker.js
127
_worker.js
@@ -306,44 +306,25 @@ function handleConnection(ws, request, FIXED_UUID) {
|
||||
let socket, writer, reader, info;
|
||||
let isFirstMsg = true, bytesReceived = 0, stallCount = 0, reconnectCount = 0;
|
||||
let lastData = Date.now();
|
||||
let udpStreamWrite = null, isDns = false;
|
||||
const timers = {};
|
||||
const dataBuffer = [];
|
||||
const earlyDataHeader = request.headers.get("sec-websocket-protocol") || "";
|
||||
async function 处理魏烈思握手(data) {
|
||||
const bytes = new Uint8Array(data);
|
||||
const 协议版本 = new Uint8Array([bytes[0], 0]);
|
||||
ws.send(new Uint8Array([bytes[0], 0]));
|
||||
if (Array.from(bytes.slice(1, 17)).map(n => n.toString(16).padStart(2, '0')).join('').replace(/(.{8})(.{4})(.{4})(.{4})(.{12})/, '$1-$2-$3-$4-$5') !== FIXED_UUID) throw new Error('Auth failed');
|
||||
const offset1 = 18 + bytes[17] + 1;
|
||||
const command = bytes[offset1];
|
||||
const port = (bytes[offset1 + 1] << 8) | bytes[offset1 + 2];
|
||||
const addrType = bytes[offset1 + 3];
|
||||
const offset2 = offset1 + 4;
|
||||
const port = (bytes[offset1] << 8) | bytes[offset1 + 1];
|
||||
const addrType = bytes[offset1 + 2];
|
||||
const offset2 = offset1 + 3;
|
||||
const { host, length } = parseAddress(bytes, offset2, addrType === 1 ? 1 : addrType === 2 ? 2 : 4);
|
||||
const payload = bytes.slice(length);
|
||||
if (host.includes(atob('c3BlZWQuY2xvdWRmbGFyZS5jb20='))) throw new Error('Access');
|
||||
|
||||
// 判断是否为UDP命令(0x02)
|
||||
const isUDP = command === 2;
|
||||
if (isUDP) {
|
||||
if (port === 53) {
|
||||
isDns = true;
|
||||
const 魏烈思响应头 = new Uint8Array([协议版本[0], 0]);
|
||||
const { write } = await handleUDPOutBound(ws, 魏烈思响应头);
|
||||
udpStreamWrite = write;
|
||||
udpStreamWrite(payload);
|
||||
return { socket: null, writer: null, reader: null, info: { host, port, isUDP: true } };
|
||||
} else {
|
||||
throw new Error('UDP proxy only enable for DNS which is port 53');
|
||||
}
|
||||
}
|
||||
|
||||
const sock = await createConnection(host, port);
|
||||
await sock.opened;
|
||||
const w = sock.writable.getWriter();
|
||||
if (payload.length) await w.write(payload);
|
||||
return { socket: sock, writer: w, reader: sock.readable.getReader(), info: { host, port, isUDP: false } };
|
||||
return { socket: sock, writer: w, reader: sock.readable.getReader(), info: { host, port } };
|
||||
}
|
||||
|
||||
async function 处理木马握手(data) {
|
||||
@@ -353,44 +334,19 @@ function handleConnection(ws, request, FIXED_UUID) {
|
||||
|
||||
const socks5Data = bytes.slice(58);
|
||||
if (socks5Data.byteLength < 6) throw new Error("invalid SOCKS5 request data");
|
||||
|
||||
const command = socks5Data[0];
|
||||
// 0x01 TCP (CONNECT)
|
||||
// 0x02 UDP
|
||||
const isUDP = command === 2;
|
||||
|
||||
if (command !== 1 && command !== 2) {
|
||||
throw new Error(`unsupported command ${command}, only TCP (CONNECT) and UDP are allowed`);
|
||||
}
|
||||
if (socks5Data[0] !== 1) throw new Error("unsupported command, only TCP (CONNECT) is allowed");
|
||||
|
||||
const { host, length } = parseAddress(socks5Data, 2, socks5Data[1]);
|
||||
if (!host) throw new Error(`address is empty, addressType is ${socks5Data[1]}`);
|
||||
if (host.includes(atob('c3BlZWQuY2xvdWRmbGFyZS5jb20='))) throw new Error('Access');
|
||||
|
||||
const port = (socks5Data[length] << 8) | socks5Data[length + 1];
|
||||
const payload = socks5Data.slice(length + 4);
|
||||
|
||||
// 处理UDP DNS请求
|
||||
if (isUDP) {
|
||||
if (port === 53) {
|
||||
isDns = true;
|
||||
// 木马协议不需要响应头,直接传入空数组
|
||||
const 木马响应头 = new Uint8Array(0);
|
||||
const { write } = await handleUDPOutBound(ws, 木马响应头);
|
||||
udpStreamWrite = write;
|
||||
if (payload.length) udpStreamWrite(payload);
|
||||
return { socket: null, writer: null, reader: null, info: { host, port, isUDP: true } };
|
||||
} else {
|
||||
throw new Error('UDP proxy only enable for DNS which is port 53');
|
||||
}
|
||||
}
|
||||
|
||||
// 处理TCP连接
|
||||
const sock = await createConnection(host, port);
|
||||
await sock.opened;
|
||||
const w = sock.writable.getWriter();
|
||||
const payload = socks5Data.slice(length + 4);
|
||||
if (payload.length) await w.write(payload);
|
||||
return { socket: sock, writer: w, reader: sock.readable.getReader(), info: { host, port, isUDP: false } };
|
||||
return { socket: sock, writer: w, reader: sock.readable.getReader(), info: { host, port } };
|
||||
}
|
||||
|
||||
async function createConnection(host, port) {
|
||||
@@ -557,18 +513,11 @@ function handleConnection(ws, request, FIXED_UUID) {
|
||||
const bytes = new Uint8Array(firstData);
|
||||
if (bytes.byteLength >= 58 && bytes[56] === 0x0d && bytes[57] === 0x0a) ({ socket, writer, reader, info } = await 处理木马握手(firstData));
|
||||
else ({ socket, writer, reader, info } = await 处理魏烈思握手(firstData));
|
||||
|
||||
// 如果是DNS UDP请求,不需要启动定时器和读取循环
|
||||
if (!isDns) {
|
||||
startTimers();
|
||||
readLoop();
|
||||
}
|
||||
startTimers();
|
||||
readLoop();
|
||||
} else {
|
||||
lastData = Date.now();
|
||||
// 处理UDP DNS数据
|
||||
if (isDns && udpStreamWrite) {
|
||||
await udpStreamWrite(evt.data);
|
||||
} else if (socket && writer) {
|
||||
if (socket && writer) {
|
||||
await writer.write(evt.data);
|
||||
} else {
|
||||
dataBuffer.push(evt.data);
|
||||
@@ -613,62 +562,6 @@ function parseAddress(bytes, offset, addrType) {
|
||||
}
|
||||
return { host, length: endOffset };
|
||||
}
|
||||
|
||||
const WS_READY_STATE_OPEN = 1;
|
||||
async function handleUDPOutBound(webSocket, 协议响应头) {
|
||||
let 响应头已发送 = false;
|
||||
const transformStream = new TransformStream({
|
||||
start(controller) { },
|
||||
transform(chunk, controller) {
|
||||
// UDP消息前2字节是UDP数据的长度
|
||||
for (let index = 0; index < chunk.byteLength;) {
|
||||
const lengthBuffer = chunk.slice(index, index + 2);
|
||||
const udpPacketLength = new DataView(lengthBuffer).getUint16(0);
|
||||
const udpData = new Uint8Array(
|
||||
chunk.slice(index + 2, index + 2 + udpPacketLength)
|
||||
);
|
||||
index = index + 2 + udpPacketLength;
|
||||
controller.enqueue(udpData);
|
||||
}
|
||||
},
|
||||
flush(controller) { }
|
||||
});
|
||||
|
||||
// 处理DNS UDP查询
|
||||
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;
|
||||
const udpSizeBuffer = new Uint8Array([(udpSize >> 8) & 0xff, udpSize & 0xff]);
|
||||
|
||||
if (webSocket.readyState === WS_READY_STATE_OPEN) {
|
||||
console.log(`DoH success and dns message length is ${udpSize}`);
|
||||
if (响应头已发送) {
|
||||
webSocket.send(await new Blob([udpSizeBuffer, dnsQueryResult]).arrayBuffer());
|
||||
} else {
|
||||
webSocket.send(await new Blob([协议响应头, udpSizeBuffer, dnsQueryResult]).arrayBuffer());
|
||||
响应头已发送 = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
})).catch((error) => {
|
||||
console.error('DNS UDP has error:', error);
|
||||
});
|
||||
const writer = transformStream.writable.getWriter();
|
||||
return {
|
||||
write(chunk) {
|
||||
writer.write(chunk);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
////////////////////////////////SOCKS5/HTTP函数///////////////////////////////////////////////
|
||||
async function httpConnect(addressRemote, portRemote) {
|
||||
const { username, password, hostname, port } = parsedSocks5Address;
|
||||
|
||||
Reference in New Issue
Block a user