dns2 2.0.5 → 2.2.1

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/ts/index.d.ts ADDED
@@ -0,0 +1,371 @@
1
+ /// <reference types="node" />
2
+
3
+ import * as dgram from 'node:dgram';
4
+ import { EventEmitter } from 'node:events';
5
+ import * as http from 'node:http';
6
+ import * as net from 'node:net';
7
+
8
+ // ─── Main DNS class ───────────────────────────────────────────────────────────
9
+
10
+ declare class DNS extends EventEmitter {
11
+ constructor(options?: Partial<DNS.ClientOptions>);
12
+
13
+ resolve(
14
+ domain: string,
15
+ type?: string,
16
+ cls?: number,
17
+ options?: DNS.ResolveOptions,
18
+ ): Promise<DNS.Packet>;
19
+
20
+ resolveA(domain: string, clientIp?: string): Promise<DNS.Packet>;
21
+ resolveAAAA(domain: string): Promise<DNS.Packet>;
22
+ resolveMX(domain: string): Promise<DNS.Packet>;
23
+ resolveCNAME(domain: string): Promise<DNS.Packet>;
24
+ resolvePTR(domain: string): Promise<DNS.Packet>;
25
+ resolveDNSKEY(domain: string): Promise<DNS.Packet>;
26
+ resolveRRSIG(domain: string): Promise<DNS.Packet>;
27
+ resolveSOA(domain: string): Promise<DNS.Packet>;
28
+
29
+ static createServer(options: DNS.CreateServerOptions): DNS.DnsServer;
30
+ static createUDPServer(options?: DNS.UdpServerOptions | DNS.DnsHandler): DNS.UDPServer;
31
+ static createTCPServer(options?: DNS.DnsHandler): DNS.TCPServer;
32
+ static createDOHServer(options?: DNS.DohServerOptions): DNS.DOHServer;
33
+
34
+ static UDPClient(options?: DNS.UdpClientOptions): DNS.DnsResolver;
35
+ static TCPClient(options?: DNS.TcpClientOptions): DNS.DnsResolver;
36
+ static DOHClient(options?: DNS.DohClientOptions): DNS.DnsResolver;
37
+ static GoogleClient(): DNS.DnsResolver;
38
+ }
39
+
40
+ // ─── Namespace (all exported sub-types live here) ─────────────────────────────
41
+
42
+ declare namespace DNS {
43
+
44
+ // ── Packet ──────────────────────────────────────────────────────────────────
45
+
46
+ class Packet {
47
+ header: Packet.Header;
48
+ questions: Packet.Question[];
49
+ answers: Packet.Resource[];
50
+ authorities: Packet.Resource[];
51
+ additionals: Packet.Resource[];
52
+ recursive: boolean;
53
+
54
+ constructor(
55
+ data?: Packet | Packet.Header | Packet.Question | Packet.Resource | string | any[],
56
+ );
57
+
58
+ toBuffer(): Buffer;
59
+ toBase64URL(): string;
60
+
61
+ // ── Static constants ────────────────────────────────────────────────────
62
+
63
+ static TYPE: {
64
+ A : 0x01;
65
+ NS : 0x02;
66
+ MD : 0x03;
67
+ MF : 0x04;
68
+ CNAME : 0x05;
69
+ SOA : 0x06;
70
+ MB : 0x07;
71
+ MG : 0x08;
72
+ MR : 0x09;
73
+ NULL : 0x0a;
74
+ WKS : 0x0b;
75
+ PTR : 0x0c;
76
+ HINFO : 0x0d;
77
+ MINFO : 0x0e;
78
+ MX : 0x0f;
79
+ TXT : 0x10;
80
+ AAAA : 0x1c;
81
+ SRV : 0x21;
82
+ EDNS : 0x29;
83
+ SPF : 0x63;
84
+ AXFR : 0xfc;
85
+ MAILB : 0xfd;
86
+ MAILA : 0xfe;
87
+ ANY : 0xff;
88
+ CAA : 0x101;
89
+ DNSKEY : 0x30;
90
+ };
91
+
92
+ static CLASS: {
93
+ IN : 0x01;
94
+ CS : 0x02;
95
+ CH : 0x03;
96
+ HS : 0x04;
97
+ ANY : 0xff;
98
+ };
99
+
100
+ static EDNS_OPTION_CODE: {
101
+ ECS: 0x08;
102
+ };
103
+
104
+ // ── Static helpers ──────────────────────────────────────────────────────
105
+
106
+ static parse(buffer: Buffer): Packet;
107
+ static createResponseFromRequest(request: Packet): Packet;
108
+ static createResourceFromQuestion(
109
+ base: Packet.Question,
110
+ record: Partial<Packet.Resource>,
111
+ ): Packet.Resource;
112
+ static readStream(socket: NodeJS.ReadableStream): Promise<Buffer>;
113
+ static toIPv6(parts: number[]): string;
114
+ static fromIPv6(address: string): string[];
115
+ static uuid(): number;
116
+
117
+ // ── Sub-constructors ────────────────────────────────────────────────────
118
+
119
+ static Header: {
120
+ new(header?: Partial<Packet.Header>): Packet.Header;
121
+ parse(reader: Buffer | Packet.Reader): Packet.Header;
122
+ };
123
+
124
+ static Question: {
125
+ new(
126
+ name?: string | Partial<Packet.Question>,
127
+ type?: number,
128
+ cls?: number,
129
+ ): Packet.Question;
130
+ parse(reader: Buffer | Packet.Reader): Packet.Question;
131
+ decode(reader: Buffer | Packet.Reader): Packet.Question;
132
+ encode(question: Packet.Question, writer?: Packet.Writer): Buffer;
133
+ };
134
+
135
+ static Resource: {
136
+ new(
137
+ name?: string | Partial<Packet.Resource>,
138
+ type?: number,
139
+ cls?: number,
140
+ ttl?: number,
141
+ ): Packet.Resource;
142
+ parse(reader: Buffer | Packet.Reader): Packet.Resource;
143
+ decode(reader: Buffer | Packet.Reader): Packet.Resource;
144
+ encode(resource: Packet.Resource, writer?: Packet.Writer): Buffer;
145
+ EDNS(rdata: object[]): Packet.Resource;
146
+ };
147
+
148
+ static Name: {
149
+ COPY: 0xc0;
150
+ encode(domain: string, writer?: Packet.Writer): Buffer;
151
+ decode(reader: Buffer | Packet.Reader): string;
152
+ };
153
+
154
+ static Reader: new(buffer: Buffer, offset?: number) => Packet.Reader;
155
+ static Writer: new() => Packet.Writer;
156
+ }
157
+
158
+ namespace Packet {
159
+ interface Header {
160
+ id: number;
161
+ qr: 0 | 1;
162
+ opcode: number;
163
+ aa: 0 | 1;
164
+ tc: 0 | 1;
165
+ rd: 0 | 1;
166
+ ra: 0 | 1;
167
+ z: number;
168
+ rcode: number;
169
+ qdcount: number;
170
+ ancount: number;
171
+ nscount: number;
172
+ arcount: number;
173
+ toBuffer(writer?: Writer): Buffer;
174
+ }
175
+
176
+ interface Question {
177
+ name: string;
178
+ type: number;
179
+ class: number;
180
+ toBuffer(writer?: Writer): Buffer;
181
+ }
182
+
183
+ /** Union of all possible DNS resource record shapes. */
184
+ interface Resource {
185
+ name: string;
186
+ type: number;
187
+ class: number;
188
+ ttl: number;
189
+ // A / AAAA
190
+ address?: string;
191
+ // MX
192
+ exchange?: string;
193
+ priority?: number;
194
+ // CNAME / PTR / NS
195
+ domain?: string;
196
+ ns?: string;
197
+ // TXT / SPF
198
+ data?: string | string[];
199
+ // SOA
200
+ primary?: string;
201
+ admin?: string;
202
+ serial?: number;
203
+ refresh?: number;
204
+ retry?: number;
205
+ expiration?: number;
206
+ minimum?: number;
207
+ // SRV
208
+ weight?: number;
209
+ port?: number;
210
+ target?: string;
211
+ // CAA
212
+ flags?: number;
213
+ tag?: string;
214
+ value?: string;
215
+ // DNSKEY
216
+ algorithm?: number;
217
+ keyTag?: number;
218
+ publicKey?: string;
219
+ toBuffer(writer?: Writer): Buffer;
220
+ }
221
+
222
+ interface Reader {
223
+ offset: number;
224
+ read(bits: number): number;
225
+ }
226
+
227
+ interface Writer {
228
+ buffer: number[];
229
+ write(value: number, bits: number): void;
230
+ writeBuffer(writer: Writer): void;
231
+ toBuffer(): Buffer;
232
+ }
233
+ }
234
+
235
+ // ── Servers ─────────────────────────────────────────────────────────────────
236
+
237
+ class UDPServer extends dgram.Socket {
238
+ constructor(options?: UdpServerOptions | DnsHandler);
239
+ handle(data: Buffer, rinfo: dgram.RemoteInfo): void;
240
+ response(rinfo: dgram.RemoteInfo, message: Packet | Buffer): Promise<Buffer>;
241
+ listen(port?: number, address?: string): Promise<void>;
242
+ on(event: 'request', listener: DnsHandler): this;
243
+ on(event: 'requestError', listener: (error: Error) => void): this;
244
+ on(event: 'listening', listener: () => void): this;
245
+ on(event: 'close', listener: () => void): this;
246
+ on(event: string, listener: (...args: any[]) => void): this;
247
+ }
248
+
249
+ class TCPServer extends net.Server {
250
+ constructor(options?: DnsHandler);
251
+ on(event: 'request', listener: DnsHandler): this;
252
+ on(event: 'requestError', listener: (error: Error) => void): this;
253
+ on(event: string, listener: (...args: any[]) => void): this;
254
+ }
255
+
256
+ class DOHServer extends EventEmitter {
257
+ constructor(options?: DohServerOptions);
258
+ listen(port?: number, address?: string): void;
259
+ address(): net.AddressInfo | null;
260
+ close(): void;
261
+ on(event: 'request', listener: DnsHandler): this;
262
+ on(event: 'requestError', listener: (error: Error) => void): this;
263
+ on(event: 'listening', listener: (address: net.AddressInfo) => void): this;
264
+ on(event: 'close', listener: () => void): this;
265
+ on(event: string, listener: (...args: any[]) => void): this;
266
+ }
267
+
268
+ class DnsServer extends EventEmitter {
269
+ constructor(options: CreateServerOptions);
270
+ addresses(): ServerAddresses;
271
+ listen(options?: DnsServerListenOptions): Promise<ServerAddresses>;
272
+ close(): Promise<void>;
273
+ on(event: 'request', listener: DnsHandler): this;
274
+ on(event: 'requestError', listener: (error: Error) => void): this;
275
+ on(event: 'listening', listener: (addresses: ServerAddresses) => void): this;
276
+ on(event: 'close', listener: () => void): this;
277
+ on(event: 'error', listener: (error: Error, transport: 'udp' | 'tcp' | 'doh') => void): this;
278
+ on(event: string, listener: (...args: any[]) => void): this;
279
+ }
280
+
281
+ // ── Handler & resolver callable types ────────────────────────────────────────
282
+
283
+ type DnsHandler = (
284
+ request: Packet,
285
+ send: (response: Packet | Buffer) => Promise<Buffer>,
286
+ client: dgram.RemoteInfo | net.Socket | http.IncomingMessage,
287
+ ) => void;
288
+
289
+ type DnsResolver = (
290
+ name: string,
291
+ type?: string,
292
+ cls?: number,
293
+ options?: ResolveOptions,
294
+ ) => Promise<Packet>;
295
+
296
+ // ── Options ──────────────────────────────────────────────────────────────────
297
+
298
+ interface ClientOptions {
299
+ port: number;
300
+ retries: number;
301
+ timeout: number;
302
+ recursive: boolean;
303
+ /** When using UDP and the TC (truncated) bit is set, automatically retry over TCP. Default: `true`. */
304
+ retryOverTCP: boolean;
305
+ resolverProtocol: 'UDP' | 'TCP' | 'DOH' | 'Google';
306
+ /** Shorthand alias for `nameServers`. A single IP string or an array. */
307
+ dns?: string | string[];
308
+ nameServers: string[];
309
+ rootServers: string[];
310
+ }
311
+
312
+ interface ResolveOptions {
313
+ recursive?: boolean;
314
+ /** EDNS ECS client subnet in CIDR notation, e.g. `"1.2.3.4/24"` */
315
+ clientIp?: string;
316
+ }
317
+
318
+ interface UdpClientOptions {
319
+ dns?: string;
320
+ port?: number;
321
+ socketType?: dgram.SocketType;
322
+ timeout?: number;
323
+ /** When the TC (truncated) bit is set, automatically retry over TCP. Default: `true`. */
324
+ retryOverTCP?: boolean;
325
+ }
326
+
327
+ interface TcpClientOptions {
328
+ dns: string;
329
+ protocol?: 'tcp:' | 'tls:';
330
+ port?: number;
331
+ }
332
+
333
+ interface DohClientOptions {
334
+ dns: string;
335
+ }
336
+
337
+ interface UdpServerOptions {
338
+ type?: 'udp4' | 'udp6';
339
+ }
340
+
341
+ interface DohServerOptions {
342
+ port?: number;
343
+ ssl?: boolean;
344
+ cors?: boolean | string | ((origin: string) => boolean);
345
+ [key: string]: any;
346
+ }
347
+
348
+ type ListenOptions = number | { port?: number; address?: string };
349
+
350
+ interface DnsServerListenOptions {
351
+ udp?: ListenOptions;
352
+ tcp?: ListenOptions;
353
+ doh?: ListenOptions;
354
+ }
355
+
356
+ interface CreateServerOptions {
357
+ udp?: boolean | UdpServerOptions;
358
+ tcp?: boolean;
359
+ doh?: boolean | DohServerOptions;
360
+ handle?: DnsHandler;
361
+ maxConcurrent?: number;
362
+ }
363
+
364
+ interface ServerAddresses {
365
+ udp?: net.AddressInfo;
366
+ tcp?: net.AddressInfo;
367
+ doh?: net.AddressInfo;
368
+ }
369
+ }
370
+
371
+ export = DNS;
@@ -0,0 +1,13 @@
1
+ {
2
+ "compilerOptions": {
3
+ "target": "ES2019",
4
+ "module": "commonjs",
5
+ "moduleResolution": "node",
6
+ "strict": true,
7
+ "noEmit": true,
8
+ "esModuleInterop": true,
9
+ "ignoreDeprecations": "6.0",
10
+ "typeRoots": ["../node_modules/@types"]
11
+ },
12
+ "include": ["typings-check.ts"]
13
+ }
@@ -0,0 +1,124 @@
1
+ /**
2
+ * Type-check smoke test for index.d.ts.
3
+ *
4
+ * This file is NOT executed at runtime. It exists solely so that `tsc` can
5
+ * verify that index.d.ts accurately describes the package's public API.
6
+ * CI runs `tsc --project tsconfig.json` and fails if there are type errors.
7
+ *
8
+ * Add a line here whenever a new public API surface is added to index.js.
9
+ */
10
+
11
+ import DNS = require('./index');
12
+ import type { AddressInfo } from 'node:net';
13
+
14
+ const { Packet } = DNS;
15
+
16
+ // ── DNS instance (high-level resolver) ────────────────────────────────────────
17
+
18
+ const dns = new DNS({ nameServers: ['8.8.8.8'], port: 53, recursive: true });
19
+
20
+ void dns.resolve('example.com', 'A');
21
+ void dns.resolveA('example.com');
22
+ void dns.resolveA('example.com', '1.2.3.4');
23
+ void dns.resolveAAAA('example.com');
24
+ void dns.resolveMX('example.com');
25
+ void dns.resolveCNAME('www.example.com');
26
+ void dns.resolvePTR('1.0.0.127.in-addr.arpa');
27
+ void dns.resolveDNSKEY('example.com');
28
+ void dns.resolveRRSIG('example.com');
29
+ void dns.resolveSOA('example.com');
30
+
31
+ dns.resolve('example.com').then((packet: DNS.Packet) => {
32
+ const hdr: DNS.Packet.Header = packet.header;
33
+ const _id: number = hdr.id;
34
+ const _rc: number = hdr.rcode;
35
+ const answer: DNS.Packet.Resource = packet.answers[0];
36
+ const _addr: string | undefined = answer.address;
37
+ const _ttl: number = answer.ttl;
38
+ });
39
+
40
+ // ── Packet static constants ───────────────────────────────────────────────────
41
+
42
+ const _typeA: number = Packet.TYPE.A;
43
+ const _typeAAAA: number = Packet.TYPE.AAAA;
44
+ const _typeMX: number = Packet.TYPE.MX;
45
+ const _typeDNSKEY: number = Packet.TYPE.DNSKEY;
46
+ const _classIN: number = Packet.CLASS.IN;
47
+ const _ecsCode: number = Packet.EDNS_OPTION_CODE.ECS;
48
+
49
+ // ── Packet static helpers ─────────────────────────────────────────────────────
50
+
51
+ const buf = Buffer.alloc(12);
52
+ const parsed: DNS.Packet = Packet.parse(buf);
53
+ const response: DNS.Packet = Packet.createResponseFromRequest(parsed);
54
+ response.header.rcode = 3; // NXDOMAIN
55
+
56
+ const q: DNS.Packet.Question = parsed.questions[0];
57
+ if (q) {
58
+ Packet.createResourceFromQuestion(q, { address: '1.2.3.4', ttl: 60 });
59
+ }
60
+
61
+ // ── Packet encode / round-trip ────────────────────────────────────────────────
62
+
63
+ const pkt = new Packet();
64
+ pkt.header.qr = 1;
65
+ const encoded: Buffer = pkt.toBuffer();
66
+ Packet.parse(encoded);
67
+
68
+ // ── Multi-server (DnsServer) ──────────────────────────────────────────────────
69
+
70
+ const server: DNS.DnsServer = DNS.createServer({
71
+ udp: true,
72
+ tcp: true,
73
+ maxConcurrent: 100,
74
+ handle: (request, send, _client) => {
75
+ const res = Packet.createResponseFromRequest(request);
76
+ res.header.rcode = 5; // REFUSED
77
+ void send(res);
78
+ },
79
+ });
80
+
81
+ server.listen({ udp: { port: 53 }, tcp: 5353 }).then((addrs: DNS.ServerAddresses) => {
82
+ const _udp: AddressInfo | undefined = addrs.udp;
83
+ });
84
+
85
+ server.on('request', (req, send, _client) => {
86
+ void send(Packet.createResponseFromRequest(req));
87
+ });
88
+
89
+ server.on('error', (err: Error, transport: 'udp' | 'tcp' | 'doh') => {
90
+ void err;
91
+ void transport;
92
+ });
93
+
94
+ void server.close();
95
+
96
+ // ── Individual server factories ───────────────────────────────────────────────
97
+
98
+ const udpServer: DNS.UDPServer = DNS.createUDPServer({ type: 'udp4' });
99
+ udpServer.on('request', (req, send) => { void send(req); });
100
+
101
+ const tcpServer: DNS.TCPServer = DNS.createTCPServer();
102
+ tcpServer.on('request', (req, send) => { void send(req); });
103
+
104
+ const dohServer: DNS.DOHServer = DNS.createDOHServer({ ssl: false, cors: true });
105
+ dohServer.on('request', (req, send) => { void send(req); });
106
+
107
+ // ── Client factories ──────────────────────────────────────────────────────────
108
+
109
+ const udpClient: DNS.DnsResolver = DNS.UDPClient({ dns: '8.8.8.8', port: 53 });
110
+ const tcpClient: DNS.DnsResolver = DNS.TCPClient({ dns: '8.8.8.8', protocol: 'tcp:' });
111
+ const dohClient: DNS.DnsResolver = DNS.DOHClient({ dns: 'https://cloudflare-dns.com/dns-query' });
112
+ const googleClient: DNS.DnsResolver = DNS.GoogleClient();
113
+
114
+ void udpClient('example.com', 'A');
115
+ void tcpClient('example.com', 'MX');
116
+ void dohClient('example.com', 'AAAA');
117
+ void googleClient('example.com');
118
+
119
+ // ── Sub-class type assignability ──────────────────────────────────────────────
120
+
121
+ const _dnsServer: DNS.DnsServer = DNS.createServer({ udp: true });
122
+ const _udp: DNS.UDPServer = DNS.createUDPServer();
123
+ const _tcp: DNS.TCPServer = DNS.createTCPServer();
124
+ const _doh: DNS.DOHServer = DNS.createDOHServer();
package/.eslintrc DELETED
@@ -1,16 +0,0 @@
1
- {
2
- "extends": "semistandard",
3
- "rules": {
4
- "space-before-function-paren": ["error", "never"],
5
- "no-multi-spaces": ["error"],
6
- "array-bracket-spacing": ["error", "always"],
7
- "key-spacing": ["error", {
8
- "align": {
9
- "beforeColon": true,
10
- "afterColon": true,
11
- "on": "colon"
12
- }
13
- }],
14
- "comma-dangle": ["error", "always-multiline"]
15
- }
16
- }
@@ -1,12 +0,0 @@
1
- # These are supported funding model platforms
2
-
3
- github: song940
4
- patreon: song940
5
- open_collective: song940
6
- ko_fi: # Replace with a single Ko-fi username
7
- tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel
8
- community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry
9
- liberapay: # Replace with a single Liberapay username
10
- issuehunt: # Replace with a single IssueHunt username
11
- otechie: # Replace with a single Otechie username
12
- custom: https://git.io/fjRcB
@@ -1,17 +0,0 @@
1
- # This workflow will do a clean install of node dependencies, build the source code and run tests across different versions of node
2
- # For more information see: https://help.github.com/actions/language-and-framework-guides/using-nodejs-with-github-actions
3
-
4
- name: Linting
5
-
6
- on: [push, pull_request]
7
-
8
- jobs:
9
- build:
10
- runs-on: ubuntu-latest
11
- steps:
12
- - uses: actions/checkout@v2
13
- - uses: actions/setup-node@v1
14
- with:
15
- node-version: 16
16
- - run: npm i
17
- - run: npm run lint
@@ -1,29 +0,0 @@
1
- # This workflow will do a clean install of node dependencies, build the source code and run tests across different versions of node
2
- # For more information see: https://help.github.com/actions/language-and-framework-guides/using-nodejs-with-github-actions
3
-
4
- name: Node.js CI
5
-
6
- on:
7
- push:
8
- branches: [ master ]
9
- pull_request:
10
- branches: [ master ]
11
-
12
- jobs:
13
- build:
14
-
15
- runs-on: ubuntu-latest
16
-
17
- strategy:
18
- matrix:
19
- node-version: [10.x, 12.x, 14.x, 16.x]
20
- # See supported Node.js release schedule at https://nodejs.org/en/about/releases/
21
-
22
- steps:
23
- - uses: actions/checkout@v2
24
- - name: Use Node.js ${{ matrix.node-version }}
25
- uses: actions/setup-node@v1
26
- with:
27
- node-version: ${{ matrix.node-version }}
28
- - run: npm ci
29
- - run: npm test
package/SECURITY.md DELETED
@@ -1,21 +0,0 @@
1
- # Security Policy
2
-
3
- ## Supported Versions
4
-
5
- Use this section to tell people about which versions of your project are
6
- currently being supported with security updates.
7
-
8
- | Version | Supported |
9
- | ------- | ------------------ |
10
- | 5.1.x | :white_check_mark: |
11
- | 5.0.x | :x: |
12
- | 4.0.x | :white_check_mark: |
13
- | < 4.0 | :x: |
14
-
15
- ## Reporting a Vulnerability
16
-
17
- Use this section to tell people how to report a vulnerability.
18
-
19
- Tell them where to go, how often they can expect to get an update on a
20
- reported vulnerability, what to expect if the vulnerability is accepted or
21
- declined, etc.