Comparing version 1.4.3 to 1.4.4
177
index.js
@@ -41,2 +41,15 @@ const dns = require('node:dns'); | ||
static CTYPE_BY_VALUE = { | ||
1: 'PKIX', | ||
2: 'SPKI', | ||
3: 'PGP', | ||
4: 'IPKIX', | ||
5: 'ISPKI', | ||
6: 'IPGP', | ||
7: 'ACPKIX', | ||
8: 'IACPKIX', | ||
253: 'URI', | ||
254: 'OID' | ||
}; | ||
static getAddrConfigTypes() { | ||
@@ -142,3 +155,3 @@ const networkInterfaces = os.networkInterfaces(); | ||
static TYPES = new Set([ | ||
static DNS_TYPES = new Set([ | ||
'A', | ||
@@ -157,2 +170,95 @@ 'AAAA', | ||
// <https://www.iana.org/assignments/dns-parameters/dns-parameters.xhtml#dns-parameters-4> | ||
static TYPES = new Set([ | ||
'A', | ||
'A6', | ||
'AAAA', | ||
'AFSDB', | ||
'AMTRELAY', | ||
'APL', | ||
'ATMA', | ||
'AVC', | ||
'AXFR', | ||
'CAA', | ||
'CDNSKEY', | ||
'CDS', | ||
'CERT', | ||
'CNAME', | ||
'CSYNC', | ||
'DHCID', | ||
'DLV', | ||
'DNAME', | ||
'DNSKEY', | ||
'DOA', | ||
'DS', | ||
'EID', | ||
'EUI48', | ||
'EUI64', | ||
'GID', | ||
'GPOS', | ||
'HINFO', | ||
'HIP', | ||
'HTTPS', | ||
'IPSECKEY', | ||
'ISDN', | ||
'IXFR', | ||
'KEY', | ||
'KX', | ||
'L32', | ||
'L64', | ||
'LOC', | ||
'LP', | ||
'MAILA', | ||
'MAILB', | ||
'MB', | ||
'MD', | ||
'MF', | ||
'MG', | ||
'MINFO', | ||
'MR', | ||
'MX', | ||
'NAPTR', | ||
'NID', | ||
'NIMLOC', | ||
'NINFO', | ||
'NS', | ||
'NSAP', | ||
'NSAP-PTR', | ||
'NSEC', | ||
'NSEC3', | ||
'NSEC3PARAM', | ||
'NULL', | ||
'NXT', | ||
'OPENPGPKEY', | ||
'OPT', | ||
'PTR', | ||
'PX', | ||
'RKEY', | ||
'RP', | ||
'RRSIG', | ||
'RT', | ||
'Reserved', | ||
'SIG', | ||
'SINK', | ||
'SMIMEA', | ||
'SOA', | ||
'SPF', | ||
'SRV', | ||
'SSHFP', | ||
'SVCB', | ||
'TA', | ||
'TALINK', | ||
'TKEY', | ||
'TLSA', | ||
'TSIG', | ||
'TXT', | ||
'UID', | ||
'UINFO', | ||
'UNSPEC', | ||
'URI', | ||
'WKS', | ||
'X25', | ||
'ZONEMD' | ||
]); | ||
static ANY_TYPES = [ | ||
@@ -811,2 +917,11 @@ 'A', | ||
resolveCert(name, options, abortController) { | ||
return this.resolve(name, 'CERT', options, abortController); | ||
} | ||
// NOTE: parse this properly according to spec (see below default case) | ||
resolveTlsa(name, options, abortController) { | ||
return this.resolve(name, 'TLSA', options, abortController); | ||
} | ||
// 1:1 mapping with node's official dns.promises API | ||
@@ -1393,3 +1508,3 @@ // (this means it's a drop-in replacement for `dns`) | ||
const args = [key, result, ...this.options.setCacheArgs(key, result)]; | ||
debug('setting cache', [key, result, ...args]); | ||
debug('setting cache', { args }); | ||
await this.options.cache.set(...args); | ||
@@ -1580,4 +1695,60 @@ } | ||
case 'CERT': { | ||
// CERT records `tangerine.resolveCert` | ||
// <https://github.com/jpnarkinsky/tangerine/commit/5f70954875aa93ef4acf076172d7540298b0a16b> | ||
// <https://www.rfc-editor.org/rfc/rfc4398.html> | ||
return result.answers.map((answer) => { | ||
if (!Buffer.isBuffer(answer.data)) | ||
throw new Error('Buffer was not available'); | ||
try { | ||
// <https://github.com/rthalley/dnspython/blob/98b12e9e43847dac615bb690355d2fabaff969d2/dns/rdtypes/ANY/CERT.py#L69> | ||
const obj = { | ||
name: answer.name, | ||
ttl: answer.ttl, | ||
certificate_type: answer.data.subarray(0, 2).readUInt16BE(), | ||
key_tag: answer.data.subarray(2, 4).readUInt16BE(), | ||
algorithm: answer.data.subarray(4, 5).readUInt8(), | ||
certificate: answer.data.subarray(5).toString('base64') | ||
}; | ||
obj.certificate_type = this.constructor.CTYPE_BY_VALUE[ | ||
obj.certificate_type | ||
] | ||
? this.constructor.CTYPE_BY_VALUE[obj.certificate_type] | ||
: obj.certificate_type.toString(); | ||
return obj; | ||
} catch (err) { | ||
console.error(err); | ||
throw err; | ||
} | ||
}); | ||
} | ||
case 'TLSA': { | ||
// if it returns answers with `type: TLSA` then recursively lookup | ||
// 3 1 1 D6FEA64D4E68CAEAB7CBB2E0F905D7F3CA3308B12FD88C5B469F08AD 7E05C7C7 | ||
return result.answers.map((answer) => { | ||
if (!Buffer.isBuffer(answer.data)) | ||
throw new Error('Buffer was not available'); | ||
// <https://www.mailhardener.com/kb/dane> | ||
return { | ||
name: answer.name, | ||
ttl: answer.ttl, | ||
// <https://github.com/rthalley/dnspython/blob/98b12e9e43847dac615bb690355d2fabaff969d2/dns/rdtypes/tlsabase.py#L35> | ||
usage: answer.data.subarray(0, 1).readUInt8(), | ||
selector: answer.data.subarray(1, 2).readUInt8(), | ||
mtype: answer.data.subarray(2, 3).readUInt8(), | ||
cert: answer.data.subarray(3) | ||
}; | ||
}); | ||
} | ||
default: { | ||
throw new Error(`Unknown type of ${rrtype}`); | ||
this.options.logger.error( | ||
new Error( | ||
`Submit a PR at <https://github.com/forwardemail/tangerine> with proper parsing for ${rrtype} records. You can reference <https://github.com/rthalley/dnspython/tree/master/dns/rdtypes/ANY> for inspiration.` | ||
) | ||
); | ||
return result.answers; | ||
} | ||
@@ -1584,0 +1755,0 @@ } |
{ | ||
"name": "tangerine", | ||
"description": "Tangerine is the best Node.js drop-in replacement for dns.promises.Resolver using DNS over HTTPS (\"DoH\") via undici with built-in retries, timeouts, smart server rotation, AbortControllers, and caching support for multiple backends (with TTL and purge support).", | ||
"version": "1.4.3", | ||
"version": "1.4.4", | ||
"author": "Forward Email (https://forwardemail.net)", | ||
@@ -6,0 +6,0 @@ "bugs": { |
@@ -54,2 +54,4 @@ <h1 align="center"> | ||
* [`tangerine.resolveTxt(hostname[, options, abortController]))`](#tangerineresolvetxthostname-options-abortcontroller) | ||
* [`tangerine.resolveCert(hostname, [, options, abortController]))`](#tangerineresolvecerthostname--options-abortcontroller) | ||
* [`tangerine.resolveTlsa(hostname, [, options, abortController]))`](#tangerineresolvetlsahostname--options-abortcontroller) | ||
* [`tangerine.reverse(ip[, abortController, purgeCache])`](#tangerinereverseip-abortcontroller-purgecache) | ||
@@ -160,2 +162,3 @@ * [`tangerine.setDefaultResultOrder(order)`](#tangerinesetdefaultresultorderorder) | ||
* `resolveTxt` → `queryTxt` | ||
* `resolveTsla` → `queryTsla` | ||
* `resolveSrv` → `querySrv` | ||
@@ -235,2 +238,3 @@ * `resolvePtr` → `queryPtr` | ||
* See the complete list of [Options](#options) below. | ||
* Any `rrtype` from the list at <https://www.iana.org/assignments/dns-parameters/dns-parameters.xhtml#dns-parameters-4> is supported (unlike the native Node.js DNS module which only supports a limited set). | ||
@@ -275,2 +279,54 @@ ### `tangerine.cancel()` | ||
### `tangerine.resolveCert(hostname, [, options, abortController]))` | ||
This function returns a Promise that resolves with an Array with parsed values from results: | ||
```js | ||
[ | ||
{ | ||
algorithm: 0, | ||
certificate: 'MIIEoTCCA4mgAwIBAgICAacwDQYJKoZIhvcNAQELBQAwgY0xCzAJBgNVBAYTAlVTMQswCQYDVQQIDAJNRDEOMAwGA1UEBwwFQm95ZHMxEzARBgNVBAoMCkRyYWplciBMTEMxIjAgBgNVBAMMGWludGVybWVkaWF0ZS5oZWFsdGhpdC5nb3YxKDAmBgkqhkiG9w0BCQEWGWludGVybWVkaWF0ZS5oZWFsdGhpdC5nb3YwHhcNMTgwOTI1MTgyNDIzWhcNMjgwOTIyMTgyNDIzWjB7MQswCQYDVQQGEwJVUzELMAkGA1UECAwCTUQxDjAMBgNVBAcMBUJveWRzMRMwEQYDVQQKDApEcmFqZXIgTExDMRkwFwYDVQQDDBBldHQuaGVhbHRoaXQuZ292MR8wHQYJKoZIhvcNAQkBFhBldHQuaGVhbHRoaXQuZ292MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAxaA2MIuaqpvP2Id85KIhUVA6zlj+CgZh/3prgJ1q4leP3T5F1tSSgrQ/WYTFglEwN7FJx4yJ324NaKncaMPDBIg3IUgC3Q5nrPUbIJAUgM5+67pXnGgt6s9bQelEsTdbyA/JlLC7Hsv184mqo0yrueC9NJEea4/yTV51G9S4jLjnKhr0XUTw0Fb/PFNL9ZwaEdFgQfUaE1maleazKGDyLLuEGvpXsRNs1Ju/kdHkOUVLf741Cq8qLlqOKN2v5jQkUdFUKHbYIF5KXt4ToV9mvxTaz6Mps1UbS+a73Xr+VqmBqmEQnXA5DZ7ucikzv9DLokDwtmPzhdqye2msgDpw0QIDAQABo4IBGjCCARYwCQYDVR0TBAIwADAbBgNVHREEFDASghBldHQuaGVhbHRoaXQuZ292MB0GA1UdDgQWBBQ6E22jc99mm+WraUj93IvQcw6JHDAfBgNVHSMEGDAWgBRfW20fzencvG+Attm1rcvQV+3rOTALBgNVHQ8EBAMCBaAwSQYDVR0fBEIwQDA+oDygOoY4aHR0cDovL2NhLmRpcmVjdGNhLm9yZy9jcmwvaW50ZXJtZWRpYXRlLmhlYWx0aGl0Lmdvdi5jcmwwVAYIKwYBBQUHAQEESDBGMEQGCCsGAQUFBzAChjhodHRwOi8vY2EuZGlyZWN0Y2Eub3JnL2FpYS9pbnRlcm1lZGlhdGUuaGVhbHRoaXQuZ292LmRlcjANBgkqhkiG9w0BAQsFAAOCAQEAhCASLubdxWp+XzXO4a8zMgWOMpjft+ilIy2ROVKOKslbB7lKx0NR7chrTPxCmK+YTL2ttLaTpOniw/vTGrZgeFPyXzJCNtpnx8fFipPE18OAlKMc2nyy7RfUscf28UAEmFo2cEJfpsZjyynkBsTnQ5rQVNgM7TbXXfboxwWwhg4HnWIcmlTs2YM1a9v+idK6LSfX9y/Nvhf9pl0DQflc9ym4z/XCq87erCce+11kxH1+36N6rRqeiHVBYnoYIGMH690r4cgE8cW5B4eK7kaD3iCbmpChO0gZSa5Lex49WLXeFfM+ukd9y3AB00KMZcsUV5bCgwShH053ZQa+FMON8w==', | ||
certificate_type: 'PKIX', | ||
key_tag: 0, | ||
name: 'ett.healthit.gov', | ||
ttl: 19045, | ||
}, | ||
] | ||
``` | ||
This mirrors output from <https://github.com/rthalley/dnspython>. | ||
### `tangerine.resolveTlsa(hostname, [, options, abortController]))` | ||
This method was added for DANE and TSLA support. See this [excellent article](https://www.mailhardener.com/kb/dane), [index.js](https://github.com/forwardemail/tangerine/blob/main/index.js), and <https://github.com/nodejs/node/issues/39569> for more insight. | ||
This function returns a Promise that resolves with an Array with parsed values from results: | ||
```js | ||
[ | ||
{ | ||
cert: Buffer @Uint8Array [ | ||
e1ae9c3d e848ece1 ba72e0d9 91ae4d0d 9ec547c6 bad1ddda b9d6beb0 a7e0e0d8 | ||
], | ||
mtype: 1, | ||
name: 'proloprod.mail._dane.internet.nl', | ||
selector: 1, | ||
ttl: 622, | ||
usage: 2, | ||
}, | ||
{ | ||
cert: Buffer @Uint8Array [ | ||
d6fea64d 4e68caea b7cbb2e0 f905d7f3 ca3308b1 2fd88c5b 469f08ad 7e05c7c7 | ||
], | ||
mtype: 1, | ||
name: 'proloprod.mail._dane.internet.nl', | ||
selector: 1, | ||
ttl: 622, | ||
usage: 3, | ||
}, | ||
] | ||
``` | ||
This mirrors output from <https://github.com/rthalley/dnspython>. | ||
### `tangerine.reverse(ip[, abortController, purgeCache])` | ||
@@ -277,0 +333,0 @@ |
115943
1564
684