dns-resolver.js•7.6 kB
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.DnsResolver = void 0;
const promises_1 = require("dns/promises");
class DnsResolver {
resolver;
config;
constructor(config) {
this.resolver = new promises_1.Resolver();
this.config = config || {
servers: ['8.8.8.8', '8.8.4.4', '1.1.1.1', '1.0.0.1'],
timeout: 5000,
retries: 2
};
if (this.config.servers && this.config.servers.length > 0) {
this.resolver.setServers(this.config.servers);
}
}
async lookup(domain, recordType, timeout) {
const startTime = Date.now();
const records = [];
try {
switch (recordType) {
case 'A':
const aRecords = await this.resolver.resolve4(domain, { ttl: true });
records.push(...aRecords.map(r => ({
type: 'A',
name: domain,
value: r.address,
ttl: r.ttl
})));
break;
case 'AAAA':
const aaaaRecords = await this.resolver.resolve6(domain, { ttl: true });
records.push(...aaaaRecords.map(r => ({
type: 'AAAA',
name: domain,
value: r.address,
ttl: r.ttl
})));
break;
case 'CNAME':
const cnameRecords = await this.resolver.resolveCname(domain);
records.push(...cnameRecords.map(r => ({
type: 'CNAME',
name: domain,
value: r
})));
break;
case 'MX':
const mxRecords = await this.resolver.resolveMx(domain);
records.push(...mxRecords.map(r => ({
type: 'MX',
name: domain,
value: r.exchange,
priority: r.priority
})));
break;
case 'TXT':
const txtRecords = await this.resolver.resolveTxt(domain);
records.push(...txtRecords.map(r => ({
type: 'TXT',
name: domain,
value: r.join('')
})));
break;
case 'NS':
const nsRecords = await this.resolver.resolveNs(domain);
records.push(...nsRecords.map(r => ({
type: 'NS',
name: domain,
value: r
})));
break;
case 'SOA':
const soaRecord = await this.resolver.resolveSoa(domain);
if (soaRecord) {
records.push({
type: 'SOA',
name: domain,
value: JSON.stringify(soaRecord)
});
}
break;
case 'PTR':
const ptrRecords = await this.resolver.resolvePtr(domain);
records.push(...ptrRecords.map(r => ({
type: 'PTR',
name: domain,
value: r
})));
break;
case 'SRV':
const srvRecords = await this.resolver.resolveSrv(domain);
records.push(...srvRecords.map(r => ({
type: 'SRV',
name: domain,
value: r.name,
priority: r.priority,
weight: r.weight,
port: r.port
})));
break;
case 'CAA':
const caaRecords = await this.resolver.resolveCaa(domain);
records.push(...caaRecords.map(r => ({
type: 'CAA',
name: domain,
value: `${r.critical ? '128' : '0'} ${r.issue || r.issuewild || r.iodef || ''}`
})));
break;
default:
throw new Error(`Unsupported record type: ${recordType}`);
}
return {
domain,
recordType,
records,
queryTime: Date.now() - startTime,
server: this.config.servers[0],
timestamp: new Date().toISOString()
};
}
catch (error) {
throw {
code: error.code || 'UNKNOWN_ERROR',
message: error.message || 'An unknown error occurred',
domain,
recordType
};
}
}
async reverseLookup(ipAddress) {
try {
return await this.resolver.reverse(ipAddress);
}
catch (error) {
throw {
code: error.code || 'REVERSE_LOOKUP_FAILED',
message: error.message || 'Reverse lookup failed',
domain: ipAddress
};
}
}
async batchLookup(queries, parallel = true) {
const results = [];
const errors = [];
const performQuery = async (domain, recordType) => {
try {
const result = await this.lookup(domain, recordType);
results.push(result);
}
catch (error) {
errors.push(error);
}
};
const allQueries = queries.flatMap(q => q.recordTypes.map(rt => ({ domain: q.domain, recordType: rt })));
if (parallel) {
await Promise.all(allQueries.map(q => performQuery(q.domain, q.recordType)));
}
else {
for (const q of allQueries) {
await performQuery(q.domain, q.recordType);
}
}
return { results, errors };
}
async traceDns(domain, recordType = 'A') {
const trace = [];
try {
const rootServers = await this.resolver.resolveNs('.');
trace.push({ level: 'root', servers: rootServers });
const parts = domain.split('.').reverse();
let currentDomain = '';
for (const part of parts) {
currentDomain = currentDomain ? `${part}.${currentDomain}` : part;
try {
const nsRecords = await this.resolver.resolveNs(currentDomain);
trace.push({ level: currentDomain, servers: nsRecords });
}
catch (error) {
break;
}
}
const finalResult = await this.lookup(domain, recordType);
trace.push({ level: 'final', result: finalResult });
return trace;
}
catch (error) {
throw {
code: 'TRACE_FAILED',
message: error.message || 'DNS trace failed',
domain,
recordType
};
}
}
updateServers(servers) {
this.config.servers = servers;
this.resolver.setServers(servers);
}
}
exports.DnsResolver = DnsResolver;
//# sourceMappingURL=dns-resolver.js.map