feat: 添加UDP处理功能,优化DNS查询逻辑

This commit is contained in:
cmliu
2025-08-04 01:59:34 +08:00
parent bfbfd08cad
commit a834984489

View File

@@ -294,14 +294,16 @@ async function 维列斯OverWSHandler(request) {
value: null,
};
// 标记是否为 DNS 查询
let udpStreamWrite = null;
let isDns = false;
// WebSocket 数据流向远程服务器的管道
readableWebSocketStream.pipeTo(new WritableStream({
async write(chunk, controller) {
if (isDns) {
if (isDns && udpStreamWrite) {
// 如果是 DNS 查询,调用 DNS 处理函数
return await handleDNSQuery(chunk, webSocket, null, log);
//return await handleDNSQuery(chunk, webSocket, null, log);
return udpStreamWrite(chunk);
}
if (remoteSocketWapper.value) {
// 如果已有远程 Socket直接写入数据
@@ -346,7 +348,11 @@ async function 维列斯OverWSHandler(request) {
if (isDns) {
// 如果是 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 出站连接
if (!banHosts.includes(addressRemote)) {
@@ -875,6 +881,78 @@ function stringify(arr, offset = 0) {
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 查询的函数
* @param {ArrayBuffer} udpChunk - 客户端发送的 DNS 查询数据
@@ -2409,7 +2487,7 @@ async function resolveToIPv6(target) {
// 获取域名的IPv4地址
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, {
headers: { 'Accept': 'application/dns-json' }
});
@@ -2599,7 +2677,7 @@ async function bestIP(request, env, txt = 'ADD.txt') {
'Accept': 'application/dns-json'
}
});
if (response.ok) {
const data = await response.json();
if (data.Status === 0 && data.Answer && data.Answer.length > 0) {