mirror of
https://github.com/lush2020/edgetunnel.git
synced 2026-03-21 08:52:43 +08:00
feat: 添加UDP处理功能,优化DNS查询逻辑
This commit is contained in:
88
_worker.js
88
_worker.js
@@ -294,14 +294,16 @@ async function 维列斯OverWSHandler(request) {
|
|||||||
value: null,
|
value: null,
|
||||||
};
|
};
|
||||||
// 标记是否为 DNS 查询
|
// 标记是否为 DNS 查询
|
||||||
|
let udpStreamWrite = null;
|
||||||
let isDns = false;
|
let isDns = false;
|
||||||
|
|
||||||
// WebSocket 数据流向远程服务器的管道
|
// WebSocket 数据流向远程服务器的管道
|
||||||
readableWebSocketStream.pipeTo(new WritableStream({
|
readableWebSocketStream.pipeTo(new WritableStream({
|
||||||
async write(chunk, controller) {
|
async write(chunk, controller) {
|
||||||
if (isDns) {
|
if (isDns && udpStreamWrite) {
|
||||||
// 如果是 DNS 查询,调用 DNS 处理函数
|
// 如果是 DNS 查询,调用 DNS 处理函数
|
||||||
return await handleDNSQuery(chunk, webSocket, null, log);
|
//return await handleDNSQuery(chunk, webSocket, null, log);
|
||||||
|
return udpStreamWrite(chunk);
|
||||||
}
|
}
|
||||||
if (remoteSocketWapper.value) {
|
if (remoteSocketWapper.value) {
|
||||||
// 如果已有远程 Socket,直接写入数据
|
// 如果已有远程 Socket,直接写入数据
|
||||||
@@ -346,7 +348,11 @@ async function 维列斯OverWSHandler(request) {
|
|||||||
|
|
||||||
if (isDns) {
|
if (isDns) {
|
||||||
// 如果是 DNS 查询,调用 DNS 处理函数
|
// 如果是 DNS 查询,调用 DNS 处理函数
|
||||||
return handleDNSQuery(rawClientData, webSocket, 维列斯ResponseHeader, log);
|
//return handleDNSQuery(rawClientData, webSocket, 维列斯ResponseHeader, log);
|
||||||
|
const { write } = await handleUDPOutBound(webSocket, 维列斯ResponseHeader, log);
|
||||||
|
udpStreamWrite = write;
|
||||||
|
udpStreamWrite(rawClientData);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
// 处理 TCP 出站连接
|
// 处理 TCP 出站连接
|
||||||
if (!banHosts.includes(addressRemote)) {
|
if (!banHosts.includes(addressRemote)) {
|
||||||
@@ -875,6 +881,78 @@ function stringify(arr, offset = 0) {
|
|||||||
return uuid;
|
return uuid;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param {import("@cloudflare/workers-types").WebSocket} webSocket
|
||||||
|
* @param {ArrayBuffer} 维列斯ResponseHeader
|
||||||
|
* @param {(string)=> void} log
|
||||||
|
*/
|
||||||
|
async function handleUDPOutBound(webSocket, 维列斯ResponseHeader, log) {
|
||||||
|
|
||||||
|
let is维列斯HeaderSent = 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 (is维列斯HeaderSent) {
|
||||||
|
webSocket.send(await new Blob([udpSizeBuffer, dnsQueryResult]).arrayBuffer());
|
||||||
|
} else {
|
||||||
|
webSocket.send(await new Blob([维列斯ResponseHeader, udpSizeBuffer, dnsQueryResult]).arrayBuffer());
|
||||||
|
is维列斯HeaderSent = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})).catch((error) => {
|
||||||
|
log('dns udp has error' + error)
|
||||||
|
});
|
||||||
|
|
||||||
|
const writer = transformStream.writable.getWriter();
|
||||||
|
|
||||||
|
return {
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param {Uint8Array} chunk
|
||||||
|
*/
|
||||||
|
write(chunk) {
|
||||||
|
writer.write(chunk);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 处理 DNS 查询的函数
|
* 处理 DNS 查询的函数
|
||||||
* @param {ArrayBuffer} udpChunk - 客户端发送的 DNS 查询数据
|
* @param {ArrayBuffer} udpChunk - 客户端发送的 DNS 查询数据
|
||||||
@@ -2409,7 +2487,7 @@ async function resolveToIPv6(target) {
|
|||||||
|
|
||||||
// 获取域名的IPv4地址
|
// 获取域名的IPv4地址
|
||||||
async function fetchIPv4(domain) {
|
async function fetchIPv4(domain) {
|
||||||
const url = `https://cloudflare-dns.com/dns-query?name=${domain}&type=A`;
|
const url = `https://1.1.1.1/dns-query?name=${domain}&type=A`;
|
||||||
const response = await fetch(url, {
|
const response = await fetch(url, {
|
||||||
headers: { 'Accept': 'application/dns-json' }
|
headers: { 'Accept': 'application/dns-json' }
|
||||||
});
|
});
|
||||||
@@ -2599,7 +2677,7 @@ async function bestIP(request, env, txt = 'ADD.txt') {
|
|||||||
'Accept': 'application/dns-json'
|
'Accept': 'application/dns-json'
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
if (response.ok) {
|
if (response.ok) {
|
||||||
const data = await response.json();
|
const data = await response.json();
|
||||||
if (data.Status === 0 && data.Answer && data.Answer.length > 0) {
|
if (data.Status === 0 && data.Answer && data.Answer.length > 0) {
|
||||||
|
|||||||
Reference in New Issue
Block a user