domain-alive 0.1.12 → 0.1.14
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +1798 -8
- package/dist/index.mjs +1786 -6
- package/package.json +9 -9
package/dist/index.js
CHANGED
|
@@ -1,20 +1,1808 @@
|
|
|
1
1
|
Object.defineProperty(exports, '__esModule', { value: true });
|
|
2
2
|
|
|
3
3
|
var tldts = require('tldts');
|
|
4
|
-
var
|
|
4
|
+
var require$$0$1 = require('dgram');
|
|
5
|
+
var require$$0 = require('util');
|
|
6
|
+
var require$$0$2 = require('net');
|
|
7
|
+
var require$$0$3 = require('http');
|
|
8
|
+
var require$$1 = require('https');
|
|
9
|
+
var require$$2 = require('url');
|
|
10
|
+
var require$$4 = require('events');
|
|
11
|
+
var require$$0$4 = require('tls');
|
|
12
|
+
var require$$2$1 = require('http2');
|
|
13
|
+
var require$$2$2 = require('assert');
|
|
5
14
|
var asyncRetry = require('foxts/async-retry');
|
|
6
15
|
var net = require('node:net');
|
|
7
16
|
var retrie = require('foxts/retrie');
|
|
8
17
|
var extractErrorMessage = require('foxts/extract-error-message');
|
|
9
18
|
var debug = require('debug');
|
|
10
19
|
var shuffleArray = require('foxts/shuffle-array');
|
|
11
|
-
var url = require('url');
|
|
12
20
|
|
|
13
21
|
function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
|
|
14
22
|
|
|
23
|
+
var require$$0__default$1 = /*#__PURE__*/_interopDefault(require$$0$1);
|
|
24
|
+
var require$$0__default = /*#__PURE__*/_interopDefault(require$$0);
|
|
25
|
+
var require$$0__default$2 = /*#__PURE__*/_interopDefault(require$$0$2);
|
|
26
|
+
var require$$0__default$3 = /*#__PURE__*/_interopDefault(require$$0$3);
|
|
27
|
+
var require$$1__default = /*#__PURE__*/_interopDefault(require$$1);
|
|
28
|
+
var require$$2__default = /*#__PURE__*/_interopDefault(require$$2);
|
|
29
|
+
var require$$4__default = /*#__PURE__*/_interopDefault(require$$4);
|
|
30
|
+
var require$$0__default$4 = /*#__PURE__*/_interopDefault(require$$0$4);
|
|
31
|
+
var require$$2__default$1 = /*#__PURE__*/_interopDefault(require$$2$1);
|
|
32
|
+
var require$$2__default$2 = /*#__PURE__*/_interopDefault(require$$2$2);
|
|
15
33
|
var net__default = /*#__PURE__*/_interopDefault(net);
|
|
16
34
|
var debug__default = /*#__PURE__*/_interopDefault(debug);
|
|
17
35
|
|
|
36
|
+
var packet = {exports: {}};
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* [Reader description]
|
|
40
|
+
* @param {[type]} buffer [description]
|
|
41
|
+
* @param {[type]} offset [description]
|
|
42
|
+
*/
|
|
43
|
+
|
|
44
|
+
var reader;
|
|
45
|
+
var hasRequiredReader;
|
|
46
|
+
|
|
47
|
+
function requireReader () {
|
|
48
|
+
if (hasRequiredReader) return reader;
|
|
49
|
+
hasRequiredReader = 1;
|
|
50
|
+
function BufferReader(buffer, offset) {
|
|
51
|
+
this.buffer = buffer;
|
|
52
|
+
this.offset = offset || 0;
|
|
53
|
+
return this;
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* [read description]
|
|
57
|
+
* @param {[type]} buffer [description]
|
|
58
|
+
* @param {[type]} offset [description]
|
|
59
|
+
* @param {[type]} length [description]
|
|
60
|
+
* @return {[type]} [description]
|
|
61
|
+
*/ BufferReader.read = function(buffer, offset, length) {
|
|
62
|
+
let a = [];
|
|
63
|
+
let c = Math.ceil(length / 8);
|
|
64
|
+
let l = Math.floor(offset / 8);
|
|
65
|
+
const m = offset % 8;
|
|
66
|
+
function t(n) {
|
|
67
|
+
const r = [
|
|
68
|
+
0,
|
|
69
|
+
0,
|
|
70
|
+
0,
|
|
71
|
+
0,
|
|
72
|
+
0,
|
|
73
|
+
0,
|
|
74
|
+
0,
|
|
75
|
+
0
|
|
76
|
+
];
|
|
77
|
+
for(let i = 7; i >= 0; i--){
|
|
78
|
+
r[7 - i] = n & Math.pow(2, i) ? 1 : 0;
|
|
79
|
+
}
|
|
80
|
+
a = a.concat(r);
|
|
81
|
+
}
|
|
82
|
+
function p(a) {
|
|
83
|
+
let n = 0;
|
|
84
|
+
const f = a.length - 1;
|
|
85
|
+
for(let i = f; i >= 0; i--){
|
|
86
|
+
if (a[f - i]) n += Math.pow(2, i);
|
|
87
|
+
}
|
|
88
|
+
return n;
|
|
89
|
+
}
|
|
90
|
+
while(c--)t(buffer.readUInt8(l++));
|
|
91
|
+
return p(a.slice(m, m + length));
|
|
92
|
+
};
|
|
93
|
+
/**
|
|
94
|
+
* [read description]
|
|
95
|
+
* @param {[type]} size [description]
|
|
96
|
+
* @return {[type]} [description]
|
|
97
|
+
*/ BufferReader.prototype.read = function(size) {
|
|
98
|
+
const val = BufferReader.read(this.buffer, this.offset, size);
|
|
99
|
+
this.offset += size;
|
|
100
|
+
return val;
|
|
101
|
+
};
|
|
102
|
+
reader = BufferReader;
|
|
103
|
+
return reader;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
/**
|
|
107
|
+
* [Writer description]
|
|
108
|
+
*/
|
|
109
|
+
|
|
110
|
+
var writer;
|
|
111
|
+
var hasRequiredWriter;
|
|
112
|
+
|
|
113
|
+
function requireWriter () {
|
|
114
|
+
if (hasRequiredWriter) return writer;
|
|
115
|
+
hasRequiredWriter = 1;
|
|
116
|
+
function BufferWriter() {
|
|
117
|
+
this.buffer = [];
|
|
118
|
+
}
|
|
119
|
+
/**
|
|
120
|
+
* [write description]
|
|
121
|
+
* @param {[type]} d [description]
|
|
122
|
+
* @param {[type]} size [description]
|
|
123
|
+
* @return {[type]} [description]
|
|
124
|
+
*/ BufferWriter.prototype.write = function(d, size) {
|
|
125
|
+
for(let i = 0; i < size; i++){
|
|
126
|
+
this.buffer.push(d & Math.pow(2, size - i - 1) ? 1 : 0);
|
|
127
|
+
}
|
|
128
|
+
};
|
|
129
|
+
/**
|
|
130
|
+
* [writeBuffer description]
|
|
131
|
+
* @param {[type]} b [description]
|
|
132
|
+
*/ BufferWriter.prototype.writeBuffer = function(b) {
|
|
133
|
+
this.buffer = this.buffer.concat(b.buffer);
|
|
134
|
+
};
|
|
135
|
+
/**
|
|
136
|
+
* [toBuffer description]
|
|
137
|
+
* @return {[type]} [description]
|
|
138
|
+
*/ BufferWriter.prototype.toBuffer = function() {
|
|
139
|
+
const arr = [];
|
|
140
|
+
for(let i = 0; i < this.buffer.length; i += 8){
|
|
141
|
+
const chunk = this.buffer.slice(i, i + 8);
|
|
142
|
+
arr.push(parseInt(chunk.join(''), 2));
|
|
143
|
+
}
|
|
144
|
+
return Buffer.from(arr);
|
|
145
|
+
};
|
|
146
|
+
writer = BufferWriter;
|
|
147
|
+
return writer;
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
var hasRequiredPacket;
|
|
151
|
+
|
|
152
|
+
function requirePacket () {
|
|
153
|
+
if (hasRequiredPacket) return packet.exports;
|
|
154
|
+
hasRequiredPacket = 1;
|
|
155
|
+
const { debuglog } = require$$0__default.default;
|
|
156
|
+
const BufferReader = requireReader();
|
|
157
|
+
const BufferWriter = requireWriter();
|
|
158
|
+
const debug = debuglog('dns2');
|
|
159
|
+
const toIPv6 = (buffer)=>buffer.map((part)=>part > 0 ? part.toString(16) : '0').join(':').replace(/\b(?:0+:){1,}/, ':');
|
|
160
|
+
const fromIPv6 = (address)=>{
|
|
161
|
+
const digits = address.split(':');
|
|
162
|
+
// CAVEAT edge case for :: and IPs starting
|
|
163
|
+
// or ending by ::
|
|
164
|
+
if (digits[0] === '') {
|
|
165
|
+
digits.shift();
|
|
166
|
+
}
|
|
167
|
+
if (digits[digits.length - 1] === '') {
|
|
168
|
+
digits.pop();
|
|
169
|
+
}
|
|
170
|
+
// node js 10 does not support Array.prototype.flatMap
|
|
171
|
+
if (!Array.prototype.flatMap) {
|
|
172
|
+
// eslint-disable-next-line no-extend-native
|
|
173
|
+
Array.prototype.flatMap = function(f, ctx) {
|
|
174
|
+
return this.reduce((r, x, i, a)=>r.concat(f.call(ctx, x, i, a)), []);
|
|
175
|
+
};
|
|
176
|
+
}
|
|
177
|
+
// CAVEAT we have to take into account
|
|
178
|
+
// the extra space used by the empty string
|
|
179
|
+
const missingFields = 8 - digits.length + 1;
|
|
180
|
+
return digits.flatMap((digit)=>{
|
|
181
|
+
if (digit === '') {
|
|
182
|
+
return Array(missingFields).fill('0');
|
|
183
|
+
}
|
|
184
|
+
return digit.padStart(4, '0');
|
|
185
|
+
});
|
|
186
|
+
};
|
|
187
|
+
/**
|
|
188
|
+
* [Packet description]
|
|
189
|
+
* @param {[type]} data [description]
|
|
190
|
+
* @docs https://tools.ietf.org/html/rfc1034
|
|
191
|
+
* @docs https://tools.ietf.org/html/rfc1035
|
|
192
|
+
*
|
|
193
|
+
* <Buffer 29 64 01 00 00 01 00 00 00 00 00 00
|
|
194
|
+
* |-ID----------- HEADER ----------->|
|
|
195
|
+
*
|
|
196
|
+
* 03 77 77 77 01 7a 02 63 6e 00 00 01 00 01>
|
|
197
|
+
* <-W--W--W-----Z-----C--N>|<----------->|
|
|
198
|
+
*/ function Packet(data) {
|
|
199
|
+
this.header = {};
|
|
200
|
+
this.questions = [];
|
|
201
|
+
this.answers = [];
|
|
202
|
+
this.authorities = [];
|
|
203
|
+
this.additionals = [];
|
|
204
|
+
if (data instanceof Packet) {
|
|
205
|
+
return data;
|
|
206
|
+
} else if (data instanceof Packet.Header) {
|
|
207
|
+
this.header = data;
|
|
208
|
+
} else if (data instanceof Packet.Question) {
|
|
209
|
+
this.questions.push(data);
|
|
210
|
+
} else if (data instanceof Packet.Resource) {
|
|
211
|
+
this.answers.push(data);
|
|
212
|
+
} else if (typeof data === 'string') {
|
|
213
|
+
this.questions.push(data);
|
|
214
|
+
} else if (typeof data === 'object') {
|
|
215
|
+
const type = ({}).toString.call(data).match(/\[object (\w+)\]/)[1];
|
|
216
|
+
if (type === 'Array') {
|
|
217
|
+
this.questions = data;
|
|
218
|
+
}
|
|
219
|
+
if (type === 'Object') {
|
|
220
|
+
this.header = data;
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
return this;
|
|
224
|
+
}
|
|
225
|
+
/**
|
|
226
|
+
* [QUERY_TYPE description]
|
|
227
|
+
* @type {Object}
|
|
228
|
+
* @docs https://tools.ietf.org/html/rfc1035#section-3.2.2
|
|
229
|
+
*/ Packet.TYPE = {
|
|
230
|
+
A: 0x01,
|
|
231
|
+
NS: 0x02,
|
|
232
|
+
MD: 0x03,
|
|
233
|
+
MF: 0x04,
|
|
234
|
+
CNAME: 0x05,
|
|
235
|
+
SOA: 0x06,
|
|
236
|
+
MB: 0x07,
|
|
237
|
+
MG: 0x08,
|
|
238
|
+
MR: 0x09,
|
|
239
|
+
NULL: 0x0A,
|
|
240
|
+
WKS: 0x0B,
|
|
241
|
+
PTR: 0x0C,
|
|
242
|
+
HINFO: 0x0D,
|
|
243
|
+
MINFO: 0x0E,
|
|
244
|
+
MX: 0x0F,
|
|
245
|
+
TXT: 0x10,
|
|
246
|
+
AAAA: 0x1C,
|
|
247
|
+
SRV: 0x21,
|
|
248
|
+
EDNS: 0x29,
|
|
249
|
+
SPF: 0x63,
|
|
250
|
+
AXFR: 0xFC,
|
|
251
|
+
MAILB: 0xFD,
|
|
252
|
+
MAILA: 0xFE,
|
|
253
|
+
ANY: 0xFF,
|
|
254
|
+
CAA: 0x101,
|
|
255
|
+
DNSKEY: 0x30
|
|
256
|
+
};
|
|
257
|
+
/**
|
|
258
|
+
* [QUERY_CLASS description]
|
|
259
|
+
* @type {Object}
|
|
260
|
+
* @docs https://tools.ietf.org/html/rfc1035#section-3.2.4
|
|
261
|
+
*/ Packet.CLASS = {
|
|
262
|
+
IN: 0x01,
|
|
263
|
+
CS: 0x02,
|
|
264
|
+
CH: 0x03,
|
|
265
|
+
HS: 0x04,
|
|
266
|
+
ANY: 0xFF
|
|
267
|
+
};
|
|
268
|
+
/**
|
|
269
|
+
* [EDNS_OPTION_CODE description]
|
|
270
|
+
* @type {Object}
|
|
271
|
+
* @docs https://tools.ietf.org/html/rfc6891#section-6.1.2
|
|
272
|
+
*/ Packet.EDNS_OPTION_CODE = {
|
|
273
|
+
ECS: 0x08
|
|
274
|
+
};
|
|
275
|
+
/**
|
|
276
|
+
* [uuid description]
|
|
277
|
+
* @return {[type]} [description]
|
|
278
|
+
*/ Packet.uuid = function() {
|
|
279
|
+
return Math.floor(Math.random() * 1e5);
|
|
280
|
+
};
|
|
281
|
+
/**
|
|
282
|
+
* [parse description]
|
|
283
|
+
* @param {[type]} buffer [description]
|
|
284
|
+
* @return {[type]} [description]
|
|
285
|
+
*/ Packet.parse = function(buffer) {
|
|
286
|
+
const packet = new Packet();
|
|
287
|
+
const reader = new Packet.Reader(buffer);
|
|
288
|
+
packet.header = Packet.Header.parse(reader);
|
|
289
|
+
[
|
|
290
|
+
[
|
|
291
|
+
'questions',
|
|
292
|
+
Packet.Question,
|
|
293
|
+
packet.header.qdcount
|
|
294
|
+
],
|
|
295
|
+
[
|
|
296
|
+
'answers',
|
|
297
|
+
Packet.Resource,
|
|
298
|
+
packet.header.ancount
|
|
299
|
+
],
|
|
300
|
+
[
|
|
301
|
+
'authorities',
|
|
302
|
+
Packet.Resource,
|
|
303
|
+
packet.header.nscount
|
|
304
|
+
],
|
|
305
|
+
[
|
|
306
|
+
'additionals',
|
|
307
|
+
Packet.Resource,
|
|
308
|
+
packet.header.arcount
|
|
309
|
+
]
|
|
310
|
+
].forEach(function(def) {
|
|
311
|
+
const section = def[0];
|
|
312
|
+
const decoder = def[1];
|
|
313
|
+
let count = def[2];
|
|
314
|
+
while(count--){
|
|
315
|
+
try {
|
|
316
|
+
packet[section] = packet[section] || [];
|
|
317
|
+
packet[section].push(decoder.parse(reader));
|
|
318
|
+
} catch (e) {
|
|
319
|
+
debug('node-dns > parse %s error:', section, e.message);
|
|
320
|
+
}
|
|
321
|
+
}
|
|
322
|
+
});
|
|
323
|
+
return packet;
|
|
324
|
+
};
|
|
325
|
+
/**
|
|
326
|
+
* recursive
|
|
327
|
+
*/ Object.defineProperty(Packet.prototype, 'recursive', {
|
|
328
|
+
enumerable: true,
|
|
329
|
+
configurable: true,
|
|
330
|
+
get () {
|
|
331
|
+
return !!this.header.rd;
|
|
332
|
+
},
|
|
333
|
+
set (yn) {
|
|
334
|
+
this.header.rd = +yn;
|
|
335
|
+
return this.header.rd;
|
|
336
|
+
}
|
|
337
|
+
});
|
|
338
|
+
/**
|
|
339
|
+
* [toBuffer description]
|
|
340
|
+
* @return {[type]} [description]
|
|
341
|
+
*/ Packet.prototype.toBuffer = function(writer) {
|
|
342
|
+
writer = writer || new Packet.Writer();
|
|
343
|
+
this.header.qdcount = this.questions.length;
|
|
344
|
+
this.header.ancount = this.answers.length;
|
|
345
|
+
this.header.nscount = this.authorities.length;
|
|
346
|
+
this.header.arcount = this.additionals.length;
|
|
347
|
+
if (!(this instanceof Packet.Header)) {
|
|
348
|
+
this.header = new Packet.Header(this.header);
|
|
349
|
+
}
|
|
350
|
+
this.header.toBuffer(writer);
|
|
351
|
+
[
|
|
352
|
+
[
|
|
353
|
+
'questions',
|
|
354
|
+
Packet.Question
|
|
355
|
+
],
|
|
356
|
+
[
|
|
357
|
+
'answers',
|
|
358
|
+
Packet.Resource
|
|
359
|
+
],
|
|
360
|
+
[
|
|
361
|
+
'authorities',
|
|
362
|
+
Packet.Resource
|
|
363
|
+
],
|
|
364
|
+
[
|
|
365
|
+
'additionals',
|
|
366
|
+
Packet.Resource
|
|
367
|
+
]
|
|
368
|
+
].forEach((function(def) {
|
|
369
|
+
const section = def[0];
|
|
370
|
+
const Encoder = def[1];
|
|
371
|
+
(this[section] || []).map(function(resource) {
|
|
372
|
+
return Encoder.encode(resource, writer);
|
|
373
|
+
});
|
|
374
|
+
}).bind(this));
|
|
375
|
+
return writer.toBuffer();
|
|
376
|
+
};
|
|
377
|
+
/**
|
|
378
|
+
* [Header description]
|
|
379
|
+
* @param {[type]} options [description]
|
|
380
|
+
* @docs https://tools.ietf.org/html/rfc1035#section-4.1.1
|
|
381
|
+
*/ Packet.Header = function(header) {
|
|
382
|
+
this.id = 0;
|
|
383
|
+
this.qr = 0;
|
|
384
|
+
this.opcode = 0;
|
|
385
|
+
this.aa = 0;
|
|
386
|
+
this.tc = 0;
|
|
387
|
+
this.rd = 0;
|
|
388
|
+
this.ra = 0;
|
|
389
|
+
this.z = 0;
|
|
390
|
+
this.rcode = 0;
|
|
391
|
+
this.qdcount = 0;
|
|
392
|
+
this.nscount = 0;
|
|
393
|
+
this.arcount = 0;
|
|
394
|
+
for(const k in header){
|
|
395
|
+
this[k] = header[k];
|
|
396
|
+
}
|
|
397
|
+
return this;
|
|
398
|
+
};
|
|
399
|
+
/**
|
|
400
|
+
* [parse description]
|
|
401
|
+
* @param {[type]} buffer [description]
|
|
402
|
+
* @return {[type]} [description]
|
|
403
|
+
* @docs https://tools.ietf.org/html/rfc1035#section-4.1.1
|
|
404
|
+
*/ Packet.Header.parse = function(reader) {
|
|
405
|
+
const header = new Packet.Header();
|
|
406
|
+
if (reader instanceof Buffer) {
|
|
407
|
+
reader = new Packet.Reader(reader);
|
|
408
|
+
}
|
|
409
|
+
header.id = reader.read(16);
|
|
410
|
+
header.qr = reader.read(1);
|
|
411
|
+
header.opcode = reader.read(4);
|
|
412
|
+
header.aa = reader.read(1);
|
|
413
|
+
header.tc = reader.read(1);
|
|
414
|
+
header.rd = reader.read(1);
|
|
415
|
+
header.ra = reader.read(1);
|
|
416
|
+
header.z = reader.read(3);
|
|
417
|
+
header.rcode = reader.read(4);
|
|
418
|
+
header.qdcount = reader.read(16);
|
|
419
|
+
header.ancount = reader.read(16);
|
|
420
|
+
header.nscount = reader.read(16);
|
|
421
|
+
header.arcount = reader.read(16);
|
|
422
|
+
return header;
|
|
423
|
+
};
|
|
424
|
+
/**
|
|
425
|
+
* [toBuffer description]
|
|
426
|
+
* @return {[type]} [description]
|
|
427
|
+
*/ Packet.Header.prototype.toBuffer = function(writer) {
|
|
428
|
+
writer = writer || new Packet.Writer();
|
|
429
|
+
writer.write(this.id, 16);
|
|
430
|
+
writer.write(this.qr, 1);
|
|
431
|
+
writer.write(this.opcode, 4);
|
|
432
|
+
writer.write(this.aa, 1);
|
|
433
|
+
writer.write(this.tc, 1);
|
|
434
|
+
writer.write(this.rd, 1);
|
|
435
|
+
writer.write(this.ra, 1);
|
|
436
|
+
writer.write(this.z, 3);
|
|
437
|
+
writer.write(this.rcode, 4);
|
|
438
|
+
writer.write(this.qdcount, 16);
|
|
439
|
+
writer.write(this.ancount, 16);
|
|
440
|
+
writer.write(this.nscount, 16);
|
|
441
|
+
writer.write(this.arcount, 16);
|
|
442
|
+
return writer.toBuffer();
|
|
443
|
+
};
|
|
444
|
+
/**
|
|
445
|
+
* Question section format
|
|
446
|
+
* @docs https://tools.ietf.org/html/rfc1035#section-4.1.2
|
|
447
|
+
*/ Packet.Question = function(name, type, cls) {
|
|
448
|
+
const defaults = {
|
|
449
|
+
type: Packet.TYPE.ANY,
|
|
450
|
+
class: Packet.CLASS.ANY
|
|
451
|
+
};
|
|
452
|
+
if (typeof name === 'object') {
|
|
453
|
+
for(const k in name){
|
|
454
|
+
this[k] = name[k] || defaults[k];
|
|
455
|
+
}
|
|
456
|
+
} else {
|
|
457
|
+
this.name = name;
|
|
458
|
+
this.type = type || defaults.type;
|
|
459
|
+
this.class = cls || defaults.class;
|
|
460
|
+
}
|
|
461
|
+
return this;
|
|
462
|
+
};
|
|
463
|
+
/**
|
|
464
|
+
* [toBuffer description]
|
|
465
|
+
* @param {[type]} writer [description]
|
|
466
|
+
* @return {[type]} [description]
|
|
467
|
+
*/ Packet.Question.prototype.toBuffer = function(writer) {
|
|
468
|
+
return Packet.Question.encode(this, writer);
|
|
469
|
+
};
|
|
470
|
+
/**
|
|
471
|
+
* [parse description]
|
|
472
|
+
* @param {[type]} reader [description]
|
|
473
|
+
* @return {[type]} [description]
|
|
474
|
+
*/ Packet.Question.parse = Packet.Question.decode = function(reader) {
|
|
475
|
+
const question = new Packet.Question();
|
|
476
|
+
if (reader instanceof Buffer) {
|
|
477
|
+
reader = new Packet.Reader(reader);
|
|
478
|
+
}
|
|
479
|
+
question.name = Packet.Name.decode(reader);
|
|
480
|
+
question.type = reader.read(16);
|
|
481
|
+
question.class = reader.read(16);
|
|
482
|
+
return question;
|
|
483
|
+
};
|
|
484
|
+
Packet.Question.encode = function(question, writer) {
|
|
485
|
+
writer = writer || new Packet.Writer();
|
|
486
|
+
Packet.Name.encode(question.name, writer);
|
|
487
|
+
writer.write(question.type, 16);
|
|
488
|
+
writer.write(question.class, 16);
|
|
489
|
+
return writer.toBuffer();
|
|
490
|
+
};
|
|
491
|
+
/**
|
|
492
|
+
* Resource record format
|
|
493
|
+
* @docs https://tools.ietf.org/html/rfc1035#section-4.1.3
|
|
494
|
+
*/ Packet.Resource = function(name, type, cls, ttl) {
|
|
495
|
+
const defaults = {
|
|
496
|
+
name: '',
|
|
497
|
+
ttl: 300,
|
|
498
|
+
type: Packet.TYPE.ANY,
|
|
499
|
+
class: Packet.CLASS.ANY
|
|
500
|
+
};
|
|
501
|
+
let input;
|
|
502
|
+
if (typeof name === 'object') {
|
|
503
|
+
input = name;
|
|
504
|
+
} else {
|
|
505
|
+
input = {
|
|
506
|
+
name,
|
|
507
|
+
type,
|
|
508
|
+
class: cls,
|
|
509
|
+
ttl
|
|
510
|
+
};
|
|
511
|
+
}
|
|
512
|
+
Object.assign(this, defaults, input);
|
|
513
|
+
return this;
|
|
514
|
+
};
|
|
515
|
+
/**
|
|
516
|
+
* [toBuffer description]
|
|
517
|
+
* @param {[type]} writer [description]
|
|
518
|
+
* @return {[type]} [description]
|
|
519
|
+
*/ Packet.Resource.prototype.toBuffer = function(writer) {
|
|
520
|
+
return Packet.Resource.encode(this, writer);
|
|
521
|
+
};
|
|
522
|
+
/**
|
|
523
|
+
* [encode description]
|
|
524
|
+
* @param {[type]} resource [description]
|
|
525
|
+
* @param {[type]} writer [description]
|
|
526
|
+
* @return {[type]} [description]
|
|
527
|
+
*/ Packet.Resource.encode = function(resource, writer) {
|
|
528
|
+
writer = writer || new Packet.Writer();
|
|
529
|
+
Packet.Name.encode(resource.name, writer);
|
|
530
|
+
writer.write(resource.type, 16);
|
|
531
|
+
writer.write(resource.class, 16);
|
|
532
|
+
writer.write(resource.ttl, 32);
|
|
533
|
+
const encoder = Object.keys(Packet.TYPE).filter(function(type) {
|
|
534
|
+
return resource.type === Packet.TYPE[type];
|
|
535
|
+
})[0];
|
|
536
|
+
if (encoder in Packet.Resource && Packet.Resource[encoder].encode) {
|
|
537
|
+
return Packet.Resource[encoder].encode(resource, writer);
|
|
538
|
+
} else {
|
|
539
|
+
debug('node-dns > unknown encoder %s(%j)', encoder, resource.type);
|
|
540
|
+
}
|
|
541
|
+
};
|
|
542
|
+
/**
|
|
543
|
+
* [parse description]
|
|
544
|
+
* @param {[type]} reader [description]
|
|
545
|
+
* @return {[type]} [description]
|
|
546
|
+
*/ Packet.Resource.parse = Packet.Resource.decode = function(reader) {
|
|
547
|
+
if (reader instanceof Buffer) {
|
|
548
|
+
reader = new Packet.Reader(reader);
|
|
549
|
+
}
|
|
550
|
+
let resource = new Packet.Resource();
|
|
551
|
+
resource.name = Packet.Name.decode(reader);
|
|
552
|
+
resource.type = reader.read(16);
|
|
553
|
+
resource.class = reader.read(16);
|
|
554
|
+
resource.ttl = reader.read(32);
|
|
555
|
+
let length = reader.read(16);
|
|
556
|
+
const parser = Object.keys(Packet.TYPE).filter(function(type) {
|
|
557
|
+
return resource.type === Packet.TYPE[type];
|
|
558
|
+
})[0];
|
|
559
|
+
if (parser in Packet.Resource) {
|
|
560
|
+
resource = Packet.Resource[parser].decode.call(resource, reader, length);
|
|
561
|
+
} else {
|
|
562
|
+
debug('node-dns > unknown parser type: %s(%j)', parser, resource.type);
|
|
563
|
+
const arr = [];
|
|
564
|
+
while(length--)arr.push(reader.read(8));
|
|
565
|
+
resource.data = Buffer.from(arr);
|
|
566
|
+
}
|
|
567
|
+
return resource;
|
|
568
|
+
};
|
|
569
|
+
/**
|
|
570
|
+
* [encode_name description]
|
|
571
|
+
* @param {[type]} domain [description]
|
|
572
|
+
* @return {[type]} [description]
|
|
573
|
+
*/ Packet.Name = {
|
|
574
|
+
COPY: 0xc0,
|
|
575
|
+
decode: function(reader) {
|
|
576
|
+
if (reader instanceof Buffer) {
|
|
577
|
+
reader = new Packet.Reader(reader);
|
|
578
|
+
}
|
|
579
|
+
const name = [];
|
|
580
|
+
let o;
|
|
581
|
+
let len = reader.read(8);
|
|
582
|
+
while(len){
|
|
583
|
+
if ((len & Packet.Name.COPY) === Packet.Name.COPY) {
|
|
584
|
+
len -= Packet.Name.COPY;
|
|
585
|
+
len = len << 8;
|
|
586
|
+
const pos = len + reader.read(8);
|
|
587
|
+
if (!o) o = reader.offset;
|
|
588
|
+
reader.offset = pos * 8;
|
|
589
|
+
len = reader.read(8);
|
|
590
|
+
continue;
|
|
591
|
+
} else {
|
|
592
|
+
let part = '';
|
|
593
|
+
while(len--)part += String.fromCharCode(reader.read(8));
|
|
594
|
+
name.push(part);
|
|
595
|
+
len = reader.read(8);
|
|
596
|
+
}
|
|
597
|
+
}
|
|
598
|
+
if (o) reader.offset = o;
|
|
599
|
+
return name.join('.');
|
|
600
|
+
},
|
|
601
|
+
encode: function(domain, writer) {
|
|
602
|
+
writer = writer || new Packet.Writer();
|
|
603
|
+
// TODO: domain name compress
|
|
604
|
+
(domain || '').split('.').filter(function(part) {
|
|
605
|
+
return !!part;
|
|
606
|
+
}).forEach(function(part) {
|
|
607
|
+
writer.write(part.length, 8);
|
|
608
|
+
part.split('').map(function(c) {
|
|
609
|
+
writer.write(c.charCodeAt(0), 8);
|
|
610
|
+
return c.charCodeAt(0);
|
|
611
|
+
});
|
|
612
|
+
});
|
|
613
|
+
writer.write(0, 8);
|
|
614
|
+
return writer.toBuffer();
|
|
615
|
+
}
|
|
616
|
+
};
|
|
617
|
+
/**
|
|
618
|
+
* [A description]
|
|
619
|
+
* @type {Object}
|
|
620
|
+
* @docs https://tools.ietf.org/html/rfc1035#section-3.4.1
|
|
621
|
+
*/ Packet.Resource.A = function(address) {
|
|
622
|
+
this.type = Packet.TYPE.A;
|
|
623
|
+
this.class = Packet.CLASS.IN;
|
|
624
|
+
this.address = address;
|
|
625
|
+
return this;
|
|
626
|
+
};
|
|
627
|
+
Packet.Resource.A.encode = function(record, writer) {
|
|
628
|
+
writer = writer || new Packet.Writer();
|
|
629
|
+
const parts = record.address.split('.');
|
|
630
|
+
writer.write(parts.length, 16);
|
|
631
|
+
parts.forEach(function(part) {
|
|
632
|
+
writer.write(parseInt(part, 10), 8);
|
|
633
|
+
});
|
|
634
|
+
return writer.toBuffer();
|
|
635
|
+
};
|
|
636
|
+
Packet.Resource.A.decode = function(reader, length) {
|
|
637
|
+
const parts = [];
|
|
638
|
+
while(length--)parts.push(reader.read(8));
|
|
639
|
+
this.address = parts.join('.');
|
|
640
|
+
return this;
|
|
641
|
+
};
|
|
642
|
+
/**
|
|
643
|
+
* [MX description]
|
|
644
|
+
* @param {[type]} exchange [description]
|
|
645
|
+
* @param {[type]} priority [description]
|
|
646
|
+
* @docs https://tools.ietf.org/html/rfc1035#section-3.3.9
|
|
647
|
+
*/ Packet.Resource.MX = function(exchange, priority) {
|
|
648
|
+
this.type = Packet.TYPE.MX;
|
|
649
|
+
this.class = Packet.CLASS.IN;
|
|
650
|
+
this.exchange = exchange;
|
|
651
|
+
this.priority = priority;
|
|
652
|
+
return this;
|
|
653
|
+
};
|
|
654
|
+
/**
|
|
655
|
+
* [encode description]
|
|
656
|
+
* @param {[type]} record [description]
|
|
657
|
+
* @param {[type]} writer [description]
|
|
658
|
+
* @return {[type]} [description]
|
|
659
|
+
*/ Packet.Resource.MX.encode = function(record, writer) {
|
|
660
|
+
writer = writer || new Packet.Writer();
|
|
661
|
+
const len = Packet.Name.encode(record.exchange).length;
|
|
662
|
+
writer.write(len + 2, 16);
|
|
663
|
+
writer.write(record.priority, 16);
|
|
664
|
+
Packet.Name.encode(record.exchange, writer);
|
|
665
|
+
return writer.toBuffer();
|
|
666
|
+
};
|
|
667
|
+
/**
|
|
668
|
+
* [decode description]
|
|
669
|
+
* @param {[type]} reader [description]
|
|
670
|
+
* @param {[type]} length [description]
|
|
671
|
+
* @return {[type]} [description]
|
|
672
|
+
*/ Packet.Resource.MX.decode = function(reader, length) {
|
|
673
|
+
this.priority = reader.read(16);
|
|
674
|
+
this.exchange = Packet.Name.decode(reader);
|
|
675
|
+
return this;
|
|
676
|
+
};
|
|
677
|
+
/**
|
|
678
|
+
* [AAAA description]
|
|
679
|
+
* @type {Object}
|
|
680
|
+
* @docs https://en.wikipedia.org/wiki/IPv6
|
|
681
|
+
*/ Packet.Resource.AAAA = {
|
|
682
|
+
decode: function(reader, length) {
|
|
683
|
+
const parts = [];
|
|
684
|
+
while(length){
|
|
685
|
+
length -= 2;
|
|
686
|
+
parts.push(reader.read(16));
|
|
687
|
+
}
|
|
688
|
+
this.address = toIPv6(parts);
|
|
689
|
+
return this;
|
|
690
|
+
},
|
|
691
|
+
encode: function(record, writer) {
|
|
692
|
+
writer = writer || new Packet.Writer();
|
|
693
|
+
const parts = fromIPv6(record.address);
|
|
694
|
+
writer.write(parts.length * 2, 16);
|
|
695
|
+
parts.forEach(function(part) {
|
|
696
|
+
writer.write(parseInt(part, 16), 16);
|
|
697
|
+
});
|
|
698
|
+
return writer.toBuffer();
|
|
699
|
+
}
|
|
700
|
+
};
|
|
701
|
+
/**
|
|
702
|
+
* [NS description]
|
|
703
|
+
* @type {Object}
|
|
704
|
+
* @docs https://tools.ietf.org/html/rfc1035#section-3.3.11
|
|
705
|
+
*/ Packet.Resource.NS = {
|
|
706
|
+
decode: function(reader, length) {
|
|
707
|
+
this.ns = Packet.Name.decode(reader);
|
|
708
|
+
return this;
|
|
709
|
+
},
|
|
710
|
+
encode: function(record, writer) {
|
|
711
|
+
writer = writer || new Packet.Writer();
|
|
712
|
+
writer.write(Packet.Name.encode(record.ns).length, 16);
|
|
713
|
+
Packet.Name.encode(record.ns, writer);
|
|
714
|
+
return writer.toBuffer();
|
|
715
|
+
}
|
|
716
|
+
};
|
|
717
|
+
/**
|
|
718
|
+
* [CNAME description]
|
|
719
|
+
* @type {Object}
|
|
720
|
+
* @docs https://tools.ietf.org/html/rfc1035#section-3.3.1
|
|
721
|
+
*/ Packet.Resource.PTR = Packet.Resource.CNAME = {
|
|
722
|
+
decode: function(reader, length) {
|
|
723
|
+
this.domain = Packet.Name.decode(reader);
|
|
724
|
+
return this;
|
|
725
|
+
},
|
|
726
|
+
encode: function(record, writer) {
|
|
727
|
+
writer = writer || new Packet.Writer();
|
|
728
|
+
writer.write(Packet.Name.encode(record.domain).length, 16);
|
|
729
|
+
Packet.Name.encode(record.domain, writer);
|
|
730
|
+
return writer.toBuffer();
|
|
731
|
+
}
|
|
732
|
+
};
|
|
733
|
+
/**
|
|
734
|
+
* [SPF description]
|
|
735
|
+
* @type {[type]}
|
|
736
|
+
* @docs https://tools.ietf.org/html/rfc1035#section-3.3.14
|
|
737
|
+
*/ Packet.Resource.SPF = Packet.Resource.TXT = {
|
|
738
|
+
decode: function(reader, length) {
|
|
739
|
+
const parts = [];
|
|
740
|
+
let bytesRead = 0;
|
|
741
|
+
let chunkLength = 0;
|
|
742
|
+
while(bytesRead < length){
|
|
743
|
+
chunkLength = reader.read(8); // text length
|
|
744
|
+
bytesRead++;
|
|
745
|
+
while(chunkLength--){
|
|
746
|
+
parts.push(reader.read(8));
|
|
747
|
+
bytesRead++;
|
|
748
|
+
}
|
|
749
|
+
}
|
|
750
|
+
this.data = Buffer.from(parts).toString('utf8');
|
|
751
|
+
return this;
|
|
752
|
+
},
|
|
753
|
+
encode: function(record, writer) {
|
|
754
|
+
writer = writer || new Packet.Writer();
|
|
755
|
+
// make sure that resource data is a an array of strings
|
|
756
|
+
const characterStrings = Array.isArray(record.data) ? record.data : [
|
|
757
|
+
record.data
|
|
758
|
+
];
|
|
759
|
+
// convert array of strings to array of buffers
|
|
760
|
+
const characterStringBuffers = characterStrings.map(function(characterString) {
|
|
761
|
+
if (Buffer.isBuffer(characterString)) {
|
|
762
|
+
return characterString;
|
|
763
|
+
}
|
|
764
|
+
if (typeof characterString === 'string') {
|
|
765
|
+
return Buffer.from(characterString, 'utf8');
|
|
766
|
+
}
|
|
767
|
+
return false;
|
|
768
|
+
}).filter(function(characterString) {
|
|
769
|
+
// remove invalid values from the array
|
|
770
|
+
return characterString;
|
|
771
|
+
});
|
|
772
|
+
// calculate byte length of resource strings
|
|
773
|
+
const bufferLength = characterStringBuffers.reduce(function(sum, characterStringBuffer) {
|
|
774
|
+
return sum + characterStringBuffer.length;
|
|
775
|
+
}, 0);
|
|
776
|
+
// write string length to output
|
|
777
|
+
writer.write(bufferLength + characterStringBuffers.length, 16); // response length
|
|
778
|
+
// write each string to output
|
|
779
|
+
characterStringBuffers.forEach(function(buffer) {
|
|
780
|
+
writer.write(buffer.length, 8); // text length
|
|
781
|
+
buffer.forEach(function(c) {
|
|
782
|
+
writer.write(c, 8);
|
|
783
|
+
});
|
|
784
|
+
});
|
|
785
|
+
return writer.toBuffer();
|
|
786
|
+
}
|
|
787
|
+
};
|
|
788
|
+
/**
|
|
789
|
+
* [SOA description]
|
|
790
|
+
* @type {Object}
|
|
791
|
+
* @docs https://tools.ietf.org/html/rfc1035#section-3.3.13
|
|
792
|
+
*/ Packet.Resource.SOA = {
|
|
793
|
+
decode: function(reader, length) {
|
|
794
|
+
this.primary = Packet.Name.decode(reader);
|
|
795
|
+
this.admin = Packet.Name.decode(reader);
|
|
796
|
+
this.serial = reader.read(32);
|
|
797
|
+
this.refresh = reader.read(32);
|
|
798
|
+
this.retry = reader.read(32);
|
|
799
|
+
this.expiration = reader.read(32);
|
|
800
|
+
this.minimum = reader.read(32);
|
|
801
|
+
return this;
|
|
802
|
+
},
|
|
803
|
+
encode: function(record, writer) {
|
|
804
|
+
writer = writer || new Packet.Writer();
|
|
805
|
+
let len = 0;
|
|
806
|
+
len += Packet.Name.encode(record.primary).length;
|
|
807
|
+
len += Packet.Name.encode(record.admin).length;
|
|
808
|
+
len += 32 * 5 / 8;
|
|
809
|
+
writer.write(len, 16);
|
|
810
|
+
Packet.Name.encode(record.primary, writer);
|
|
811
|
+
Packet.Name.encode(record.admin, writer);
|
|
812
|
+
writer.write(record.serial, 32);
|
|
813
|
+
writer.write(record.refresh, 32);
|
|
814
|
+
writer.write(record.retry, 32);
|
|
815
|
+
writer.write(record.expiration, 32);
|
|
816
|
+
writer.write(record.minimum, 32);
|
|
817
|
+
return writer.toBuffer();
|
|
818
|
+
}
|
|
819
|
+
};
|
|
820
|
+
/**
|
|
821
|
+
* [SRV description]
|
|
822
|
+
* @type {Object}
|
|
823
|
+
* @docs https://tools.ietf.org/html/rfc2782
|
|
824
|
+
*/ Packet.Resource.SRV = {
|
|
825
|
+
decode: function(reader, length) {
|
|
826
|
+
this.priority = reader.read(16);
|
|
827
|
+
this.weight = reader.read(16);
|
|
828
|
+
this.port = reader.read(16);
|
|
829
|
+
this.target = Packet.Name.decode(reader);
|
|
830
|
+
return this;
|
|
831
|
+
},
|
|
832
|
+
encode: function(record, writer) {
|
|
833
|
+
writer = writer || new Packet.Writer();
|
|
834
|
+
const { length } = Packet.Name.encode(record.target);
|
|
835
|
+
writer.write(length + 6, 16);
|
|
836
|
+
writer.write(record.priority, 16);
|
|
837
|
+
writer.write(record.weight, 16);
|
|
838
|
+
writer.write(record.port, 16);
|
|
839
|
+
Packet.Name.encode(record.target, writer);
|
|
840
|
+
return writer.toBuffer();
|
|
841
|
+
}
|
|
842
|
+
};
|
|
843
|
+
Packet.Resource.EDNS = function(rdata) {
|
|
844
|
+
return {
|
|
845
|
+
type: Packet.TYPE.EDNS,
|
|
846
|
+
class: 512,
|
|
847
|
+
ttl: 0,
|
|
848
|
+
rdata
|
|
849
|
+
};
|
|
850
|
+
};
|
|
851
|
+
Packet.Resource.EDNS.decode = function(reader, length) {
|
|
852
|
+
this.type = Packet.TYPE.EDNS;
|
|
853
|
+
this.class = 512;
|
|
854
|
+
this.ttl = 0;
|
|
855
|
+
this.rdata = [];
|
|
856
|
+
while(length){
|
|
857
|
+
const optionCode = reader.read(16);
|
|
858
|
+
const optionLength = reader.read(16); // In octet (https://tools.ietf.org/html/rfc6891#page-8)
|
|
859
|
+
const decoder = Object.keys(Packet.EDNS_OPTION_CODE).filter(function(type) {
|
|
860
|
+
return optionCode === Packet.EDNS_OPTION_CODE[type];
|
|
861
|
+
})[0];
|
|
862
|
+
if (decoder in Packet.Resource.EDNS && Packet.Resource.EDNS[decoder].decode) {
|
|
863
|
+
const rdata = Packet.Resource.EDNS[decoder].decode(reader, optionLength);
|
|
864
|
+
this.rdata.push(rdata);
|
|
865
|
+
} else {
|
|
866
|
+
reader.read(optionLength); // Ignore data that doesn't understand
|
|
867
|
+
debug('node-dns > unknown EDNS rdata decoder %s(%j)', decoder, optionCode);
|
|
868
|
+
}
|
|
869
|
+
length = length - 4 - optionLength;
|
|
870
|
+
}
|
|
871
|
+
return this;
|
|
872
|
+
};
|
|
873
|
+
Packet.Resource.EDNS.encode = function(record, writer) {
|
|
874
|
+
const rdataWriter = new Packet.Writer();
|
|
875
|
+
for (const rdata of record.rdata){
|
|
876
|
+
const encoder = Object.keys(Packet.EDNS_OPTION_CODE).filter(function(type) {
|
|
877
|
+
return rdata.ednsCode === Packet.EDNS_OPTION_CODE[type];
|
|
878
|
+
})[0];
|
|
879
|
+
if (encoder in Packet.Resource.EDNS && Packet.Resource.EDNS[encoder].encode) {
|
|
880
|
+
const w = new Packet.Writer();
|
|
881
|
+
Packet.Resource.EDNS[encoder].encode(rdata, w);
|
|
882
|
+
rdataWriter.write(rdata.ednsCode, 16);
|
|
883
|
+
rdataWriter.write(w.buffer.length / 8, 16);
|
|
884
|
+
rdataWriter.writeBuffer(w);
|
|
885
|
+
} else {
|
|
886
|
+
debug('node-dns > unknown EDNS rdata encoder %s(%j)', encoder, rdata.ednsCode);
|
|
887
|
+
}
|
|
888
|
+
}
|
|
889
|
+
writer = writer || new Packet.Writer();
|
|
890
|
+
writer.write(rdataWriter.buffer.length / 8, 16);
|
|
891
|
+
writer.writeBuffer(rdataWriter);
|
|
892
|
+
return writer.toBuffer();
|
|
893
|
+
};
|
|
894
|
+
Packet.Resource.EDNS.ECS = function(clientIp) {
|
|
895
|
+
const [ip, prefixLength] = clientIp.split('/');
|
|
896
|
+
const numPrefixLength = parseInt(prefixLength) || 32;
|
|
897
|
+
return {
|
|
898
|
+
ednsCode: Packet.EDNS_OPTION_CODE.ECS,
|
|
899
|
+
family: 1,
|
|
900
|
+
sourcePrefixLength: numPrefixLength,
|
|
901
|
+
scopePrefixLength: 0,
|
|
902
|
+
ip
|
|
903
|
+
};
|
|
904
|
+
};
|
|
905
|
+
Packet.Resource.EDNS.ECS.decode = function(reader, length) {
|
|
906
|
+
const rdata = {};
|
|
907
|
+
rdata.ednsCode = Packet.EDNS_OPTION_CODE.ECS;
|
|
908
|
+
rdata.family = reader.read(16);
|
|
909
|
+
rdata.sourcePrefixLength = reader.read(8);
|
|
910
|
+
rdata.scopePrefixLength = reader.read(8);
|
|
911
|
+
length -= 4;
|
|
912
|
+
if (rdata.family === 1) {
|
|
913
|
+
const ipv4Octets = [];
|
|
914
|
+
while(length--){
|
|
915
|
+
const octet = reader.read(8);
|
|
916
|
+
ipv4Octets.push(octet);
|
|
917
|
+
}
|
|
918
|
+
while(ipv4Octets.length < 4){
|
|
919
|
+
ipv4Octets.push(0);
|
|
920
|
+
}
|
|
921
|
+
rdata.ip = ipv4Octets.join('.');
|
|
922
|
+
}
|
|
923
|
+
if (rdata.family === 2) {
|
|
924
|
+
const ipv6Segments = [];
|
|
925
|
+
for(; length; length -= 2){
|
|
926
|
+
const segment = reader.read(16).toString(16);
|
|
927
|
+
ipv6Segments.push(segment);
|
|
928
|
+
}
|
|
929
|
+
while(ipv6Segments.length < 8){
|
|
930
|
+
ipv6Segments.push('0');
|
|
931
|
+
}
|
|
932
|
+
rdata.ip = ipv6Segments.join(':');
|
|
933
|
+
}
|
|
934
|
+
return rdata;
|
|
935
|
+
};
|
|
936
|
+
Packet.Resource.EDNS.ECS.encode = function(record, writer) {
|
|
937
|
+
const ip = record.ip.split('.').map((s)=>parseInt(s));
|
|
938
|
+
writer.write(record.family, 16);
|
|
939
|
+
writer.write(record.sourcePrefixLength, 8);
|
|
940
|
+
writer.write(record.scopePrefixLength, 8);
|
|
941
|
+
writer.write(ip[0], 8);
|
|
942
|
+
writer.write(ip[1], 8);
|
|
943
|
+
writer.write(ip[2], 8);
|
|
944
|
+
writer.write(ip[3], 8);
|
|
945
|
+
};
|
|
946
|
+
Packet.Resource.CAA = {
|
|
947
|
+
encode: function(record, writer) {
|
|
948
|
+
writer = writer || new Packet.Writer();
|
|
949
|
+
const buffer = Buffer.from(record.tag + record.value, 'utf8');
|
|
950
|
+
writer.write(2 + buffer.length, 16);
|
|
951
|
+
writer.write(record.flags, 8);
|
|
952
|
+
writer.write(record.tag.length, 8);
|
|
953
|
+
buffer.forEach(function(c) {
|
|
954
|
+
writer.write(c, 8);
|
|
955
|
+
});
|
|
956
|
+
return writer.toBuffer();
|
|
957
|
+
}
|
|
958
|
+
};
|
|
959
|
+
/**
|
|
960
|
+
* @type {{decode: (function(*, *): Packet.Resource.DNSKEY)}}
|
|
961
|
+
* @link https://tools.ietf.org/html/rfc4034
|
|
962
|
+
* @link https://www.iana.org/assignments/dns-sec-alg-numbers/dns-sec-alg-numbers.xhtml#table-dns-sec-alg-numbers-1
|
|
963
|
+
*/ Packet.Resource.DNSKEY = {
|
|
964
|
+
decode: function(reader, length) {
|
|
965
|
+
const RData = [];
|
|
966
|
+
while(RData.length < length){
|
|
967
|
+
RData.push(reader.read(8));
|
|
968
|
+
}
|
|
969
|
+
this.flags = RData[0] << 8 | RData[1];
|
|
970
|
+
this.protocol = RData[2];
|
|
971
|
+
this.algorithm = RData[3];
|
|
972
|
+
// for key tag
|
|
973
|
+
let ac = 0;
|
|
974
|
+
for(let i = 0; i < length; ++i){
|
|
975
|
+
ac += i & 1 ? RData[i] : RData[i] << 8;
|
|
976
|
+
}
|
|
977
|
+
ac += ac >> 16 & 0xFFFF;
|
|
978
|
+
this.keyTag = ac & 0XFFFF;
|
|
979
|
+
// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 = 16
|
|
980
|
+
// convert binary flags
|
|
981
|
+
let binFlags = this.flags.toString(2);
|
|
982
|
+
// add left padding until 16 chars
|
|
983
|
+
while(binFlags.length < 16){
|
|
984
|
+
binFlags = '0' + binFlags;
|
|
985
|
+
}
|
|
986
|
+
this.zoneKey = binFlags[7] === '1';
|
|
987
|
+
this.zoneSep = binFlags[15] === '1';
|
|
988
|
+
this.key = Buffer.from(RData.slice(4)).toString('base64');
|
|
989
|
+
return this;
|
|
990
|
+
},
|
|
991
|
+
encode: function(record, writer) {
|
|
992
|
+
writer = writer || new Packet.Writer();
|
|
993
|
+
const buffer = Buffer.from(record.key, 'base64');
|
|
994
|
+
writer.write(4 + buffer.length, 16);
|
|
995
|
+
writer.write(record.flags, 16);
|
|
996
|
+
writer.write(record.protocol, 8);
|
|
997
|
+
writer.write(record.algorithm, 8);
|
|
998
|
+
buffer.forEach(function(c) {
|
|
999
|
+
writer.write(c, 8);
|
|
1000
|
+
});
|
|
1001
|
+
return writer.toBuffer();
|
|
1002
|
+
}
|
|
1003
|
+
};
|
|
1004
|
+
/**
|
|
1005
|
+
* RRSIG just support decode
|
|
1006
|
+
* test with dns.resolveRRSIG('example.com')
|
|
1007
|
+
*
|
|
1008
|
+
* @type {{decode: (function(*, *): Packet.Resource.RRSIG)}}
|
|
1009
|
+
*/ Packet.Resource.RRSIG = {
|
|
1010
|
+
decode: function(reader, length) {
|
|
1011
|
+
function dateForSig(date) {
|
|
1012
|
+
// javascript date is from millisecond
|
|
1013
|
+
date = new Date(date * 1000);
|
|
1014
|
+
const definitions = {
|
|
1015
|
+
month: date.getUTCMonth() + 1,
|
|
1016
|
+
date: date.getUTCDate(),
|
|
1017
|
+
hour: date.getUTCHours(),
|
|
1018
|
+
minutes: date.getUTCMinutes(),
|
|
1019
|
+
seconds: date.getUTCSeconds()
|
|
1020
|
+
};
|
|
1021
|
+
let i;
|
|
1022
|
+
for(i in definitions){
|
|
1023
|
+
// if less than 10 > single
|
|
1024
|
+
if (definitions[i] < 10) {
|
|
1025
|
+
definitions[i] = '0' + '' + definitions[i];
|
|
1026
|
+
}
|
|
1027
|
+
}
|
|
1028
|
+
return date.getFullYear() + '' + definitions.month + '' + definitions.date + '' + definitions.hour + '' + definitions.minutes + '' + definitions.seconds;
|
|
1029
|
+
}
|
|
1030
|
+
// calculate max-offset uint8
|
|
1031
|
+
const maxOffset = reader.offset + length * 8;
|
|
1032
|
+
/*
|
|
1033
|
+
* Stuff sign contains 18 octets
|
|
1034
|
+
*/ this.sigType = reader.read(16); // 2
|
|
1035
|
+
this.algorithm = reader.read(8); // 1
|
|
1036
|
+
this.labels = reader.read(8); // 1
|
|
1037
|
+
this.originalTtl = reader.read(32); // 4
|
|
1038
|
+
this.expiration = dateForSig(reader.read(32)); // 4
|
|
1039
|
+
this.inception = dateForSig(reader.read(32)); // 4
|
|
1040
|
+
this.keyTag = reader.read(16); // 2
|
|
1041
|
+
this.signer = Packet.Name.decode(reader);
|
|
1042
|
+
const maxLength = (maxOffset - reader.offset) / 8;
|
|
1043
|
+
const signature = [];
|
|
1044
|
+
while(signature.length < maxLength){
|
|
1045
|
+
signature.push(reader.read(8));
|
|
1046
|
+
}
|
|
1047
|
+
this.signature = Buffer.from(signature).toString('base64');
|
|
1048
|
+
return this;
|
|
1049
|
+
}
|
|
1050
|
+
};
|
|
1051
|
+
Packet.Reader = BufferReader;
|
|
1052
|
+
Packet.Writer = BufferWriter;
|
|
1053
|
+
Packet.createResponseFromRequest = function(request) {
|
|
1054
|
+
const response = new Packet(request);
|
|
1055
|
+
response.header.qr = 1;
|
|
1056
|
+
response.additionals = [];
|
|
1057
|
+
return response;
|
|
1058
|
+
};
|
|
1059
|
+
Packet.createResourceFromQuestion = function(base, record) {
|
|
1060
|
+
const resource = new Packet.Resource(base);
|
|
1061
|
+
Object.assign(resource, record);
|
|
1062
|
+
return resource;
|
|
1063
|
+
};
|
|
1064
|
+
Packet.readStream = (socket)=>{
|
|
1065
|
+
let chunks = [];
|
|
1066
|
+
let chunklen = 0;
|
|
1067
|
+
let received = false;
|
|
1068
|
+
let expected = false;
|
|
1069
|
+
return new Promise((resolve, reject)=>{
|
|
1070
|
+
const processMessage = ()=>{
|
|
1071
|
+
if (received) return;
|
|
1072
|
+
received = true;
|
|
1073
|
+
const buffer = Buffer.concat(chunks, chunklen);
|
|
1074
|
+
resolve(buffer.slice(2));
|
|
1075
|
+
};
|
|
1076
|
+
socket.on('end', processMessage);
|
|
1077
|
+
socket.on('error', reject);
|
|
1078
|
+
socket.on('readable', ()=>{
|
|
1079
|
+
let chunk;
|
|
1080
|
+
while((chunk = socket.read()) !== null){
|
|
1081
|
+
chunks.push(chunk);
|
|
1082
|
+
chunklen += chunk.length;
|
|
1083
|
+
}
|
|
1084
|
+
if (!expected && chunklen >= 2) {
|
|
1085
|
+
if (chunks.length > 1) {
|
|
1086
|
+
chunks = [
|
|
1087
|
+
Buffer.concat(chunks, chunklen)
|
|
1088
|
+
];
|
|
1089
|
+
}
|
|
1090
|
+
expected = chunks[0].readUInt16BE(0);
|
|
1091
|
+
}
|
|
1092
|
+
if (chunklen >= 2 + expected) {
|
|
1093
|
+
processMessage();
|
|
1094
|
+
}
|
|
1095
|
+
});
|
|
1096
|
+
});
|
|
1097
|
+
};
|
|
1098
|
+
/**
|
|
1099
|
+
* DoH
|
|
1100
|
+
* @docs https://tools.ietf.org/html/rfc8484
|
|
1101
|
+
*/ Packet.prototype.toBase64URL = function() {
|
|
1102
|
+
const buffer = this.toBuffer();
|
|
1103
|
+
const base64 = buffer.toString('base64');
|
|
1104
|
+
return base64.replace(/=/g, '').replace(/\+/g, '-').replace(/\//g, '_');
|
|
1105
|
+
};
|
|
1106
|
+
packet.exports = Packet;
|
|
1107
|
+
packet.exports.toIPv6 = toIPv6;
|
|
1108
|
+
packet.exports.fromIPv6 = fromIPv6;
|
|
1109
|
+
return packet.exports;
|
|
1110
|
+
}
|
|
1111
|
+
|
|
1112
|
+
var udp_1$1;
|
|
1113
|
+
var hasRequiredUdp$1;
|
|
1114
|
+
|
|
1115
|
+
function requireUdp$1 () {
|
|
1116
|
+
if (hasRequiredUdp$1) return udp_1$1;
|
|
1117
|
+
hasRequiredUdp$1 = 1;
|
|
1118
|
+
const udp = require$$0__default$1.default;
|
|
1119
|
+
const Packet = requirePacket();
|
|
1120
|
+
/**
|
|
1121
|
+
* [Server description]
|
|
1122
|
+
* @docs https://tools.ietf.org/html/rfc1034
|
|
1123
|
+
* @docs https://tools.ietf.org/html/rfc1035
|
|
1124
|
+
*/ class Server extends udp.Socket {
|
|
1125
|
+
constructor(options){
|
|
1126
|
+
let type = 'udp4';
|
|
1127
|
+
if (typeof options === 'object') {
|
|
1128
|
+
type = options.type ?? type;
|
|
1129
|
+
}
|
|
1130
|
+
super(type);
|
|
1131
|
+
if (typeof options === 'function') {
|
|
1132
|
+
this.on('request', options);
|
|
1133
|
+
}
|
|
1134
|
+
this.on('message', this.handle.bind(this));
|
|
1135
|
+
}
|
|
1136
|
+
handle(data, rinfo) {
|
|
1137
|
+
try {
|
|
1138
|
+
const message = Packet.parse(data);
|
|
1139
|
+
this.emit('request', message, this.response.bind(this, rinfo), rinfo);
|
|
1140
|
+
} catch (e) {
|
|
1141
|
+
this.emit('requestError', e);
|
|
1142
|
+
}
|
|
1143
|
+
}
|
|
1144
|
+
response(rinfo, message) {
|
|
1145
|
+
if (message instanceof Packet) {
|
|
1146
|
+
message = message.toBuffer();
|
|
1147
|
+
}
|
|
1148
|
+
return new Promise((resolve, reject)=>{
|
|
1149
|
+
this.send(message, rinfo.port, rinfo.address, (err)=>{
|
|
1150
|
+
if (err) return reject(err);
|
|
1151
|
+
resolve(message);
|
|
1152
|
+
});
|
|
1153
|
+
});
|
|
1154
|
+
}
|
|
1155
|
+
listen(port, address) {
|
|
1156
|
+
return new Promise((resolve)=>this.bind(port, address, resolve));
|
|
1157
|
+
}
|
|
1158
|
+
}
|
|
1159
|
+
udp_1$1 = Server;
|
|
1160
|
+
return udp_1$1;
|
|
1161
|
+
}
|
|
1162
|
+
|
|
1163
|
+
var tcp_1$1;
|
|
1164
|
+
var hasRequiredTcp$1;
|
|
1165
|
+
|
|
1166
|
+
function requireTcp$1 () {
|
|
1167
|
+
if (hasRequiredTcp$1) return tcp_1$1;
|
|
1168
|
+
hasRequiredTcp$1 = 1;
|
|
1169
|
+
const tcp = require$$0__default$2.default;
|
|
1170
|
+
const Packet = requirePacket();
|
|
1171
|
+
class Server extends tcp.Server {
|
|
1172
|
+
constructor(options){
|
|
1173
|
+
super();
|
|
1174
|
+
if (typeof options === 'function') {
|
|
1175
|
+
this.on('request', options);
|
|
1176
|
+
}
|
|
1177
|
+
this.on('connection', this.handle.bind(this));
|
|
1178
|
+
}
|
|
1179
|
+
async handle(client) {
|
|
1180
|
+
try {
|
|
1181
|
+
const data = await Packet.readStream(client);
|
|
1182
|
+
const message = Packet.parse(data);
|
|
1183
|
+
this.emit('request', message, this.response.bind(this, client), client);
|
|
1184
|
+
} catch (e) {
|
|
1185
|
+
this.emit('requestError', e);
|
|
1186
|
+
client.destroy();
|
|
1187
|
+
}
|
|
1188
|
+
}
|
|
1189
|
+
response(client, message) {
|
|
1190
|
+
if (message instanceof Packet) {
|
|
1191
|
+
message = message.toBuffer();
|
|
1192
|
+
}
|
|
1193
|
+
const len = Buffer.alloc(2);
|
|
1194
|
+
len.writeUInt16BE(message.length);
|
|
1195
|
+
client.end(Buffer.concat([
|
|
1196
|
+
len,
|
|
1197
|
+
message
|
|
1198
|
+
]));
|
|
1199
|
+
}
|
|
1200
|
+
}
|
|
1201
|
+
tcp_1$1 = Server;
|
|
1202
|
+
return tcp_1$1;
|
|
1203
|
+
}
|
|
1204
|
+
|
|
1205
|
+
var doh$1;
|
|
1206
|
+
var hasRequiredDoh$1;
|
|
1207
|
+
|
|
1208
|
+
function requireDoh$1 () {
|
|
1209
|
+
if (hasRequiredDoh$1) return doh$1;
|
|
1210
|
+
hasRequiredDoh$1 = 1;
|
|
1211
|
+
const http = require$$0__default$3.default;
|
|
1212
|
+
const https = require$$1__default.default;
|
|
1213
|
+
const { URL } = require$$2__default.default;
|
|
1214
|
+
const Packet = requirePacket();
|
|
1215
|
+
const EventEmitter = require$$4__default.default;
|
|
1216
|
+
const { debuglog } = require$$0__default.default;
|
|
1217
|
+
const debug = debuglog('dns2-server');
|
|
1218
|
+
const decodeBase64URL = (str)=>{
|
|
1219
|
+
let queryData = str.replace(/-/g, '+').replace(/_/g, '/');
|
|
1220
|
+
const pad = queryData.length % 4;
|
|
1221
|
+
if (pad === 1) return;
|
|
1222
|
+
if (pad) {
|
|
1223
|
+
queryData += new Array(5 - pad).join('=');
|
|
1224
|
+
}
|
|
1225
|
+
return queryData;
|
|
1226
|
+
};
|
|
1227
|
+
const readStream = (stream)=>new Promise((resolve, reject)=>{
|
|
1228
|
+
let buffer = '';
|
|
1229
|
+
stream.on('error', reject).on('data', (chunk)=>{
|
|
1230
|
+
buffer += chunk;
|
|
1231
|
+
}).on('end', ()=>resolve(buffer));
|
|
1232
|
+
});
|
|
1233
|
+
class Server extends EventEmitter {
|
|
1234
|
+
constructor(options){
|
|
1235
|
+
super();
|
|
1236
|
+
const { ssl } = Object.assign(this, {
|
|
1237
|
+
cors: true
|
|
1238
|
+
}, options);
|
|
1239
|
+
this.server = (ssl ? https.createServer(options) : http.createServer()).on('request', this.handleRequest.bind(this)).on('listening', ()=>this.emit('listening', this.address())).on('error', (error)=>this.emit('error', error)).on('close', ()=>{
|
|
1240
|
+
this.server.removeAllListeners();
|
|
1241
|
+
this.emit('close');
|
|
1242
|
+
});
|
|
1243
|
+
return this;
|
|
1244
|
+
}
|
|
1245
|
+
async handleRequest(client, res) {
|
|
1246
|
+
try {
|
|
1247
|
+
const { method, url, headers } = client;
|
|
1248
|
+
const { pathname, searchParams: query } = new URL(url, 'http://unused/');
|
|
1249
|
+
const { cors } = this;
|
|
1250
|
+
if (cors === true) {
|
|
1251
|
+
res.setHeader('Access-Control-Allow-Origin', '*');
|
|
1252
|
+
} else if (typeof cors === 'string') {
|
|
1253
|
+
res.setHeader('Access-Control-Allow-Origin', cors);
|
|
1254
|
+
res.setHeader('Vary', 'Origin');
|
|
1255
|
+
} else if (typeof cors === 'function') {
|
|
1256
|
+
const isAllowed = cors(headers.origin);
|
|
1257
|
+
res.setHeader('Access-Control-Allow-Origin', isAllowed ? headers.origin : 'false');
|
|
1258
|
+
res.setHeader('Vary', 'Origin');
|
|
1259
|
+
}
|
|
1260
|
+
// debug
|
|
1261
|
+
debug('request', method, url);
|
|
1262
|
+
// We are only handling get and post as reqired by rfc
|
|
1263
|
+
if (method !== 'GET' && method !== 'POST') {
|
|
1264
|
+
res.writeHead(405, {
|
|
1265
|
+
'Content-Type': 'text/plain'
|
|
1266
|
+
});
|
|
1267
|
+
res.write('405 Method not allowed\n');
|
|
1268
|
+
res.end();
|
|
1269
|
+
return;
|
|
1270
|
+
}
|
|
1271
|
+
// Check so the uri is correct
|
|
1272
|
+
if (pathname !== '/dns-query') {
|
|
1273
|
+
res.writeHead(404, {
|
|
1274
|
+
'Content-Type': 'text/plain'
|
|
1275
|
+
});
|
|
1276
|
+
res.write('404 Not Found\n');
|
|
1277
|
+
res.end();
|
|
1278
|
+
return;
|
|
1279
|
+
}
|
|
1280
|
+
// Make sure the requestee is requesting the correct content type
|
|
1281
|
+
const contentType = headers.accept;
|
|
1282
|
+
if (contentType !== 'application/dns-message') {
|
|
1283
|
+
res.writeHead(400, {
|
|
1284
|
+
'Content-Type': 'text/plain'
|
|
1285
|
+
});
|
|
1286
|
+
res.write('400 Bad Request: Illegal content type\n');
|
|
1287
|
+
res.end();
|
|
1288
|
+
return;
|
|
1289
|
+
}
|
|
1290
|
+
let queryData;
|
|
1291
|
+
if (method === 'GET') {
|
|
1292
|
+
// Parse query string for the request data
|
|
1293
|
+
const dns = query.get('dns');
|
|
1294
|
+
if (!dns) {
|
|
1295
|
+
res.writeHead(400, {
|
|
1296
|
+
'Content-Type': 'text/plain'
|
|
1297
|
+
});
|
|
1298
|
+
res.write('400 Bad Request: No query defined\n');
|
|
1299
|
+
res.end();
|
|
1300
|
+
return;
|
|
1301
|
+
}
|
|
1302
|
+
// Decode from Base64Url Encoding
|
|
1303
|
+
const base64 = decodeBase64URL(dns);
|
|
1304
|
+
if (!base64) {
|
|
1305
|
+
res.writeHead(400, {
|
|
1306
|
+
'Content-Type': 'text/plain'
|
|
1307
|
+
});
|
|
1308
|
+
res.write('400 Bad Request: Invalid query data\n');
|
|
1309
|
+
res.end();
|
|
1310
|
+
return;
|
|
1311
|
+
}
|
|
1312
|
+
// Decode Base64 to buffer
|
|
1313
|
+
queryData = Buffer.from(base64, 'base64');
|
|
1314
|
+
} else if (method === 'POST') {
|
|
1315
|
+
queryData = await readStream(client);
|
|
1316
|
+
}
|
|
1317
|
+
// Parse DNS query and Raise event.
|
|
1318
|
+
const message = Packet.parse(queryData);
|
|
1319
|
+
this.emit('request', message, this.response.bind(this, res), client);
|
|
1320
|
+
} catch (e) {
|
|
1321
|
+
this.emit('requestError', e);
|
|
1322
|
+
res.destroy();
|
|
1323
|
+
}
|
|
1324
|
+
}
|
|
1325
|
+
/**
|
|
1326
|
+
* Send of the response to the client
|
|
1327
|
+
* @param {*} res
|
|
1328
|
+
* @param {*} message
|
|
1329
|
+
*/ response(res, message) {
|
|
1330
|
+
debug('response');
|
|
1331
|
+
res.setHeader('Content-Type', 'application/dns-message');
|
|
1332
|
+
res.writeHead(200);
|
|
1333
|
+
res.end(message.toBuffer());
|
|
1334
|
+
}
|
|
1335
|
+
/**
|
|
1336
|
+
* listen
|
|
1337
|
+
* @param {*} port
|
|
1338
|
+
* @returns
|
|
1339
|
+
*/ listen(port, address) {
|
|
1340
|
+
return this.server.listen(port || this.port, address);
|
|
1341
|
+
}
|
|
1342
|
+
address() {
|
|
1343
|
+
return this.server.address();
|
|
1344
|
+
}
|
|
1345
|
+
close() {
|
|
1346
|
+
return this.server.close();
|
|
1347
|
+
}
|
|
1348
|
+
}
|
|
1349
|
+
doh$1 = Server;
|
|
1350
|
+
return doh$1;
|
|
1351
|
+
}
|
|
1352
|
+
|
|
1353
|
+
var dns;
|
|
1354
|
+
var hasRequiredDns;
|
|
1355
|
+
|
|
1356
|
+
function requireDns () {
|
|
1357
|
+
if (hasRequiredDns) return dns;
|
|
1358
|
+
hasRequiredDns = 1;
|
|
1359
|
+
const EventEmitter = require$$4__default.default;
|
|
1360
|
+
const DOHServer = requireDoh$1();
|
|
1361
|
+
const TCPServer = requireTcp$1();
|
|
1362
|
+
const UDPServer = requireUdp$1();
|
|
1363
|
+
class DNSServer extends EventEmitter {
|
|
1364
|
+
constructor(options = {}){
|
|
1365
|
+
super();
|
|
1366
|
+
this.servers = {};
|
|
1367
|
+
if (options.doh) {
|
|
1368
|
+
this.servers.doh = new DOHServer(options.doh).on('error', (error)=>this.emit('error', error, 'doh'));
|
|
1369
|
+
}
|
|
1370
|
+
if (options.tcp) {
|
|
1371
|
+
this.servers.tcp = new TCPServer().on('error', (error)=>this.emit('error', error, 'tcp'));
|
|
1372
|
+
}
|
|
1373
|
+
if (options.udp) {
|
|
1374
|
+
this.servers.udp = new UDPServer(typeof options.udp === 'object' ? options.udp : undefined).on('error', (error)=>this.emit('error', error, 'udp'));
|
|
1375
|
+
}
|
|
1376
|
+
const servers = Object.values(this.servers);
|
|
1377
|
+
this.closed = Promise.all(servers.map((server)=>new Promise((resolve)=>server.once('close', resolve)))).then(()=>{
|
|
1378
|
+
this.emit('close');
|
|
1379
|
+
});
|
|
1380
|
+
this.listening = Promise.all(servers.map((server)=>new Promise((resolve)=>server.once('listening', resolve)))).then(()=>{
|
|
1381
|
+
const addresses = this.addresses();
|
|
1382
|
+
this.emit('listening', addresses);
|
|
1383
|
+
return addresses;
|
|
1384
|
+
});
|
|
1385
|
+
const emitRequest = (request, send, client)=>this.emit('request', request, send, client);
|
|
1386
|
+
const emitRequestError = (error)=>this.emit('requestError', error);
|
|
1387
|
+
for (const server of servers){
|
|
1388
|
+
server.on('request', emitRequest);
|
|
1389
|
+
server.on('requestError', emitRequestError);
|
|
1390
|
+
}
|
|
1391
|
+
if (options.handle) {
|
|
1392
|
+
this.on('request', options.handle.bind(options));
|
|
1393
|
+
}
|
|
1394
|
+
}
|
|
1395
|
+
addresses() {
|
|
1396
|
+
const addresses = {};
|
|
1397
|
+
const { udp, tcp, doh } = this.servers;
|
|
1398
|
+
if (udp) {
|
|
1399
|
+
addresses.udp = udp.address();
|
|
1400
|
+
}
|
|
1401
|
+
if (tcp) {
|
|
1402
|
+
addresses.tcp = tcp.address();
|
|
1403
|
+
}
|
|
1404
|
+
if (doh) {
|
|
1405
|
+
addresses.doh = doh.address();
|
|
1406
|
+
}
|
|
1407
|
+
return addresses;
|
|
1408
|
+
}
|
|
1409
|
+
listen(options = {}) {
|
|
1410
|
+
for (const serverType of Object.keys(this.servers)){
|
|
1411
|
+
const server = this.servers[serverType];
|
|
1412
|
+
const serverOptions = options[serverType]; // Port or { port, address }
|
|
1413
|
+
if (serverOptions && serverOptions.port) {
|
|
1414
|
+
server.listen(serverOptions.port, serverOptions.address);
|
|
1415
|
+
} else {
|
|
1416
|
+
server.listen(serverOptions);
|
|
1417
|
+
}
|
|
1418
|
+
}
|
|
1419
|
+
return this.listening;
|
|
1420
|
+
}
|
|
1421
|
+
close() {
|
|
1422
|
+
const { doh, udp, tcp } = this.servers;
|
|
1423
|
+
if (udp) {
|
|
1424
|
+
udp.close();
|
|
1425
|
+
}
|
|
1426
|
+
if (tcp) {
|
|
1427
|
+
tcp.close();
|
|
1428
|
+
}
|
|
1429
|
+
if (doh) {
|
|
1430
|
+
doh.close();
|
|
1431
|
+
}
|
|
1432
|
+
return this.closed;
|
|
1433
|
+
}
|
|
1434
|
+
}
|
|
1435
|
+
dns = DNSServer;
|
|
1436
|
+
return dns;
|
|
1437
|
+
}
|
|
1438
|
+
|
|
1439
|
+
var server;
|
|
1440
|
+
var hasRequiredServer;
|
|
1441
|
+
|
|
1442
|
+
function requireServer () {
|
|
1443
|
+
if (hasRequiredServer) return server;
|
|
1444
|
+
hasRequiredServer = 1;
|
|
1445
|
+
const UDPServer = requireUdp$1();
|
|
1446
|
+
const TCPServer = requireTcp$1();
|
|
1447
|
+
const DOHServer = requireDoh$1();
|
|
1448
|
+
const DNSServer = requireDns();
|
|
1449
|
+
const createUDPServer = (options)=>{
|
|
1450
|
+
return new UDPServer(options);
|
|
1451
|
+
};
|
|
1452
|
+
const createTCPServer = (options)=>{
|
|
1453
|
+
return new TCPServer(options);
|
|
1454
|
+
};
|
|
1455
|
+
const createDOHServer = (options)=>{
|
|
1456
|
+
return new DOHServer(options);
|
|
1457
|
+
};
|
|
1458
|
+
const createServer = (options)=>{
|
|
1459
|
+
return new DNSServer(options);
|
|
1460
|
+
};
|
|
1461
|
+
server = {
|
|
1462
|
+
UDPServer,
|
|
1463
|
+
TCPServer,
|
|
1464
|
+
DOHServer,
|
|
1465
|
+
DNSServer,
|
|
1466
|
+
createTCPServer,
|
|
1467
|
+
createUDPServer,
|
|
1468
|
+
createDOHServer,
|
|
1469
|
+
createServer
|
|
1470
|
+
};
|
|
1471
|
+
return server;
|
|
1472
|
+
}
|
|
1473
|
+
|
|
1474
|
+
var tcp_1;
|
|
1475
|
+
var hasRequiredTcp;
|
|
1476
|
+
|
|
1477
|
+
function requireTcp () {
|
|
1478
|
+
if (hasRequiredTcp) return tcp_1;
|
|
1479
|
+
hasRequiredTcp = 1;
|
|
1480
|
+
const tls = require$$0__default$4.default;
|
|
1481
|
+
const tcp = require$$0__default$2.default;
|
|
1482
|
+
const Packet = requirePacket();
|
|
1483
|
+
const makeQuery = ({ name, type = 'A', cls = Packet.CLASS.IN, clientIp, recursive = true })=>{
|
|
1484
|
+
const packet = new Packet();
|
|
1485
|
+
packet.header.rd = recursive ? 1 : 0;
|
|
1486
|
+
if (clientIp) {
|
|
1487
|
+
packet.additionals.push(Packet.Resource.EDNS([
|
|
1488
|
+
Packet.Resource.EDNS.ECS(clientIp)
|
|
1489
|
+
]));
|
|
1490
|
+
}
|
|
1491
|
+
packet.questions.push({
|
|
1492
|
+
name,
|
|
1493
|
+
class: cls,
|
|
1494
|
+
type: Packet.TYPE[type]
|
|
1495
|
+
});
|
|
1496
|
+
return packet.toBuffer();
|
|
1497
|
+
};
|
|
1498
|
+
const sendQuery = (client, message)=>{
|
|
1499
|
+
const len = Buffer.alloc(2);
|
|
1500
|
+
len.writeUInt16BE(message.length);
|
|
1501
|
+
client.write(Buffer.concat([
|
|
1502
|
+
len,
|
|
1503
|
+
message
|
|
1504
|
+
]));
|
|
1505
|
+
};
|
|
1506
|
+
const protocols = {
|
|
1507
|
+
'tcp:': (host, port)=>tcp.connect({
|
|
1508
|
+
host,
|
|
1509
|
+
port
|
|
1510
|
+
}),
|
|
1511
|
+
'tls:': (host, port)=>tls.connect({
|
|
1512
|
+
host,
|
|
1513
|
+
port,
|
|
1514
|
+
servername: host
|
|
1515
|
+
})
|
|
1516
|
+
};
|
|
1517
|
+
const TCPClient = ({ dns, protocol = 'tcp:', port = protocol === 'tls:' ? 853 : 53 } = {})=>{
|
|
1518
|
+
if (!protocols[protocol]) {
|
|
1519
|
+
throw new Error('Protocol must be tcp: or tls:');
|
|
1520
|
+
}
|
|
1521
|
+
return async (name, type, cls, options = {})=>{
|
|
1522
|
+
const message = makeQuery({
|
|
1523
|
+
name,
|
|
1524
|
+
type,
|
|
1525
|
+
cls,
|
|
1526
|
+
...options
|
|
1527
|
+
});
|
|
1528
|
+
const [host] = dns.split(':');
|
|
1529
|
+
const client = protocols[protocol](host, port);
|
|
1530
|
+
sendQuery(client, message);
|
|
1531
|
+
const data = await Packet.readStream(client);
|
|
1532
|
+
client.end();
|
|
1533
|
+
if (!data.length) throw new Error('Empty response');
|
|
1534
|
+
return Packet.parse(data);
|
|
1535
|
+
};
|
|
1536
|
+
};
|
|
1537
|
+
tcp_1 = TCPClient;
|
|
1538
|
+
return tcp_1;
|
|
1539
|
+
}
|
|
1540
|
+
|
|
1541
|
+
var doh;
|
|
1542
|
+
var hasRequiredDoh;
|
|
1543
|
+
|
|
1544
|
+
function requireDoh () {
|
|
1545
|
+
if (hasRequiredDoh) return doh;
|
|
1546
|
+
hasRequiredDoh = 1;
|
|
1547
|
+
const http = require$$0__default$3.default;
|
|
1548
|
+
const https = require$$1__default.default;
|
|
1549
|
+
const http2 = require$$2__default$1.default;
|
|
1550
|
+
const Packet = requirePacket();
|
|
1551
|
+
const protocols = {
|
|
1552
|
+
'http:': http.get,
|
|
1553
|
+
'https:': https.get,
|
|
1554
|
+
'h2:': (url, options, done)=>{
|
|
1555
|
+
const urlObj = new URL(url);
|
|
1556
|
+
const client = http2.connect(url.replace('h2:', 'https:'));
|
|
1557
|
+
const req = client.request({
|
|
1558
|
+
':path': `${urlObj.pathname}${urlObj.search}`,
|
|
1559
|
+
':method': 'GET',
|
|
1560
|
+
...options.headers
|
|
1561
|
+
});
|
|
1562
|
+
req.on('response', (headers)=>{
|
|
1563
|
+
client.close();
|
|
1564
|
+
done({
|
|
1565
|
+
headers,
|
|
1566
|
+
statusCode: headers[':status'],
|
|
1567
|
+
on: req.on.bind(req)
|
|
1568
|
+
});
|
|
1569
|
+
});
|
|
1570
|
+
req.on('error', (_err)=>{
|
|
1571
|
+
client.close();
|
|
1572
|
+
});
|
|
1573
|
+
req.end();
|
|
1574
|
+
return req;
|
|
1575
|
+
}
|
|
1576
|
+
};
|
|
1577
|
+
const makeRequest = (url, query)=>new Promise((resolve, reject)=>{
|
|
1578
|
+
const index = url.indexOf('://');
|
|
1579
|
+
if (index === -1) url = `https://${url}`;
|
|
1580
|
+
const u = new URL(url);
|
|
1581
|
+
// The DNS query is included in a single variable named “dns” in the
|
|
1582
|
+
// query component of the request URI. The value of the “dns” variable
|
|
1583
|
+
// is the content of the DNS request message, encoded with base64url
|
|
1584
|
+
// [RFC4648](https://datatracker.ietf.org/doc/html/rfc8484#section-4.1).
|
|
1585
|
+
const searchParams = u.searchParams;
|
|
1586
|
+
searchParams.set('dns', query);
|
|
1587
|
+
u.search = searchParams.toString();
|
|
1588
|
+
const get = protocols[u.protocol];
|
|
1589
|
+
if (!get) throw new Error(`Unsupported protocol: ${u.protocol}, must be specified (http://, https:// or h2://)`);
|
|
1590
|
+
const req = get(u.toString(), {
|
|
1591
|
+
headers: {
|
|
1592
|
+
accept: 'application/dns-message'
|
|
1593
|
+
}
|
|
1594
|
+
}, resolve);
|
|
1595
|
+
if (req) req.on('error', reject);
|
|
1596
|
+
});
|
|
1597
|
+
const readStream = (res)=>new Promise((resolve, reject)=>{
|
|
1598
|
+
const chunks = [];
|
|
1599
|
+
res.on('error', reject).on('data', (chunk)=>chunks.push(chunk)).on('end', ()=>{
|
|
1600
|
+
const data = Buffer.concat(chunks);
|
|
1601
|
+
if (res.statusCode !== 200) {
|
|
1602
|
+
reject(new Error(`HTTP ${res.statusCode}: ${data.toString()}`));
|
|
1603
|
+
}
|
|
1604
|
+
resolve(data);
|
|
1605
|
+
});
|
|
1606
|
+
});
|
|
1607
|
+
const buildQuery = ({ name, type = 'A', cls = Packet.CLASS.IN, clientIp, recursive = true })=>{
|
|
1608
|
+
const packet = new Packet();
|
|
1609
|
+
packet.header.rd = recursive ? 1 : 0;
|
|
1610
|
+
if (clientIp) {
|
|
1611
|
+
packet.additionals.push(Packet.Resource.EDNS([
|
|
1612
|
+
Packet.Resource.EDNS.ECS(clientIp)
|
|
1613
|
+
]));
|
|
1614
|
+
}
|
|
1615
|
+
packet.questions.push({
|
|
1616
|
+
name,
|
|
1617
|
+
class: cls,
|
|
1618
|
+
type: Packet.TYPE[type]
|
|
1619
|
+
});
|
|
1620
|
+
return packet.toBase64URL();
|
|
1621
|
+
};
|
|
1622
|
+
const DOHClient = ({ dns })=>{
|
|
1623
|
+
return async (name, type, cls, options = {})=>{
|
|
1624
|
+
const query = buildQuery({
|
|
1625
|
+
name,
|
|
1626
|
+
type,
|
|
1627
|
+
cls,
|
|
1628
|
+
...options
|
|
1629
|
+
});
|
|
1630
|
+
const response = await makeRequest(dns, query);
|
|
1631
|
+
const data = await readStream(response);
|
|
1632
|
+
return Packet.parse(data);
|
|
1633
|
+
};
|
|
1634
|
+
};
|
|
1635
|
+
doh = DOHClient;
|
|
1636
|
+
return doh;
|
|
1637
|
+
}
|
|
1638
|
+
|
|
1639
|
+
var udp_1;
|
|
1640
|
+
var hasRequiredUdp;
|
|
1641
|
+
|
|
1642
|
+
function requireUdp () {
|
|
1643
|
+
if (hasRequiredUdp) return udp_1;
|
|
1644
|
+
hasRequiredUdp = 1;
|
|
1645
|
+
const udp = require$$0__default$1.default;
|
|
1646
|
+
const Packet = requirePacket();
|
|
1647
|
+
const { equal } = require$$2__default$2.default;
|
|
1648
|
+
const { debuglog } = require$$0__default.default;
|
|
1649
|
+
const debug = debuglog('dns2');
|
|
1650
|
+
udp_1 = ({ dns = '8.8.8.8', port = 53, socketType = 'udp4' } = {})=>{
|
|
1651
|
+
return (name, type = 'A', cls = Packet.CLASS.IN, options = {})=>{
|
|
1652
|
+
const { clientIp, recursive = true } = options;
|
|
1653
|
+
const query = new Packet();
|
|
1654
|
+
query.header.id = Math.random() * 1e4 | 0;
|
|
1655
|
+
// see https://github.com/song940/node-dns/issues/29
|
|
1656
|
+
if (recursive) {
|
|
1657
|
+
query.header.rd = 1;
|
|
1658
|
+
}
|
|
1659
|
+
if (clientIp) {
|
|
1660
|
+
query.additionals.push(Packet.Resource.EDNS([
|
|
1661
|
+
Packet.Resource.EDNS.ECS(clientIp)
|
|
1662
|
+
]));
|
|
1663
|
+
}
|
|
1664
|
+
query.questions.push({
|
|
1665
|
+
name,
|
|
1666
|
+
class: cls,
|
|
1667
|
+
type: Packet.TYPE[type]
|
|
1668
|
+
});
|
|
1669
|
+
const client = new udp.Socket(socketType);
|
|
1670
|
+
return new Promise((resolve, reject)=>{
|
|
1671
|
+
client.once('message', function onMessage(message) {
|
|
1672
|
+
client.close();
|
|
1673
|
+
const response = Packet.parse(message);
|
|
1674
|
+
equal(response.header.id, query.header.id);
|
|
1675
|
+
resolve(response);
|
|
1676
|
+
});
|
|
1677
|
+
debug('send', dns, query.toBuffer());
|
|
1678
|
+
client.send(query.toBuffer(), port, dns, (err)=>err && reject(err));
|
|
1679
|
+
});
|
|
1680
|
+
};
|
|
1681
|
+
};
|
|
1682
|
+
return udp_1;
|
|
1683
|
+
}
|
|
1684
|
+
|
|
1685
|
+
var google;
|
|
1686
|
+
var hasRequiredGoogle;
|
|
1687
|
+
|
|
1688
|
+
function requireGoogle () {
|
|
1689
|
+
if (hasRequiredGoogle) return google;
|
|
1690
|
+
hasRequiredGoogle = 1;
|
|
1691
|
+
const https = require$$1__default.default;
|
|
1692
|
+
const get = (url)=>new Promise((resolve)=>https.get(url, resolve));
|
|
1693
|
+
const readStream = (stream)=>{
|
|
1694
|
+
const buffer = [];
|
|
1695
|
+
return new Promise((resolve, reject)=>{
|
|
1696
|
+
stream.on('error', reject).on('data', (chunk)=>{
|
|
1697
|
+
buffer.push(chunk);
|
|
1698
|
+
}).on('end', ()=>resolve(Buffer.concat(buffer)));
|
|
1699
|
+
});
|
|
1700
|
+
};
|
|
1701
|
+
const GoogleClient = ()=>(name, type = 'ANY')=>{
|
|
1702
|
+
return Promise.resolve().then(()=>get(`https://dns.google.com/resolve?name=${name}&type=${type}`)).then(readStream).then(JSON.parse);
|
|
1703
|
+
};
|
|
1704
|
+
google = GoogleClient;
|
|
1705
|
+
return google;
|
|
1706
|
+
}
|
|
1707
|
+
|
|
1708
|
+
var dns2;
|
|
1709
|
+
var hasRequiredDns2;
|
|
1710
|
+
|
|
1711
|
+
function requireDns2 () {
|
|
1712
|
+
if (hasRequiredDns2) return dns2;
|
|
1713
|
+
hasRequiredDns2 = 1;
|
|
1714
|
+
const { TCPServer, UDPServer, DOHServer, createTCPServer, createUDPServer, createDOHServer, createServer } = requireServer();
|
|
1715
|
+
const EventEmitter = require$$4__default.default;
|
|
1716
|
+
/**
|
|
1717
|
+
* [DNS description]
|
|
1718
|
+
* @docs https://tools.ietf.org/html/rfc1034
|
|
1719
|
+
* @docs https://tools.ietf.org/html/rfc1035
|
|
1720
|
+
*/ class DNS extends EventEmitter {
|
|
1721
|
+
constructor(options){
|
|
1722
|
+
super();
|
|
1723
|
+
Object.assign(this, {
|
|
1724
|
+
port: 53,
|
|
1725
|
+
retries: 3,
|
|
1726
|
+
timeout: 3,
|
|
1727
|
+
recursive: true,
|
|
1728
|
+
resolverProtocol: 'UDP',
|
|
1729
|
+
nameServers: [
|
|
1730
|
+
'8.8.8.8',
|
|
1731
|
+
'114.114.114.114'
|
|
1732
|
+
],
|
|
1733
|
+
rootServers: [
|
|
1734
|
+
'a',
|
|
1735
|
+
'b',
|
|
1736
|
+
'c',
|
|
1737
|
+
'd',
|
|
1738
|
+
'e',
|
|
1739
|
+
'f',
|
|
1740
|
+
'g',
|
|
1741
|
+
'h',
|
|
1742
|
+
'i',
|
|
1743
|
+
'j',
|
|
1744
|
+
'k',
|
|
1745
|
+
'l',
|
|
1746
|
+
'm'
|
|
1747
|
+
].map((x)=>`${x}.root-servers.net`)
|
|
1748
|
+
}, options);
|
|
1749
|
+
}
|
|
1750
|
+
/**
|
|
1751
|
+
* resolve
|
|
1752
|
+
* @param {*} domain
|
|
1753
|
+
* @param {*} type
|
|
1754
|
+
* @param {*} cls
|
|
1755
|
+
*/ resolve(domain, type = 'ANY', cls = DNS.Packet.CLASS.IN, options = {}) {
|
|
1756
|
+
const { port, nameServers, resolverProtocol = 'UDP' } = this;
|
|
1757
|
+
const createResolver = DNS[resolverProtocol + 'Client'];
|
|
1758
|
+
return Promise.race(nameServers.map((address)=>{
|
|
1759
|
+
const resolve = createResolver({
|
|
1760
|
+
dns: address,
|
|
1761
|
+
port
|
|
1762
|
+
});
|
|
1763
|
+
return resolve(domain, type, cls, options);
|
|
1764
|
+
}));
|
|
1765
|
+
}
|
|
1766
|
+
resolveA(domain, clientIp) {
|
|
1767
|
+
return this.resolve(domain, 'A', undefined, clientIp);
|
|
1768
|
+
}
|
|
1769
|
+
resolveAAAA(domain) {
|
|
1770
|
+
return this.resolve(domain, 'AAAA');
|
|
1771
|
+
}
|
|
1772
|
+
resolveMX(domain) {
|
|
1773
|
+
return this.resolve(domain, 'MX');
|
|
1774
|
+
}
|
|
1775
|
+
resolveCNAME(domain) {
|
|
1776
|
+
return this.resolve(domain, 'CNAME');
|
|
1777
|
+
}
|
|
1778
|
+
resolvePTR(domain) {
|
|
1779
|
+
return this.resolve(domain, 'PTR');
|
|
1780
|
+
}
|
|
1781
|
+
resolveDNSKEY(domain) {
|
|
1782
|
+
return this.resolve(domain, 'DNSKEY');
|
|
1783
|
+
}
|
|
1784
|
+
resolveRRSIG(domain) {
|
|
1785
|
+
return this.resolve(domain, 'RRSIG');
|
|
1786
|
+
}
|
|
1787
|
+
}
|
|
1788
|
+
DNS.TCPServer = TCPServer;
|
|
1789
|
+
DNS.UDPServer = UDPServer;
|
|
1790
|
+
DNS.DOHServer = DOHServer;
|
|
1791
|
+
DNS.createUDPServer = createUDPServer;
|
|
1792
|
+
DNS.createTCPServer = createTCPServer;
|
|
1793
|
+
DNS.createDOHServer = createDOHServer;
|
|
1794
|
+
DNS.createServer = createServer;
|
|
1795
|
+
DNS.TCPClient = requireTcp();
|
|
1796
|
+
DNS.DOHClient = requireDoh();
|
|
1797
|
+
DNS.UDPClient = requireUdp();
|
|
1798
|
+
DNS.GoogleClient = requireGoogle();
|
|
1799
|
+
DNS.Packet = requirePacket();
|
|
1800
|
+
dns2 = DNS;
|
|
1801
|
+
return dns2;
|
|
1802
|
+
}
|
|
1803
|
+
|
|
1804
|
+
var dns2Exports = requireDns2();
|
|
1805
|
+
|
|
18
1806
|
const defaultDnsServers = [
|
|
19
1807
|
'https://1.1.1.1',
|
|
20
1808
|
'https://1.0.0.1',
|
|
@@ -29,26 +1817,28 @@ function getDnsClients(servers) {
|
|
|
29
1817
|
const port = _port ? Number.parseInt(_port, 10) : 0;
|
|
30
1818
|
let client;
|
|
31
1819
|
switch(protocol){
|
|
1820
|
+
// case 'http':
|
|
32
1821
|
case 'https':
|
|
1822
|
+
case 'h2':
|
|
33
1823
|
{
|
|
34
1824
|
const u = new URL(dns);
|
|
35
1825
|
if (!server.includes('/')) {
|
|
36
1826
|
u.pathname = '/dns-query';
|
|
37
1827
|
}
|
|
38
|
-
client =
|
|
1828
|
+
client = dns2Exports.DOHClient({
|
|
39
1829
|
dns: u.href
|
|
40
1830
|
});
|
|
41
1831
|
break;
|
|
42
1832
|
}
|
|
43
1833
|
case 'tls':
|
|
44
|
-
client =
|
|
1834
|
+
client = dns2Exports.TCPClient({
|
|
45
1835
|
dns: server,
|
|
46
1836
|
protocol: 'tls:',
|
|
47
1837
|
port: port || 853
|
|
48
1838
|
});
|
|
49
1839
|
break;
|
|
50
1840
|
case 'tcp':
|
|
51
|
-
client =
|
|
1841
|
+
client = dns2Exports.TCPClient({
|
|
52
1842
|
dns: server,
|
|
53
1843
|
protocol: 'tcp:',
|
|
54
1844
|
port: port || 53
|
|
@@ -56,7 +1846,7 @@ function getDnsClients(servers) {
|
|
|
56
1846
|
break;
|
|
57
1847
|
case '':
|
|
58
1848
|
case 'udp':
|
|
59
|
-
client =
|
|
1849
|
+
client = dns2Exports.UDPClient({
|
|
60
1850
|
dns: server,
|
|
61
1851
|
port: port || 53
|
|
62
1852
|
});
|
|
@@ -1322,7 +3112,7 @@ const sharedNullResponse = Object.freeze({
|
|
|
1322
3112
|
const mutex = createAsyncMutex();
|
|
1323
3113
|
const dnsClients = getDnsClients(dnsServers);
|
|
1324
3114
|
return async function isRegisterableDomainAlive(domain) {
|
|
1325
|
-
domain =
|
|
3115
|
+
domain = require$$2.domainToASCII(domain);
|
|
1326
3116
|
return mutex(domain, ()=>cacheApply(registerableDomainResultCache, domain, async ()=>{
|
|
1327
3117
|
// Step 0: we normalize the domain and find the registerable part
|
|
1328
3118
|
const registerableDomain = tldts.getDomain(domain, getRegisterableDomainTldtsOption);
|
|
@@ -1428,7 +3218,7 @@ function createDomainAliveChecker(options = {}) {
|
|
|
1428
3218
|
const mutex = createAsyncMutex();
|
|
1429
3219
|
const dnsClients = getDnsClients(dnsServers);
|
|
1430
3220
|
return async function isDomainAlive(domain) {
|
|
1431
|
-
domain =
|
|
3221
|
+
domain = require$$2.domainToASCII(domain);
|
|
1432
3222
|
const registerableDomainAliveResult = await isRegisterableDomainAlive(domain);
|
|
1433
3223
|
if (registerableDomainAliveResult.registerableDomain === null) {
|
|
1434
3224
|
return sharedNullishResult;
|