@layered/dns-records
Version:
Discover publicly available DNS Records for a domain
64 lines (63 loc) • 2.07 kB
JavaScript
import url from 'node:url';
import { spawnSync } from 'node:child_process';
/**
* Get DNS records using the `dig` command
*
* @param names The name(s) to query
* @param types The DNS type(s) to query
* @param server The DNS server to query. If not provided, the default DNS server on the network will be used
* @returns The DNS records
*/
export async function getDnsRecordsDig(names, types = 'A', server) {
// start building the arguments list for the `dig` command
const args = [];
// append @ to server if not present
if (server) {
if (!server.startsWith('@')) {
server = `@${server}`;
}
args.push(server);
}
if (!Array.isArray(names)) {
names = [names];
}
names.forEach(name => {
name = url.domainToASCII(name);
if (Array.isArray(types) && types.length) {
types.forEach(type => {
args.push(name, type);
});
}
else if (types && typeof types === 'string') {
args.push(name, types);
}
else {
args.push(name);
}
});
// +noall' // don't display any texts (authority, question, stats, etc) in response,
// +answer // except the answer
// +cdflag // no DNSSEC check, faster
// https://linux.die.net/man/1/dig
const dig = spawnSync('dig', [...args, '+noall', '+answer', '+cdflag']);
let re = dig.stdout.toString();
const dnsRecords = [];
// split lines & ignore comments or empty
re.split("\n")
.filter(line => line.length && !line.startsWith(';'))
.forEach(line => {
// replace tab(s) with space, then split by space
const parts = line.replace(/[\t]+/g, " ").split(" ");
let name = String(parts[0]);
if (name.endsWith('.')) {
name = name.slice(0, -1);
}
dnsRecords.push({
name,
ttl: Number(parts[1]),
type: String(parts[3]),
data: parts.slice(4).join(" ")
});
});
return dnsRecords;
}