dns2 1.5.0 → 2.0.2

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/test/index.js CHANGED
@@ -1,49 +1,53 @@
1
1
  const assert = require('assert');
2
2
  const test = require('./test');
3
- const Packet = require('../packet');
3
+ const { Packet, createDOHServer, createServer, TCPClient, DOHClient, UDPClient } = require('..');
4
+ const http = require('http');
5
+ const tcp = require('net');
6
+ const udp = require('dgram');
4
7
 
5
- var request = Buffer.from([
8
+ /* TODO: below is unused, either delete or use
9
+ const request = Buffer.from([
6
10
  0x29, 0x64, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00,
7
11
  0x00, 0x00, 0x00, 0x00, 0x06, 0x67, 0x6f, 0x6f,
8
12
  0x67, 0x6c, 0x65, 0x03, 0x63, 0x6f, 0x6d, 0x00,
9
- 0x00, 0x01, 0x00, 01]);
13
+ 0x00, 0x01, 0x00, 0x01]);
14
+ */
10
15
 
11
- var response = Buffer.from([
16
+ const response = Buffer.from([
12
17
  0x29, 0x64, 0x81, 0x80, 0x00, 0x01, 0x00, 0x01,
13
18
  0x00, 0x00, 0x00, 0x00, 0x03, 0x77, 0x77, 0x77,
14
19
  0x01, 0x7a, 0x02, 0x63, 0x6e, 0x00, 0x00, 0x01,
15
20
  0x00, 0x01, 0xc0, 0x0c, 0x00, 0x01, 0x00, 0x01,
16
21
  0x00, 0x00, 0x01, 0x90, 0x00, 0x04, 0x36, 0xde,
17
- 0x3c, 0xfc]);
22
+ 0x3c, 0xfc ]);
18
23
 
19
- test('Name#encode', function () {
20
- var name = Packet.Name.encode('www.google.com');
21
- var pattern = [3, 'w', 'w', 'w', 5, 'g', 'o', 'o', 'g', 'l', 'e', 3, 'c', 'o', 'm', '0'];
24
+ test('Name#encode', function() {
25
+ const name = Packet.Name.encode('www.google.com');
26
+ const pattern = [ 3, 'w', 'w', 'w', 5, 'g', 'o', 'o', 'g', 'l', 'e', 3, 'c', 'o', 'm', '0' ];
22
27
  assert.equal(name.length, pattern.length);
23
28
  });
24
29
 
25
- test('Name#decode', function () {
26
- var reader = new Packet.Reader(response, 8 * 12);
27
- var name = Packet.Name.decode(reader);
30
+ test('Name#decode', function() {
31
+ const reader = new Packet.Reader(response, 8 * 12);
32
+ let name = Packet.Name.decode(reader);
28
33
  assert.equal(name, 'www.z.cn');
29
34
 
30
35
  reader.offset = 8 * 26;
31
- var name = Packet.Name.decode(reader);
36
+ name = Packet.Name.decode(reader);
32
37
  assert.equal(reader.offset, 8 * 28);
33
38
  assert.equal(name, 'www.z.cn');
34
-
35
39
  });
36
40
 
37
- test('Header#encode', function () {
38
- var header = new Packet.Header({ id: 0x2964, qr: 1 });
41
+ test('Header#encode', function() {
42
+ const header = new Packet.Header({ id: 0x2964, qr: 1 });
39
43
  header.qdcount = 1;
40
44
  header.ancount = 2;
41
45
  assert.deepEqual(header.toBuffer(), Buffer.from([
42
- 0x29, 0x64, 0x80, 0x00, 0x00, 0x01, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00]));
46
+ 0x29, 0x64, 0x80, 0x00, 0x00, 0x01, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00 ]));
43
47
  });
44
48
 
45
- test('Header#parse', function () {
46
- var header = Packet.Header.parse(response);
49
+ test('Header#parse', function() {
50
+ const header = Packet.Header.parse(response);
47
51
  assert.equal(header.id, 0x2964);
48
52
  assert.equal(header.qr, 1);
49
53
  assert.equal(header.opcode, 0);
@@ -58,33 +62,31 @@ test('Header#parse', function () {
58
62
  assert.equal(header.arcount, 0);
59
63
  });
60
64
 
61
- test('Question#encode', function () {
62
-
63
- var question = new Packet.Question({
64
- name: 'google.com',
65
- type: Packet.TYPE.A,
66
- class: Packet.CLASS.IN
65
+ test('Question#encode', function() {
66
+ const question = new Packet.Question({
67
+ name : 'google.com',
68
+ type : Packet.TYPE.A,
69
+ class : Packet.CLASS.IN,
67
70
  });
68
71
  //
69
72
  assert.deepEqual(question.toBuffer(), Buffer.from([
70
73
  0x06, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x03,
71
- 0x63, 0x6f, 0x6d, 0x00, 0x00, 0x01, 0x00, 0x01
74
+ 0x63, 0x6f, 0x6d, 0x00, 0x00, 0x01, 0x00, 0x01,
72
75
  ]));
73
76
  });
74
77
 
75
- test('Question#decode', function () {
76
-
77
- var question = new Packet.Question('google.com',
78
+ test('Question#decode', function() {
79
+ const question = new Packet.Question('google.com',
78
80
  Packet.TYPE.A, Packet.CLASS.IN);
79
81
  assert.deepEqual(question.toBuffer(), Buffer.from([
80
82
  0x06, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x03,
81
- 0x63, 0x6f, 0x6d, 0x00, 0x00, 0x01, 0x00, 0x01
83
+ 0x63, 0x6f, 0x6d, 0x00, 0x00, 0x01, 0x00, 0x01,
82
84
  ]));
83
85
  });
84
86
 
85
87
  //
86
- test('Packet#parse', function () {
87
- var packet = Packet.parse(response);
88
+ test('Packet#parse', function() {
89
+ const packet = Packet.parse(response);
88
90
  assert.equal(packet.questions[0].name, 'www.z.cn');
89
91
  assert.equal(packet.questions[0].type, Packet.TYPE.A);
90
92
  assert.equal(packet.questions[0].class, Packet.CLASS.IN);
@@ -93,122 +95,119 @@ test('Packet#parse', function () {
93
95
  assert.equal(packet.answers[0].address, '54.222.60.252');
94
96
  });
95
97
 
96
- test('Packet#encode', function () {
97
-
98
-
99
- var response = new Packet();
98
+ test('Packet#encode', function() {
99
+ const response = new Packet();
100
100
  //
101
101
  response.header.qr = 1;
102
102
  response.answers.push({
103
- name: 'lsong.org',
104
- type: Packet.TYPE.A,
105
- class: Packet.CLASS.IN,
106
- ttl: 300,
107
- address: '127.0.0.1'
103
+ name : 'lsong.org',
104
+ type : Packet.TYPE.A,
105
+ class : Packet.CLASS.IN,
106
+ ttl : 300,
107
+ address : '127.0.0.1',
108
108
  });
109
109
 
110
110
  response.answers.push({
111
- name: 'lsong.org',
112
- type: Packet.TYPE.AAAA,
113
- class: Packet.CLASS.IN,
114
- ttl: 300,
115
- address: '2001:db8::::ff00:42:8329'
111
+ name : 'lsong.org',
112
+ type : Packet.TYPE.AAAA,
113
+ class : Packet.CLASS.IN,
114
+ ttl : 300,
115
+ address : '2001:db8::::ff00:42:8329',
116
116
  });
117
117
 
118
118
  response.answers.push({
119
- name: 'lsong.org',
120
- type: Packet.TYPE.CNAME,
121
- class: Packet.CLASS.IN,
122
- ttl: 300,
123
- domain: 'sfo1.lsong.org'
119
+ name : 'lsong.org',
120
+ type : Packet.TYPE.CNAME,
121
+ class : Packet.CLASS.IN,
122
+ ttl : 300,
123
+ domain : 'sfo1.lsong.org',
124
124
  });
125
125
 
126
126
  response.answers.push({
127
- name: 'lsong.org',
128
- type: Packet.TYPE.PTR,
129
- class: Packet.CLASS.IN,
130
- ttl: 300,
131
- domain: 'sfo1.lsong.org'
127
+ name : 'lsong.org',
128
+ type : Packet.TYPE.PTR,
129
+ class : Packet.CLASS.IN,
130
+ ttl : 300,
131
+ domain : 'sfo1.lsong.org',
132
132
  });
133
133
 
134
134
  response.authorities.push({
135
- name: 'lsong.org',
136
- type: Packet.TYPE.MX,
137
- class: Packet.CLASS.IN,
138
- ttl: 300,
139
- exchange: 'mail.lsong.org',
140
- priority: 5
135
+ name : 'lsong.org',
136
+ type : Packet.TYPE.MX,
137
+ class : Packet.CLASS.IN,
138
+ ttl : 300,
139
+ exchange : 'mail.lsong.org',
140
+ priority : 5,
141
141
  });
142
142
 
143
143
  response.authorities.push({
144
- name: 'lsong.org',
145
- type: Packet.TYPE.NS,
146
- class: Packet.CLASS.IN,
147
- ttl: 300,
148
- ns: 'ns1.lsong.org',
144
+ name : 'lsong.org',
145
+ type : Packet.TYPE.NS,
146
+ class : Packet.CLASS.IN,
147
+ ttl : 300,
148
+ ns : 'ns1.lsong.org',
149
149
  });
150
150
 
151
151
  response.additionals.push({
152
- name: 'lsong.org',
153
- type: Packet.TYPE.SOA,
154
- class: Packet.CLASS.IN,
155
- ttl: 300,
156
- primary: 'lsong.org',
157
- admin: 'admin@lsong.org',
158
- serial: 2016121301,
159
- refresh: 300,
160
- retry: 3,
161
- expiration: 10,
162
- minimum: 10
152
+ name : 'lsong.org',
153
+ type : Packet.TYPE.SOA,
154
+ class : Packet.CLASS.IN,
155
+ ttl : 300,
156
+ primary : 'lsong.org',
157
+ admin : 'admin@lsong.org',
158
+ serial : 2016121301,
159
+ refresh : 300,
160
+ retry : 3,
161
+ expiration : 10,
162
+ minimum : 10,
163
163
  });
164
164
  //
165
165
  response.additionals.push({
166
- name: 'lsong.org',
167
- type: Packet.TYPE.TXT,
168
- class: Packet.CLASS.IN,
169
- ttl: 300,
170
- data: '#v=spf1 include:_spf.google.com ~all'
166
+ name : 'lsong.org',
167
+ type : Packet.TYPE.TXT,
168
+ class : Packet.CLASS.IN,
169
+ ttl : 300,
170
+ data : '#v=spf1 include:_spf.google.com ~all',
171
171
  });
172
172
 
173
173
  assert.deepEqual(Packet.parse(response.toBuffer()), response);
174
-
175
174
  });
176
175
 
177
- test('Packet#encode array of character strings', function () {
178
- var response = new Packet();
176
+ test('Packet#encode array of character strings', function() {
177
+ const response = new Packet();
179
178
  //
180
- var dkim = ['v=DKIM1; k=rsa; p=MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAsD6Th73ZDKkFAntNZDbx',
179
+ const dkim = [ 'v=DKIM1; k=rsa; p=MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAsD6Th73ZDKkFAntNZDbx',
181
180
  'Eh8VV2DSMs3re6v9/gXoT3dGcbSsuUMpfLzP5MWp4sW5cPyZxEGSiC03ZVIcCca0GRAuX9b1M0Qy25wLmPq',
182
181
  '8eT129mhwbeX50xTaXqq63A/oDM0QOPe1IeBMfPnR9tWXxvEzZKvVbmTlMY5bf+3QHLqmaEihnGlXh2LRVZ',
183
182
  'be2EMlYo18YM4LU/LkZKe06rxlq38W22TL7964tr7jmOZ+huXf2iLSg4nc4UzLwb2aOdOA+w4c87h+HW/L8',
184
- '0548pFguF46TKc0C0egZ+oll3Y8zySYrbkVrWFrcpnrw5qDiRVHEjxqZSubSYX+16TjNcJg9QIDAQAB'];
183
+ '0548pFguF46TKc0C0egZ+oll3Y8zySYrbkVrWFrcpnrw5qDiRVHEjxqZSubSYX+16TjNcJg9QIDAQAB' ];
185
184
 
186
185
  response.header.qr = 1;
187
186
  response.answers.push({
188
- name: 'lsong.org',
189
- type: Packet.TYPE.TXT,
190
- class: Packet.CLASS.IN,
191
- ttl: 300,
192
- data: dkim
187
+ name : 'lsong.org',
188
+ type : Packet.TYPE.TXT,
189
+ class : Packet.CLASS.IN,
190
+ ttl : 300,
191
+ data : dkim,
193
192
  });
194
193
 
195
- assert.equal(Packet.parse(response.toBuffer()).answers[0].data, dkim.join(''))
194
+ assert.equal(Packet.parse(response.toBuffer()).answers[0].data, dkim.join(''));
196
195
  });
197
196
 
198
- test('EDNS.ECS#encode', function () {
199
- var query = new Packet.Resource.EDNS([
200
- new Packet.Resource.EDNS.ECS('10.11.12.13/24')
197
+ test('EDNS.ECS#encode', function() {
198
+ const query = new Packet.Resource.EDNS([
199
+ new Packet.Resource.EDNS.ECS('10.11.12.13/24'),
201
200
  ]);
202
201
 
203
- let b = Packet.Resource.encode(query)
202
+ const b = Packet.Resource.encode(query);
204
203
  assert.deepEqual(b, Buffer.from([
205
204
  0x00, 0x00, 0x29, 0x02, 0x00, 0x00, 0x00, 0x00,
206
205
  0x00, 0x00, 0x0c, 0x00, 0x08, 0x00, 0x08, 0x00,
207
- 0x01, 0x18, 0x00, 0x0a, 0x0b, 0x0c, 0x0d]))
208
- })
206
+ 0x01, 0x18, 0x00, 0x0a, 0x0b, 0x0c, 0x0d ]));
207
+ });
209
208
 
210
- test('EDNS#decode', function () {
211
- const buffer = Buffer.from([0x00, 0x08, 0x00, 0x08, 0x00, 0x01, 0x18, 0x00, 0x0a, 0x0b, 0x0c, 0x0d]);
209
+ test('EDNS#decode', function() {
210
+ const buffer = Buffer.from([ 0x00, 0x08, 0x00, 0x08, 0x00, 0x01, 0x18, 0x00, 0x0a, 0x0b, 0x0c, 0x0d ]);
212
211
  const reader = new Packet.Reader(buffer);
213
212
  const record = Packet.Resource.EDNS.decode(reader, buffer.length);
214
213
 
@@ -220,7 +219,7 @@ test('EDNS#decode', function () {
220
219
  assert.equal(record.rdata[0].ip, '10.11.12.13');
221
220
 
222
221
  const query = new Packet.Resource.EDNS([
223
- new Packet.Resource.EDNS.ECS('10.20.0.0/16')
222
+ new Packet.Resource.EDNS.ECS('10.20.0.0/16'),
224
223
  ]);
225
224
  const encoded = Packet.Resource.encode(query);
226
225
  const decoded = Packet.Resource.decode(encoded);
@@ -229,12 +228,12 @@ test('EDNS#decode', function () {
229
228
  assert.deepEqual(decoded, query);
230
229
  });
231
230
 
232
- test('EDNS#decode multiple', function () {
231
+ test('EDNS#decode multiple', function() {
233
232
  const query = new Packet.Resource.EDNS([
234
233
  new Packet.Resource.EDNS.ECS('10.0.0.0/8'),
235
234
  new Packet.Resource.EDNS.ECS('10.9.0.0/16'),
236
235
  new Packet.Resource.EDNS.ECS('10.9.8.0/24'),
237
- new Packet.Resource.EDNS.ECS('10.9.8.7/32')
236
+ new Packet.Resource.EDNS.ECS('10.9.8.7/32'),
238
237
  ]);
239
238
  const encoded = Packet.Resource.encode(query);
240
239
  const decoded = Packet.Resource.decode(encoded);
@@ -242,3 +241,155 @@ test('EDNS#decode multiple', function () {
242
241
 
243
242
  assert.deepEqual(decoded, query);
244
243
  });
244
+
245
+ test('server/doh#cors - default', async function() {
246
+ const server = createDOHServer();
247
+ const { port } = await new Promise(resolve => {
248
+ server.on('listening', resolve);
249
+ server.listen();
250
+ });
251
+ const { headers } = await get(`http://localhost:${port}`);
252
+ assert.equal(headers['access-control-allow-origin'], '*');
253
+ server.server.close();
254
+ });
255
+
256
+ test('server/doh#cors - no cors', async function() {
257
+ const server = createDOHServer({
258
+ cors: false,
259
+ });
260
+ const { port } = await new Promise(resolve => {
261
+ server.on('listening', resolve);
262
+ server.listen();
263
+ });
264
+ const { headers } = await get(`http://localhost:${port}`);
265
+ assert.equal(headers['access-control-allow-origin'], undefined);
266
+ server.server.close();
267
+ });
268
+
269
+ test('server/doh#cors - cors origin', async function() {
270
+ const server = createDOHServer({
271
+ cors: 'some.domain',
272
+ });
273
+ const { port } = await new Promise(resolve => {
274
+ server.on('listening', resolve);
275
+ server.listen();
276
+ });
277
+ const { headers } = await get(`http://localhost:${port}`);
278
+ assert.equal(headers['access-control-allow-origin'], 'some.domain');
279
+ assert.equal(headers.vary, 'Origin');
280
+ server.server.close();
281
+ });
282
+
283
+ test('server/doh#cors - cors function', async function() {
284
+ const server = createDOHServer({
285
+ cors(domain) {
286
+ if (domain === 'a.domain') {
287
+ return true;
288
+ } else if (domain === 'b.domain') {
289
+ return false;
290
+ }
291
+ throw new Error(`Unexpected domain: ${domain}`);
292
+ },
293
+ });
294
+ const { port } = await new Promise(resolve => {
295
+ server.on('listening', resolve);
296
+ server.listen();
297
+ });
298
+ let headers = (await get(`http://localhost:${port}`, { headers: { origin: 'a.domain' } })).headers;
299
+ assert.equal(headers['access-control-allow-origin'], 'a.domain');
300
+ assert.equal(headers.vary, 'Origin');
301
+ headers = (await get(`http://localhost:${port}`, { headers: { origin: 'b.domain' } })).headers;
302
+ assert.equal(headers['access-control-allow-origin'], 'false');
303
+ assert.equal(headers.vary, 'Origin');
304
+ server.server.close();
305
+ });
306
+
307
+ test('server/all#simple-request', async() => {
308
+ const server = createServer({
309
+ doh : true,
310
+ tcp : true,
311
+ udp : true,
312
+ handle(request, send, _info) {
313
+ const [ question ] = request.questions;
314
+ assert.deepEqual(request.questions, [ { name: 'test.com', type: 1, class: 1 } ]);
315
+ const response = Packet.createResponseFromRequest(request);
316
+ response.answers.push({
317
+ name : question.name,
318
+ type : Packet.TYPE.TXT,
319
+ class : Packet.CLASS.IN,
320
+ ttl : 300,
321
+ data : [ 'Hello World' ],
322
+ });
323
+ send(response);
324
+ },
325
+ });
326
+ const servers = await server.listen();
327
+ assert.ok(servers.udp.port > 1000);
328
+ assert.ok(servers.tcp.port > 1000);
329
+ assert.ok(servers.doh.port > 1000);
330
+ const doh = DOHClient({ dns: `127.0.0.1:${servers.doh.port}`, http: true });
331
+ const tcp = TCPClient({ dns: '127.0.0.1', port: servers.tcp.port });
332
+ const udp = UDPClient({ dns: '127.0.0.1', port: servers.udp.port });
333
+ const expected = [ { name: 'test.com', ttl: 300, type: 16, class: 1, data: 'Hello World' } ];
334
+ assert.deepEqual((await doh('test.com')).answers, expected);
335
+ assert.deepEqual((await tcp('test.com')).answers, expected);
336
+ assert.deepEqual((await udp('test.com')).answers, expected);
337
+ await server.close();
338
+ });
339
+
340
+ test('server/all#invalid-request', async() => {
341
+ const server = createServer({
342
+ doh : true,
343
+ tcp : true,
344
+ udp : true,
345
+ handle : () => {},
346
+ });
347
+ const servers = await server.listen();
348
+ assert.ok(servers.udp.port > 1000);
349
+ assert.ok(servers.tcp.port > 1000);
350
+ assert.ok(servers.doh.port > 1000);
351
+
352
+ const errors = [];
353
+ server.on('requestError', (e) => {
354
+ errors.push(e);
355
+ });
356
+
357
+ const tcpSocket = tcp.connect({ port: servers.tcp.port, host: '127.0.0.1' });
358
+ tcpSocket.on('connect', () => tcpSocket.end('INVALID'));
359
+
360
+ const udpSocket = udp.createSocket('udp4');
361
+ udpSocket.send('INVALID', servers.udp.port, '127.0.0.1', () => udpSocket.close());
362
+
363
+ const dohConn = http.get(`http://127.0.0.1:${servers.doh.port}/dns-query?dns=INVALID`, {
364
+ headers: { accept: 'application/dns-message' },
365
+ }).on('error', () => {});
366
+
367
+ await Promise.all([
368
+ new Promise((resolve) => tcpSocket.on('close', resolve)),
369
+ new Promise((resolve) => udpSocket.on('close', resolve)),
370
+ new Promise((resolve) => dohConn.on('close', resolve)),
371
+ ]);
372
+
373
+ assert.equal(errors.length, 3);
374
+
375
+ await server.close();
376
+ });
377
+
378
+ function get(url, options) {
379
+ return new Promise((resolve, reject) => {
380
+ try {
381
+ const req = http.get(url, options, res => {
382
+ const result = [];
383
+ res.on('data', data => result.push(data));
384
+ res.once('error', reject);
385
+ res.once('end', () => resolve({
386
+ body : Buffer.concat(result),
387
+ headers : res.headers,
388
+ }));
389
+ });
390
+ req.on('error', reject);
391
+ } catch (err) {
392
+ reject(err);
393
+ }
394
+ });
395
+ }
package/test/test.js CHANGED
@@ -1,27 +1,34 @@
1
1
  const { inspect } = require('util');
2
+
3
+ let previous = Promise.resolve();
4
+
2
5
  /**
3
6
  * super tiny testing framework
4
- *
7
+ *
5
8
  * @author Liu song <hi@lsong.org>
6
9
  * @github https://github.com/song940
7
10
  */
8
- const test = async (title, fn) => {
9
- try {
10
- await fn();
11
- console.log(color(` ✔ ${title}`, 32));
12
- } catch (err) {
13
- console.error(color(` ✘ ${title}`, 31));
14
- console.log();
15
- console.log(color(` ${err.name}: ${err.message}`, 31));
16
- console.error(color(` expected: ${inspect(err.expected)}`, 32));
17
- console.error(color(` actual: ${inspect(err.actual)}`, 31));
18
- console.log();
19
- process.exit(1);
20
- }
11
+ const test = (title, fn) => {
12
+ previous = previous.then(async() => {
13
+ try {
14
+ await fn();
15
+ console.log(color(` ✔ ${title}`, 32));
16
+ } catch (err) {
17
+ console.error(color(` ✘ ${title}`, 31));
18
+ console.log();
19
+ console.log(color(` ${err.name}: ${err.message}`, 31));
20
+ console.error(color(` expected: ${inspect(err.expected)}`, 32));
21
+ console.error(color(` actual: ${inspect(err.actual)}`, 31));
22
+ console.log(err.stack);
23
+ console.log();
24
+ process.exit(1);
25
+ }
26
+ });
27
+ return previous;
21
28
  };
22
29
 
23
30
  function color(str, c) {
24
- return "\x1b[" + c + "m" + str + "\x1b[0m";
25
- };
31
+ return `\x1b[${c}m${str}\x1b[0m`;
32
+ }
26
33
 
27
- module.exports = test;
34
+ module.exports = test;
package/.travis.yml DELETED
@@ -1,4 +0,0 @@
1
- language: node_js
2
- node_js:
3
- - "stable"
4
- - "v8.13.0"