浏览代码

Chore: make sure random DoH Servers are different

SukkaW 1 年之前
父节点
当前提交
65558592cb
共有 4 个文件被更改,包括 43 次插入38 次删除
  1. 26 29
      Build/lib/is-domain-alive.ts
  2. 4 3
      Build/mod.d.ts
  3. 1 1
      package.json
  4. 12 5
      pnpm-lock.yaml

+ 26 - 29
Build/lib/is-domain-alive.ts

@@ -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)];
-
-        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;
-    }
-  };
+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(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;
   }

+ 4 - 3
Build/mod.d.ts

@@ -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;
 }

+ 1 - 1
package.json

@@ -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",

+ 12 - 5
pnpm-lock.yaml

@@ -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