smartdns/ts/index.ts

227 lines
6.6 KiB
TypeScript
Raw Permalink Normal View History

2022-07-27 06:59:29 +00:00
import * as plugins from './dnsly.plugins.js';
2016-11-15 20:39:21 +00:00
2019-01-06 23:28:15 +00:00
export type TDnsProvider = 'google' | 'cloudflare';
2023-03-23 00:41:35 +00:00
export const makeNodeProcessUseDnsProvider = (providerArg: TDnsProvider) => {
2021-08-24 09:40:44 +00:00
switch (providerArg) {
case 'cloudflare':
plugins.dns.setServers([
'1.1.1.1',
'1.0.0.1',
'[2606:4700:4700::1111]',
'[2606:4700:4700::1001]',
]);
break;
case 'google':
plugins.dns.setServers([
'8.8.8.8',
'8.8.4.4',
'[2001:4860:4860::8888]',
'[2606:4700:4700::1001]',
]);
}
};
export interface ISmartDnsConstructorOptions {}
export interface IGoogleDNSHTTPSResponse {
Status: number;
TC: boolean;
RD: boolean;
RA: boolean;
AD: boolean;
CD: boolean;
2020-02-15 16:46:04 +00:00
Question: Array<{ name: string; type: number }>;
Answer: Array<{ name: string; type: number; TTL: number; data: string }>;
Additional: [];
Comment: string;
2017-01-26 23:11:13 +00:00
}
2016-11-15 20:39:21 +00:00
/**
* class dnsly offers methods for working with dns from a dns provider like Google DNS
*/
export class Smartdns {
public dnsServerIp: string;
public dnsServerPort: number;
2020-02-15 16:46:04 +00:00
public dnsTypeMap: { [key: string]: number } = {
A: 1,
AAAA: 28,
CNAME: 5,
MX: 15,
2020-08-05 15:37:51 +00:00
TXT: 16,
2020-02-15 16:46:04 +00:00
};
2017-07-18 13:45:06 +00:00
/**
* constructor for class dnsly
*/
constructor(optionsArg: ISmartDnsConstructorOptions) {}
2016-11-15 20:39:21 +00:00
/**
* check a dns record until it has propagated to Google DNS
* should be considerably fast
2019-01-06 23:21:15 +00:00
* @param recordNameArg
* @param recordTypeArg
* @param expectedValue
*/
public async checkUntilAvailable(
recordNameArg: string,
recordTypeArg: plugins.tsclass.network.TDnsRecordType,
2019-01-06 23:53:04 +00:00
expectedValue: string,
cyclesArg: number = 50,
intervalArg: number = 500
) {
2019-01-06 23:53:04 +00:00
let runCycles = 0;
const doCheck = async () => {
2019-01-06 23:53:04 +00:00
if (runCycles < cyclesArg) {
runCycles++;
2017-07-18 13:45:06 +00:00
try {
2021-01-22 23:24:02 +00:00
let myRecordArray: plugins.tsclass.network.IDnsRecord[];
if (runCycles % 2 === 0 || !plugins.dns) {
2022-07-27 09:42:01 +00:00
myRecordArray = await this.getRecord(recordNameArg, recordTypeArg, 0);
2021-01-22 23:24:02 +00:00
} else {
myRecordArray = await this.getRecordWithNodeDNS(recordNameArg, recordTypeArg);
}
const myRecord = myRecordArray[0].value;
2017-07-18 13:45:06 +00:00
if (myRecord === expectedValue) {
2020-08-05 15:37:51 +00:00
console.log(
`smartdns: .checkUntilAvailable() verified that wanted >>>${recordTypeArg}<<< record exists for >>>${recordNameArg}<<< with value >>>${expectedValue}<<<`
);
return true;
2017-07-18 13:45:06 +00:00
} else {
2019-01-06 23:53:04 +00:00
await plugins.smartdelay.delayFor(intervalArg);
return await doCheck();
2017-07-18 13:45:06 +00:00
}
} catch (err) {
2021-01-22 23:24:02 +00:00
// console.log(err);
2019-01-06 23:53:04 +00:00
await plugins.smartdelay.delayFor(intervalArg);
return await doCheck();
2017-01-26 23:11:13 +00:00
}
2017-07-18 13:45:06 +00:00
} else {
2020-02-19 21:38:42 +00:00
console.log(
`smartdns: .checkUntilAvailable() failed permanently for ${recordNameArg} with value ${recordTypeArg} - ${expectedValue}...`
);
return false;
2017-07-18 13:45:06 +00:00
}
};
return await doCheck();
2017-07-18 13:45:06 +00:00
}
2017-01-26 23:11:13 +00:00
2017-07-18 13:45:06 +00:00
/**
* get A Dns Record
*/
public async getRecordA(recordNameArg: string): Promise<plugins.tsclass.network.IDnsRecord[]> {
return await this.getRecord(recordNameArg, 'A');
2017-07-18 13:45:06 +00:00
}
2017-01-26 23:11:13 +00:00
2017-07-18 13:45:06 +00:00
/**
* get AAAA Record
*/
public async getRecordAAAA(recordNameArg: string) {
return await this.getRecord(recordNameArg, 'AAAA');
2017-07-18 13:45:06 +00:00
}
2017-01-26 23:11:13 +00:00
2017-07-18 13:45:06 +00:00
/**
* gets a txt record
*/
public async getRecordTxt(recordNameArg: string): Promise<plugins.tsclass.network.IDnsRecord[]> {
return await this.getRecord(recordNameArg, 'TXT');
}
public async getRecord(
recordNameArg: string,
2022-07-27 09:42:01 +00:00
recordTypeArg: plugins.tsclass.network.TDnsRecordType,
2023-03-23 00:41:35 +00:00
retriesCounterArg = 20
): Promise<plugins.tsclass.network.IDnsRecord[]> {
2020-08-05 15:37:51 +00:00
const requestUrl = `https://cloudflare-dns.com/dns-query?name=${recordNameArg}&type=${recordTypeArg}&do=1`;
2020-02-15 16:46:04 +00:00
const returnArray: plugins.tsclass.network.IDnsRecord[] = [];
2022-07-27 09:42:01 +00:00
const getResponseBody = async (counterArg = 0): Promise<IGoogleDNSHTTPSResponse> => {
const response = await plugins.smartrequest.request(requestUrl, {
method: 'GET',
headers: {
accept: 'application/dns-json',
},
});
const responseBody: IGoogleDNSHTTPSResponse = response.body;
if (responseBody?.Status !== 0 && counterArg < retriesCounterArg) {
await plugins.smartdelay.delayFor(500);
return getResponseBody(counterArg++);
} else {
2023-03-23 00:41:35 +00:00
return responseBody;
2022-07-27 09:42:01 +00:00
}
2023-03-23 00:41:35 +00:00
};
2022-07-27 09:42:01 +00:00
const responseBody = await getResponseBody();
for (const dnsEntry of responseBody.Answer) {
if (dnsEntry.data.startsWith('"') && dnsEntry.data.endsWith('"')) {
dnsEntry.data = dnsEntry.data.replace(/^"(.*)"$/, '$1');
2017-07-18 13:45:06 +00:00
}
if (dnsEntry.name.endsWith('.')) {
dnsEntry.name = dnsEntry.name.substring(0, dnsEntry.name.length - 1);
2017-07-18 13:45:06 +00:00
}
returnArray.push({
name: dnsEntry.name,
type: this.convertDnsTypeNumberToTypeName(dnsEntry.type),
dnsSecEnabled: responseBody.AD,
2020-08-05 15:37:51 +00:00
value: dnsEntry.data,
});
}
// console.log(responseBody);
return returnArray;
2017-07-18 13:45:06 +00:00
}
2017-01-26 23:11:13 +00:00
2017-07-18 13:45:06 +00:00
/**
* gets a record using nodejs dns resolver
2017-07-18 13:45:06 +00:00
*/
public async getRecordWithNodeDNS(
recordNameArg: string,
recordTypeArg: plugins.tsclass.network.TDnsRecordType
): Promise<plugins.tsclass.network.IDnsRecord[]> {
const done = plugins.smartpromise.defer<plugins.tsclass.network.IDnsRecord[]>();
2017-07-18 13:45:06 +00:00
plugins.dns.resolve(recordNameArg, recordTypeArg, (err, recordsArg) => {
if (err) {
done.reject(err);
return;
2017-07-18 13:45:06 +00:00
}
const returnArray: plugins.tsclass.network.IDnsRecord[] = [];
for (const recordKey in recordsArg) {
returnArray.push({
2017-07-18 13:45:06 +00:00
name: recordNameArg,
2020-02-19 21:38:42 +00:00
value: recordsArg[recordKey][0],
type: recordTypeArg,
2020-08-05 15:37:51 +00:00
dnsSecEnabled: false,
});
}
done.resolve(returnArray);
});
return done.promise;
}
public async getNameServer(domainNameArg: string): Promise<string[]> {
const done = plugins.smartpromise.defer<string[]>();
plugins.dns.resolveNs(domainNameArg, (err, result) => {
if (!err) {
done.resolve(result);
} else {
console.log(err);
done.reject(err);
2017-07-18 13:45:06 +00:00
}
});
return await done.promise;
2017-07-18 13:45:06 +00:00
}
2016-11-15 20:39:21 +00:00
2020-02-15 16:46:04 +00:00
public convertDnsTypeNameToTypeNumber(dnsTypeNameArg: string): number {
return this.dnsTypeMap[dnsTypeNameArg];
}
2020-02-15 16:46:04 +00:00
public convertDnsTypeNumberToTypeName(
dnsTypeNumberArg: number
): plugins.tsclass.network.TDnsRecordType {
for (const key in this.dnsTypeMap) {
if (this.dnsTypeMap[key] === dnsTypeNumberArg) {
return key as plugins.tsclass.network.TDnsRecordType;
}
2020-02-15 16:46:04 +00:00
}
return null;
}
2017-01-26 23:11:13 +00:00
}