UNPKG

@push.rocks/smartdns

Version:

A robust TypeScript library providing advanced DNS management and resolution capabilities including support for DNSSEC, custom DNS servers, and integration with various DNS providers.

285 lines 21.3 kB
import * as plugins from './plugins.js'; import { RustDnsClientBridge } from './classes.rustdnsclientbridge.js'; export const makeNodeProcessUseDnsProvider = (providerArg) => { const nodeDns = plugins.dns; if (!nodeDns) { throw new Error('Node DNS module is not available in this runtime'); } switch (providerArg) { case 'cloudflare': nodeDns.setServers([ '1.1.1.1', '1.0.0.1', '[2606:4700:4700::1111]', '[2606:4700:4700::1001]', ]); break; case 'google': nodeDns.setServers([ '8.8.8.8', '8.8.4.4', '[2001:4860:4860::8888]', '[2606:4700:4700::1001]', ]); } }; /** * Smartdns offers methods for working with DNS resolution. * Supports system resolver, UDP wire-format, and DoH (DNS-over-HTTPS) via a Rust binary. */ export class Smartdns { constructor(optionsArg) { this.strategy = 'prefer-system'; this.allowDohFallback = true; this.rustBridge = null; this.dnsTypeMap = { A: 1, NS: 2, CNAME: 5, SOA: 6, PTR: 12, MX: 15, TXT: 16, AAAA: 28, SRV: 33, }; this.strategy = optionsArg?.strategy || 'prefer-system'; this.allowDohFallback = optionsArg?.allowDohFallback === undefined ? true : optionsArg.allowDohFallback; this.timeoutMs = optionsArg?.timeoutMs; } getRustBridge() { if (!this.rustBridge) { this.rustBridge = new RustDnsClientBridge(); } return this.rustBridge; } /** * check a dns record until it has propagated */ async checkUntilAvailable(recordNameArg, recordTypeArg, expectedValue, cyclesArg = 50, intervalArg = 500) { let runCycles = 0; const doCheck = async () => { if (runCycles < cyclesArg) { runCycles++; try { let myRecordArray; if (runCycles % 2 === 0 || !plugins.dns) { myRecordArray = await this.getRecords(recordNameArg, recordTypeArg, 0); } else { myRecordArray = await this.getRecordWithNodeDNS(recordNameArg, recordTypeArg); } const myRecord = myRecordArray[0].value; if (myRecord === expectedValue) { console.log(`smartdns: .checkUntilAvailable() verified that wanted >>>${recordTypeArg}<<< record exists for >>>${recordNameArg}<<< with value >>>${expectedValue}<<<`); return true; } else { await plugins.smartdelay.delayFor(intervalArg); return await doCheck(); } } catch (err) { await plugins.smartdelay.delayFor(intervalArg); return await doCheck(); } } else { console.log(`smartdns: .checkUntilAvailable() failed permanently for ${recordNameArg} with value ${recordTypeArg} - ${expectedValue}...`); return false; } }; return await doCheck(); } /** * get A Dns Record */ async getRecordsA(recordNameArg) { return await this.getRecords(recordNameArg, 'A'); } /** * get AAAA Record */ async getRecordsAAAA(recordNameArg) { return await this.getRecords(recordNameArg, 'AAAA'); } /** * gets a txt record */ async getRecordsTxt(recordNameArg) { return await this.getRecords(recordNameArg, 'TXT'); } async getRecords(recordNameArg, recordTypeArg, retriesCounterArg = 20) { const trySystem = async () => { const nodeDns = plugins.dns; if (!nodeDns) { throw new Error('Node DNS module is not available in this runtime'); } // Prefer dns.lookup for A/AAAA so hosts file and OS resolver are honored if (recordTypeArg === 'A' || recordTypeArg === 'AAAA') { const family = recordTypeArg === 'A' ? 4 : 6; const addresses = await new Promise((resolve, reject) => { const timer = this.timeoutMs ? setTimeout(() => reject(new Error('system lookup timeout')), this.timeoutMs) : null; nodeDns.lookup(recordNameArg, { family, all: true }, (err, result) => { if (timer) clearTimeout(timer); if (err) return reject(err); resolve(result || []); }); }); return addresses.map((a) => ({ name: recordNameArg, type: recordTypeArg, dnsSecEnabled: false, value: a.address, })); } if (recordTypeArg === 'TXT') { const records = await new Promise((resolve, reject) => { const timer = this.timeoutMs ? setTimeout(() => reject(new Error('system resolveTxt timeout')), this.timeoutMs) : null; nodeDns.resolveTxt(recordNameArg, (err, res) => { if (timer) clearTimeout(timer); if (err) return reject(err); resolve(res || []); }); }); return records.map((chunks) => ({ name: recordNameArg, type: 'TXT', dnsSecEnabled: false, value: chunks.join(''), })); } return []; }; const tryRust = async (protocol) => { const bridge = this.getRustBridge(); const result = await bridge.resolve(recordNameArg, recordTypeArg, protocol, undefined, undefined, this.timeoutMs); return result.answers.map((answer) => ({ name: answer.name, type: this.convertDnsTypeNameToCanonical(answer.type) || recordTypeArg, dnsSecEnabled: result.adFlag, value: answer.value, })); }; try { if (this.strategy === 'system') { return await trySystem(); } if (this.strategy === 'doh') { return await tryRust('doh'); } if (this.strategy === 'udp') { return await tryRust('udp'); } if (this.strategy === 'prefer-udp') { try { const udpRes = await tryRust('udp'); if (udpRes.length > 0) return udpRes; return await tryRust('doh'); } catch (err) { return await tryRust('doh'); } } // prefer-system (default) try { const sysRes = await trySystem(); if (sysRes.length > 0) return sysRes; return this.allowDohFallback ? await tryRust('doh') : []; } catch (err) { return this.allowDohFallback ? await tryRust('doh') : []; } } catch (finalErr) { return []; } } /** * gets a record using nodejs dns resolver */ async getRecordWithNodeDNS(recordNameArg, recordTypeArg) { const nodeDns = plugins.dns; if (!nodeDns) { throw new Error('Node DNS module is not available in this runtime'); } const done = plugins.smartpromise.defer(); nodeDns.resolve(recordNameArg, recordTypeArg, (err, recordsArg) => { if (err) { done.reject(err); return; } const returnArray = []; for (const record of recordsArg) { const value = Array.isArray(record) ? record.join('') : String(record); returnArray.push({ name: recordNameArg, value, type: recordTypeArg, dnsSecEnabled: false, }); } done.resolve(returnArray); }); return done.promise; } async getNameServers(domainNameArg) { const nodeDns = plugins.dns; if (!nodeDns) { throw new Error('Node DNS module is not available in this runtime'); } const done = plugins.smartpromise.defer(); nodeDns.resolveNs(domainNameArg, (err, result) => { if (!err) { done.resolve(result); } else { console.log(err); done.reject(err); } }); return await done.promise; } convertDnsTypeNameToTypeNumber(dnsTypeNameArg) { return this.dnsTypeMap[dnsTypeNameArg]; } convertDnsTypeNumberToTypeName(dnsTypeNumberArg) { for (const key in this.dnsTypeMap) { if (this.dnsTypeMap[key] === dnsTypeNumberArg) { return key; } } return null; } /** * Convert a DNS type string from Rust (e.g. "A", "AAAA") to the canonical TDnsRecordType. */ convertDnsTypeNameToCanonical(typeName) { const upper = typeName.toUpperCase(); if (upper in this.dnsTypeMap) { return upper; } return null; } /** * Destroy the Rust client bridge and free resources. */ destroy() { if (this.rustBridge) { this.rustBridge.kill(); this.rustBridge = null; } } } //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2xhc3Nlcy5kbnNjbGllbnQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi90c19jbGllbnQvY2xhc3Nlcy5kbnNjbGllbnQudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxLQUFLLE9BQU8sTUFBTSxjQUFjLENBQUM7QUFDeEMsT0FBTyxFQUFFLG1CQUFtQixFQUFFLE1BQU0sa0NBQWtDLENBQUM7QUFJdkUsTUFBTSxDQUFDLE1BQU0sNkJBQTZCLEdBQUcsQ0FBQyxXQUF5QixFQUFFLEVBQUU7SUFDekUsTUFBTSxPQUFPLEdBQUcsT0FBTyxDQUFDLEdBQUcsQ0FBQztJQUM1QixJQUFJLENBQUMsT0FBTyxFQUFFLENBQUM7UUFDYixNQUFNLElBQUksS0FBSyxDQUFDLGtEQUFrRCxDQUFDLENBQUM7SUFDdEUsQ0FBQztJQUNELFFBQVEsV0FBVyxFQUFFLENBQUM7UUFDcEIsS0FBSyxZQUFZO1lBQ2YsT0FBTyxDQUFDLFVBQVUsQ0FBQztnQkFDakIsU0FBUztnQkFDVCxTQUFTO2dCQUNULHdCQUF3QjtnQkFDeEIsd0JBQXdCO2FBQ3pCLENBQUMsQ0FBQztZQUNILE1BQU07UUFDUixLQUFLLFFBQVE7WUFDWCxPQUFPLENBQUMsVUFBVSxDQUFDO2dCQUNqQixTQUFTO2dCQUNULFNBQVM7Z0JBQ1Qsd0JBQXdCO2dCQUN4Qix3QkFBd0I7YUFDekIsQ0FBQyxDQUFDO0lBQ1AsQ0FBQztBQUNILENBQUMsQ0FBQztBQVVGOzs7R0FHRztBQUNILE1BQU0sT0FBTyxRQUFRO0lBa0JuQixZQUFZLFVBQXVDO1FBakIzQyxhQUFRLEdBQXdCLGVBQWUsQ0FBQztRQUNoRCxxQkFBZ0IsR0FBRyxJQUFJLENBQUM7UUFFeEIsZUFBVSxHQUErQixJQUFJLENBQUM7UUFFL0MsZUFBVSxHQUE4QjtZQUM3QyxDQUFDLEVBQUUsQ0FBQztZQUNKLEVBQUUsRUFBRSxDQUFDO1lBQ0wsS0FBSyxFQUFFLENBQUM7WUFDUixHQUFHLEVBQUUsQ0FBQztZQUNOLEdB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