Chore: make sure random DoH Servers are different
Some checks are pending
Build / Build (push) Waiting to run
Build / Diff output (push) Blocked by required conditions
Build / Deploy to Cloudflare Pages (push) Blocked by required conditions
Build / Deploy to GitHub and GitLab (push) Blocked by required conditions

This commit is contained in:
SukkaW 2025-02-14 23:44:02 +08:00
parent 26eb05572f
commit 65558592cb
4 changed files with 42 additions and 37 deletions

View File

@ -1,6 +1,7 @@
import tldts from 'tldts-experimental';
import { looseTldtsOpt } from '../constants/loose-tldts-opt';
import picocolors from 'picocolors';
import { pickRandom, pickOne } from 'foxts/pick-random';
import DNS2 from 'dns2';
import asyncRetry from 'async-retry';
@ -82,32 +83,27 @@ const domesticDohServers: Array<[string, DNS2.DnsResolver]> = ([
})
] as const);
function createResolve(server: Array<[string, DNS2.DnsResolver]>): DNS2.DnsResolver<DnsResponse> {
return async (...args) => {
try {
return await asyncRetry(async () => {
const [dohServer, dohClient] = server[Math.floor(Math.random() * server.length)];
async function $resolve(name: string, type: DNS2.PacketQuestion, server: [string, DNS2.DnsResolver]) {
try {
return await asyncRetry(async () => {
const [dohServer, dohClient] = server;
try {
return {
...await dohClient(...args),
dns: dohServer
} satisfies DnsResponse;
} catch (e) {
// console.error(e);
throw new DnsError((e as Error).message, dohServer);
}
}, { retries: 5 });
} catch (e) {
console.log('[doh error]', ...args, e);
throw e;
}
};
try {
return {
...await dohClient(name, type),
dns: dohServer
} satisfies DnsResponse;
} catch (e) {
// console.error(e);
throw new DnsError((e as Error).message, dohServer);
}
}, { retries: 5 });
} catch (e) {
console.log('[doh error]', name, type, e);
throw e;
}
}
const resolve = createResolve(dohServers);
const domesticResolve = createResolve(domesticDohServers);
async function getWhois(domain: string) {
return asyncRetry(() => whoiser.domain(domain, { raw: true }), { retries: 5 });
}
@ -147,9 +143,10 @@ export async function isDomainAlive(domain: string, isSuffix: boolean): Promise<
const aaaaDns: string[] = [];
// test 2 times before make sure record is empty
const servers = pickRandom(dohServers, 3);
for (let i = 0; i < 2; i++) {
// eslint-disable-next-line no-await-in-loop -- sequential
const aRecords = (await resolve($domain, 'A'));
const aRecords = (await $resolve($domain, 'A', servers[i]));
if (aRecords.answers.length > 0) {
return onDomainAlive(domain);
}
@ -158,7 +155,7 @@ export async function isDomainAlive(domain: string, isSuffix: boolean): Promise<
}
for (let i = 0; i < 2; i++) {
// eslint-disable-next-line no-await-in-loop -- sequential
const aaaaRecords = (await resolve($domain, 'AAAA'));
const aaaaRecords = (await $resolve($domain, 'AAAA', servers[i]));
if (aaaaRecords.answers.length > 0) {
return onDomainAlive(domain);
}
@ -167,13 +164,13 @@ export async function isDomainAlive(domain: string, isSuffix: boolean): Promise<
}
// only then, let's test once with domesticDohServers
const aRecords = (await domesticResolve($domain, 'A'));
const aRecords = (await $resolve($domain, 'A', pickOne(domesticDohServers)));
if (aRecords.answers.length > 0) {
return onDomainAlive(domain);
}
aDns.push(aRecords.dns);
const aaaaRecords = (await domesticResolve($domain, 'AAAA'));
const aaaaRecords = (await $resolve($domain, 'AAAA', pickOne(domesticDohServers)));
if (aaaaRecords.answers.length > 0) {
return onDomainAlive(domain);
}
@ -194,7 +191,7 @@ async function isApexDomainAlive(apexDomain: string): Promise<[string, boolean]>
if (apexDomainNsResolvePromiseMap.has(apexDomain)) {
resp = await apexDomainNsResolvePromiseMap.get(apexDomain)!;
} else {
const promise = resolve(apexDomain, 'NS');
const promise = $resolve(apexDomain, 'NS', pickOne(dohServers));
apexDomainNsResolvePromiseMap.set(apexDomain, promise);
resp = await promise;
}

7
Build/mod.d.ts vendored
View File

@ -1,9 +1,9 @@
import 'dns2';
declare module 'dns2' {
import DNS from 'dns2';
import DNS2 from 'dns2';
declare namespace DNS {
declare namespace DNS2 {
interface DoHClientOption {
/** @example dns.google.com */
dns: string,
@ -13,6 +13,7 @@ declare module 'dns2' {
get?: (url: string) => any
}
export type PacketQuestion = keyof typeof Packet.TYPE;
export type DnsResolver<T = DnsResponse> = (name: string, type: PacketQuestion) => Promise<T>;
declare function DOHClient(opt: DoHClientOption): DnsResolver;
@ -20,5 +21,5 @@ declare module 'dns2' {
export type $DnsResponse = DnsResponse;
}
export = DNS;
export = DNS2;
}

View File

@ -31,7 +31,7 @@
"fast-cidr-tools": "^0.3.1",
"fast-fifo": "^1.3.2",
"fdir": "^6.4.3",
"foxts": "^1.2.0",
"foxts": "^1.3.0",
"hash-wasm": "^4.12.0",
"json-stringify-pretty-compact": "3.0.0",
"picocolors": "^1.1.1",

17
pnpm-lock.yaml generated
View File

@ -53,8 +53,8 @@ importers:
specifier: ^6.4.3
version: 6.4.3(picomatch@4.0.2)
foxts:
specifier: ^1.2.0
version: 1.2.0
specifier: ^1.3.0
version: 1.3.0
hash-wasm:
specifier: ^4.12.0
version: 4.12.0
@ -1094,8 +1094,8 @@ packages:
resolution: {integrity: sha512-Ld2g8rrAyMYFXBhEqMz8ZAHBi4J4uS1i/CxGMDnjyFWddMXLVcDp051DZfu+t7+ab7Wv6SMqpWmyFIj5UbfFvg==}
engines: {node: '>=14'}
foxts@1.2.0:
resolution: {integrity: sha512-GQp91VeREH/fglR4KY5479nATcqnDLBWqEMhPFCD8qd48hA7DB9TD5Q9czC54j9ez9WGHjjTcbjokNWZsSI2Nw==}
foxts@1.3.0:
resolution: {integrity: sha512-TaqRKSTN6uQNFXma3jZQfH2fBqNoePlHJtEGWuaFGWI0lSpe/7UnugEpcZzKy2m5J8EVKdxJl+uPZbHGFNLntQ==}
fs-constants@1.0.0:
resolution: {integrity: sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==}
@ -1647,6 +1647,9 @@ packages:
engines: {node: '>=14.17'}
hasBin: true
uncrypto@0.1.3:
resolution: {integrity: sha512-Ql87qFHB3s/De2ClA9e0gsnS6zXG27SkTiSJwjCc9MebbfapQfuPzumMIUMi38ezPZVNFcHI9sUIepeQfw8J8Q==}
undici-cache-store-better-sqlite3@0.1.1:
resolution: {integrity: sha512-F/PxGx+QY3oScnFQ/YGbN7AYtqKLTzps0izFi8LddDaobso3SYXyQORuPcnUd2JbqpdxmLLkvS2zSvG6VPPMpw==}
peerDependencies:
@ -2780,7 +2783,9 @@ snapshots:
cross-spawn: 7.0.6
signal-exit: 4.1.0
foxts@1.2.0: {}
foxts@1.3.0:
dependencies:
uncrypto: 0.1.3
fs-constants@1.0.0: {}
@ -3349,6 +3354,8 @@ snapshots:
typescript@5.7.3: {}
uncrypto@0.1.3: {}
undici-cache-store-better-sqlite3@0.1.1(undici@7.3.0(patch_hash=594ba65c371ae78d02b8402fbad8cdc3617510f9ee2390a258e0ce5742a93926)):
dependencies:
better-sqlite3: 11.8.1