2018-05-13 13:51:04 +00:00
import * as plugins from './dnsly.plugins' ;
2016-11-15 20:39:21 +00:00
2019-01-06 23:28:15 +00:00
export type TDnsProvider = 'google' | 'cloudflare' ;
2020-02-15 16:41:37 +00:00
2021-08-24 09:40:44 +00:00
export const makeNodeProcessUseDnsProvider = async ( providerArg : TDnsProvider ) = > {
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]' ,
] ) ;
}
} ;
2020-02-15 16:41:37 +00:00
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
* /
2018-05-13 13:51:04 +00:00
export class Smartdns {
2020-02-15 16:41:37 +00:00
public dnsServerIp : string ;
public dnsServerPort : number ;
2020-02-15 16:46:04 +00:00
public dnsTypeMap : { [ key : string ] : number } = {
2020-02-15 16:41:37 +00:00
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
} ;
2020-02-15 16:41:37 +00:00
2017-07-18 13:45:06 +00:00
/ * *
* constructor for class dnsly
* /
2020-02-15 16:41:37 +00:00
constructor ( optionsArg : ISmartDnsConstructorOptions ) { }
2016-11-15 20:39:21 +00:00
2018-05-13 14:43:46 +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
2018-05-13 14:43:46 +00:00
* /
2020-02-15 16:41:37 +00:00
public async checkUntilAvailable (
2018-05-13 13:51:04 +00:00
recordNameArg : string ,
2020-02-15 16:41:37 +00:00
recordTypeArg : plugins.tsclass.network.TDnsRecordType ,
2019-01-06 23:53:04 +00:00
expectedValue : string ,
cyclesArg : number = 50 ,
intervalArg : number = 500
2018-05-13 13:51:04 +00:00
) {
2019-01-06 23:53:04 +00:00
let runCycles = 0 ;
2020-02-15 16:41:37 +00:00
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 ) {
myRecordArray = await this . getRecord ( recordNameArg , recordTypeArg ) ;
} else {
myRecordArray = await this . getRecordWithNodeDNS ( recordNameArg , recordTypeArg ) ;
}
2020-02-15 16:41:37 +00:00
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 } <<< `
) ;
2018-05-13 13:51:04 +00:00
return true ;
2017-07-18 13:45:06 +00:00
} else {
2019-01-06 23:53:04 +00:00
await plugins . smartdelay . delayFor ( intervalArg ) ;
2018-05-13 13:51:04 +00:00
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 ) ;
2018-05-13 13:51:04 +00:00
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 } ... `
) ;
2018-05-13 13:51:04 +00:00
return false ;
2017-07-18 13:45:06 +00:00
}
2018-05-13 13:51:04 +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
* /
2020-02-15 16:41:37 +00:00
public async getRecordA ( recordNameArg : string ) : Promise < plugins.tsclass.network.IDnsRecord [ ] > {
2018-05-13 13:51:04 +00:00
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
* /
2020-02-15 16:41:37 +00:00
public async getRecordAAAA ( recordNameArg : string ) {
2018-05-13 13:51:04 +00:00
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
* /
2020-02-15 16:41:37 +00:00
public async getRecordTxt ( recordNameArg : string ) : Promise < plugins.tsclass.network.IDnsRecord [ ] > {
return await this . getRecord ( recordNameArg , 'TXT' ) ;
}
public async getRecord (
recordNameArg : string ,
recordTypeArg : plugins.tsclass.network.TDnsRecordType
) : 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:41:37 +00:00
const response = await plugins . smartrequest . request ( requestUrl , {
2020-08-05 15:37:51 +00:00
method : 'GET' ,
headers : {
accept : 'application/dns-json' ,
} ,
2020-02-15 16:41:37 +00:00
} ) ;
2020-02-15 16:46:04 +00:00
const returnArray : plugins.tsclass.network.IDnsRecord [ ] = [ ] ;
2020-02-15 16:41:37 +00:00
const responseBody : IGoogleDNSHTTPSResponse = response . body ;
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
}
2020-02-15 16:41:37 +00:00
if ( dnsEntry . name . endsWith ( '.' ) ) {
dnsEntry . name = dnsEntry . name . substring ( 0 , dnsEntry . name . length - 1 ) ;
2017-07-18 13:45:06 +00:00
}
2020-02-15 16:41:37 +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 ,
2020-02-15 16:41:37 +00:00
} ) ;
}
// 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
/ * *
2020-02-15 16:41:37 +00:00
* gets a record using nodejs dns resolver
2017-07-18 13:45:06 +00:00
* /
2020-02-15 16:41:37 +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 ) {
2018-05-13 13:51:04 +00:00
done . reject ( err ) ;
return ;
2017-07-18 13:45:06 +00:00
}
2020-02-15 16:41:37 +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 ] ,
2020-02-15 16:41:37 +00:00
type : recordTypeArg ,
2020-08-05 15:37:51 +00:00
dnsSecEnabled : false ,
2018-05-13 13:51:04 +00:00
} ) ;
}
2020-02-15 16:41:37 +00:00
done . resolve ( returnArray ) ;
2018-05-13 13:51:04 +00:00
} ) ;
return done . promise ;
}
2020-02-15 16:41:37 +00:00
public async getNameServer ( domainNameArg : string ) : Promise < string [ ] > {
const done = plugins . smartpromise . defer < string [ ] > ( ) ;
2018-05-13 13:51:04 +00:00
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
}
2018-05-13 13:51:04 +00:00
} ) ;
2020-02-15 16:41:37 +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 {
2020-02-15 16:41:37 +00:00
return this . dnsTypeMap [ dnsTypeNameArg ] ;
}
2020-02-15 16:46:04 +00:00
public convertDnsTypeNumberToTypeName (
dnsTypeNumberArg : number
) : plugins . tsclass . network . TDnsRecordType {
2020-02-15 16:41:37 +00:00
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 ;
2020-02-15 16:41:37 +00:00
}
2017-01-26 23:11:13 +00:00
}