feat: 域名解析支持自定义 DoH(需新版前端)

This commit is contained in:
xream
2024-06-20 21:42:15 +08:00
parent a5d77c39c8
commit 32dcca4a26
7 changed files with 161 additions and 52 deletions

55
backend/src/utils/dns.js Normal file
View File

@@ -0,0 +1,55 @@
import $ from '@/core/app';
import dnsPacket from 'dns-packet';
import { Buffer } from 'buffer';
export async function doh({
url,
domain,
type = 'A',
timeout,
ip = '223.6.6.6',
}) {
const buf = dnsPacket.encode({
type: 'query',
id: 0,
flags: dnsPacket.RECURSION_DESIRED,
questions: [
{
type,
name: domain,
},
],
additionals: [
{
type: 'OPT',
name: '.',
udpPayloadSize: 4096,
flags: 0,
options: [
{
code: 'CLIENT_SUBNET',
ip,
sourcePrefixLength: 24,
scopePrefixLength: 0,
},
],
},
],
});
const res = await $.http.get({
url: `${url}?dns=${buf
.toString('base64')
.toString('utf-8')
.replace(/=/g, '')}`,
headers: {
Accept: 'application/dns-message',
// 'Content-Type': 'application/dns-message',
},
// body: buf,
'binary-mode': true,
encoding: null, // 使用 null 编码以确保响应是原始二进制数据
timeout,
});
return dnsPacket.decode(Buffer.from($.env.isQX ? res.bodyBytes : res.body));
}

View File

@@ -46,52 +46,52 @@ function getPolicyDescriptor(str) {
};
}
const utf8ArrayToStr =
typeof TextDecoder !== 'undefined'
? (v) => new TextDecoder().decode(new Uint8Array(v))
: (function () {
var charCache = new Array(128); // Preallocate the cache for the common single byte chars
var charFromCodePt = String.fromCodePoint || String.fromCharCode;
var result = [];
// const utf8ArrayToStr =
// typeof TextDecoder !== 'undefined'
// ? (v) => new TextDecoder().decode(new Uint8Array(v))
// : (function () {
// var charCache = new Array(128); // Preallocate the cache for the common single byte chars
// var charFromCodePt = String.fromCodePoint || String.fromCharCode;
// var result = [];
return function (array) {
var codePt, byte1;
var buffLen = array.length;
// return function (array) {
// var codePt, byte1;
// var buffLen = array.length;
result.length = 0;
// result.length = 0;
for (var i = 0; i < buffLen; ) {
byte1 = array[i++];
// for (var i = 0; i < buffLen; ) {
// byte1 = array[i++];
if (byte1 <= 0x7f) {
codePt = byte1;
} else if (byte1 <= 0xdf) {
codePt = ((byte1 & 0x1f) << 6) | (array[i++] & 0x3f);
} else if (byte1 <= 0xef) {
codePt =
((byte1 & 0x0f) << 12) |
((array[i++] & 0x3f) << 6) |
(array[i++] & 0x3f);
} else if (String.fromCodePoint) {
codePt =
((byte1 & 0x07) << 18) |
((array[i++] & 0x3f) << 12) |
((array[i++] & 0x3f) << 6) |
(array[i++] & 0x3f);
} else {
codePt = 63; // Cannot convert four byte code points, so use "?" instead
i += 3;
}
// if (byte1 <= 0x7f) {
// codePt = byte1;
// } else if (byte1 <= 0xdf) {
// codePt = ((byte1 & 0x1f) << 6) | (array[i++] & 0x3f);
// } else if (byte1 <= 0xef) {
// codePt =
// ((byte1 & 0x0f) << 12) |
// ((array[i++] & 0x3f) << 6) |
// (array[i++] & 0x3f);
// } else if (String.fromCodePoint) {
// codePt =
// ((byte1 & 0x07) << 18) |
// ((array[i++] & 0x3f) << 12) |
// ((array[i++] & 0x3f) << 6) |
// (array[i++] & 0x3f);
// } else {
// codePt = 63; // Cannot convert four byte code points, so use "?" instead
// i += 3;
// }
result.push(
charCache[codePt] ||
(charCache[codePt] = charFromCodePt(codePt)),
);
}
// result.push(
// charCache[codePt] ||
// (charCache[codePt] = charFromCodePt(codePt)),
// );
// }
return result.join('');
};
})();
// return result.join('');
// };
// })();
export {
isIPv4,
@@ -101,6 +101,6 @@ export {
getIfNotBlank,
isPresent,
getIfPresent,
utf8ArrayToStr,
// utf8ArrayToStr,
getPolicyDescriptor,
};