@push.rocks/smartdns 7.1.0 → 7.4.0
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_ts/00_commitinfo_data.js +1 -1
- package/dist_ts_server/classes.dnsserver.d.ts +45 -0
- package/dist_ts_server/classes.dnsserver.js +201 -41
- package/dist_ts_server/plugins.d.ts +2 -1
- package/dist_ts_server/plugins.js +3 -2
- package/package.json +2 -2
- package/readme.md +274 -0
- package/readme.plan.md +103 -0
- package/ts/00_commitinfo_data.ts +1 -1
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
*/
|
|
4
4
|
export const commitinfo = {
|
|
5
5
|
name: '@push.rocks/smartdns',
|
|
6
|
-
version: '7.
|
|
6
|
+
version: '7.4.0',
|
|
7
7
|
description: 'A robust TypeScript library providing advanced DNS management and resolution capabilities including support for DNSSEC, custom DNS servers, and integration with various DNS providers.'
|
|
8
8
|
};
|
|
9
9
|
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiMDBfY29tbWl0aW5mb19kYXRhLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vdHMvMDBfY29tbWl0aW5mb19kYXRhLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBOztHQUVHO0FBQ0gsTUFBTSxDQUFDLE1BQU0sVUFBVSxHQUFHO0lBQ3hCLElBQUksRUFBRSxzQkFBc0I7SUFDNUIsT0FBTyxFQUFFLE9BQU87SUFDaEIsV0FBVyxFQUFFLHlMQUF5TDtDQUN2TSxDQUFBIn0=
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import * as plugins from './plugins.js';
|
|
1
2
|
import * as dnsPacket from 'dns-packet';
|
|
2
3
|
export interface IDnsServerOptions {
|
|
3
4
|
httpsKey: string;
|
|
@@ -5,6 +6,10 @@ export interface IDnsServerOptions {
|
|
|
5
6
|
httpsPort: number;
|
|
6
7
|
udpPort: number;
|
|
7
8
|
dnssecZone: string;
|
|
9
|
+
udpBindInterface?: string;
|
|
10
|
+
httpsBindInterface?: string;
|
|
11
|
+
manualUdpMode?: boolean;
|
|
12
|
+
manualHttpsMode?: boolean;
|
|
8
13
|
}
|
|
9
14
|
export interface DnsAnswer {
|
|
10
15
|
name: string;
|
|
@@ -31,7 +36,39 @@ export declare class DnsServer {
|
|
|
31
36
|
private dnsSec;
|
|
32
37
|
private dnskeyRecord;
|
|
33
38
|
private keyTag;
|
|
39
|
+
private udpServerInitialized;
|
|
40
|
+
private httpsServerInitialized;
|
|
34
41
|
constructor(options: IDnsServerOptions);
|
|
42
|
+
/**
|
|
43
|
+
* Initialize servers without binding to ports
|
|
44
|
+
* This is called automatically by start() or can be called manually
|
|
45
|
+
*/
|
|
46
|
+
initializeServers(): void;
|
|
47
|
+
/**
|
|
48
|
+
* Initialize UDP server without binding
|
|
49
|
+
*/
|
|
50
|
+
initializeUdpServer(): void;
|
|
51
|
+
/**
|
|
52
|
+
* Initialize HTTPS server without binding
|
|
53
|
+
*/
|
|
54
|
+
initializeHttpsServer(): void;
|
|
55
|
+
/**
|
|
56
|
+
* Handle a raw TCP socket for HTTPS/DoH
|
|
57
|
+
* @param socket The TCP socket to handle
|
|
58
|
+
*/
|
|
59
|
+
handleHttpsSocket(socket: plugins.net.Socket): void;
|
|
60
|
+
/**
|
|
61
|
+
* Handle a UDP message manually
|
|
62
|
+
* @param msg The DNS message buffer
|
|
63
|
+
* @param rinfo Remote address information
|
|
64
|
+
* @param responseCallback Optional callback to handle the response
|
|
65
|
+
*/
|
|
66
|
+
handleUdpMessage(msg: Buffer, rinfo: plugins.dgram.RemoteInfo, responseCallback?: (response: Buffer, rinfo: plugins.dgram.RemoteInfo) => void): void;
|
|
67
|
+
/**
|
|
68
|
+
* Process a raw DNS packet and return the response
|
|
69
|
+
* This is useful for custom transport implementations
|
|
70
|
+
*/
|
|
71
|
+
processRawDnsPacket(packet: Buffer): Buffer;
|
|
35
72
|
registerHandler(domainPattern: string, recordTypes: string[], handler: (question: dnsPacket.Question) => DnsAnswer | null): void;
|
|
36
73
|
unregisterHandler(domainPattern: string, recordTypes: string[]): boolean;
|
|
37
74
|
/**
|
|
@@ -57,6 +94,14 @@ export declare class DnsServer {
|
|
|
57
94
|
* Filter domains to include only those the server is authoritative for
|
|
58
95
|
*/
|
|
59
96
|
filterAuthorizedDomains(domainNames: string[]): string[];
|
|
97
|
+
/**
|
|
98
|
+
* Validate if a string is a valid IP address (IPv4 or IPv6)
|
|
99
|
+
*/
|
|
100
|
+
private isValidIpAddress;
|
|
101
|
+
/**
|
|
102
|
+
* Determine if an IP address is IPv6
|
|
103
|
+
*/
|
|
104
|
+
private isIPv6;
|
|
60
105
|
/**
|
|
61
106
|
* Check if the server is authoritative for a domain
|
|
62
107
|
*/
|
|
@@ -5,6 +5,9 @@ export class DnsServer {
|
|
|
5
5
|
constructor(options) {
|
|
6
6
|
this.options = options;
|
|
7
7
|
this.handlers = [];
|
|
8
|
+
// Track if servers are initialized
|
|
9
|
+
this.udpServerInitialized = false;
|
|
10
|
+
this.httpsServerInitialized = false;
|
|
8
11
|
// Initialize DNSSEC
|
|
9
12
|
this.dnsSec = new DnsSec({
|
|
10
13
|
zone: options.dnssecZone,
|
|
@@ -13,11 +16,105 @@ export class DnsServer {
|
|
|
13
16
|
days: 365,
|
|
14
17
|
});
|
|
15
18
|
// Generate DNSKEY and DS records
|
|
16
|
-
const {
|
|
19
|
+
const { dnskeyRecord } = this.dnsSec.getDsAndKeyPair();
|
|
17
20
|
// Parse DNSKEY record into dns-packet format
|
|
18
21
|
this.dnskeyRecord = this.parseDNSKEYRecord(dnskeyRecord);
|
|
19
22
|
this.keyTag = this.computeKeyTag(this.dnskeyRecord);
|
|
20
23
|
}
|
|
24
|
+
/**
|
|
25
|
+
* Initialize servers without binding to ports
|
|
26
|
+
* This is called automatically by start() or can be called manually
|
|
27
|
+
*/
|
|
28
|
+
initializeServers() {
|
|
29
|
+
this.initializeUdpServer();
|
|
30
|
+
this.initializeHttpsServer();
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Initialize UDP server without binding
|
|
34
|
+
*/
|
|
35
|
+
initializeUdpServer() {
|
|
36
|
+
if (this.udpServerInitialized) {
|
|
37
|
+
return;
|
|
38
|
+
}
|
|
39
|
+
// Create UDP socket without binding
|
|
40
|
+
const udpInterface = this.options.udpBindInterface || '0.0.0.0';
|
|
41
|
+
const socketType = this.isIPv6(udpInterface) ? 'udp6' : 'udp4';
|
|
42
|
+
this.udpServer = plugins.dgram.createSocket(socketType);
|
|
43
|
+
// Set up UDP message handler
|
|
44
|
+
this.udpServer.on('message', (msg, rinfo) => {
|
|
45
|
+
this.handleUdpMessage(msg, rinfo);
|
|
46
|
+
});
|
|
47
|
+
this.udpServer.on('error', (err) => {
|
|
48
|
+
console.error(`UDP Server error:\n${err.stack}`);
|
|
49
|
+
this.udpServer.close();
|
|
50
|
+
});
|
|
51
|
+
this.udpServerInitialized = true;
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Initialize HTTPS server without binding
|
|
55
|
+
*/
|
|
56
|
+
initializeHttpsServer() {
|
|
57
|
+
if (this.httpsServerInitialized) {
|
|
58
|
+
return;
|
|
59
|
+
}
|
|
60
|
+
// Create HTTPS server without listening
|
|
61
|
+
this.httpsServer = plugins.https.createServer({
|
|
62
|
+
key: this.options.httpsKey,
|
|
63
|
+
cert: this.options.httpsCert,
|
|
64
|
+
}, this.handleHttpsRequest.bind(this));
|
|
65
|
+
this.httpsServerInitialized = true;
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Handle a raw TCP socket for HTTPS/DoH
|
|
69
|
+
* @param socket The TCP socket to handle
|
|
70
|
+
*/
|
|
71
|
+
handleHttpsSocket(socket) {
|
|
72
|
+
if (!this.httpsServer) {
|
|
73
|
+
this.initializeHttpsServer();
|
|
74
|
+
}
|
|
75
|
+
// Emit connection event on the HTTPS server
|
|
76
|
+
this.httpsServer.emit('connection', socket);
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* Handle a UDP message manually
|
|
80
|
+
* @param msg The DNS message buffer
|
|
81
|
+
* @param rinfo Remote address information
|
|
82
|
+
* @param responseCallback Optional callback to handle the response
|
|
83
|
+
*/
|
|
84
|
+
handleUdpMessage(msg, rinfo, responseCallback) {
|
|
85
|
+
try {
|
|
86
|
+
const request = dnsPacket.decode(msg);
|
|
87
|
+
const response = this.processDnsRequest(request);
|
|
88
|
+
const responseData = dnsPacket.encode(response);
|
|
89
|
+
if (responseCallback) {
|
|
90
|
+
// Use custom callback if provided
|
|
91
|
+
responseCallback(responseData, rinfo);
|
|
92
|
+
}
|
|
93
|
+
else if (this.udpServer && !this.options.manualUdpMode) {
|
|
94
|
+
// Use the internal UDP server to send response
|
|
95
|
+
this.udpServer.send(responseData, rinfo.port, rinfo.address);
|
|
96
|
+
}
|
|
97
|
+
// In manual mode without callback, caller is responsible for sending response
|
|
98
|
+
}
|
|
99
|
+
catch (err) {
|
|
100
|
+
console.error('Error processing UDP DNS request:', err);
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
/**
|
|
104
|
+
* Process a raw DNS packet and return the response
|
|
105
|
+
* This is useful for custom transport implementations
|
|
106
|
+
*/
|
|
107
|
+
processRawDnsPacket(packet) {
|
|
108
|
+
try {
|
|
109
|
+
const request = dnsPacket.decode(packet);
|
|
110
|
+
const response = this.processDnsRequest(request);
|
|
111
|
+
return dnsPacket.encode(response);
|
|
112
|
+
}
|
|
113
|
+
catch (err) {
|
|
114
|
+
console.error('Error processing raw DNS packet:', err);
|
|
115
|
+
throw err;
|
|
116
|
+
}
|
|
117
|
+
}
|
|
21
118
|
registerHandler(domainPattern, recordTypes, handler) {
|
|
22
119
|
this.handlers.push({ domainPattern, recordTypes, handler });
|
|
23
120
|
}
|
|
@@ -99,7 +196,7 @@ export class DnsServer {
|
|
|
99
196
|
for (const auth of authorizations) {
|
|
100
197
|
const domain = auth.identifier.value;
|
|
101
198
|
// Get DNS challenge
|
|
102
|
-
const challenge = auth.challenges.find(c => c.type === 'dns-01');
|
|
199
|
+
const challenge = auth.challenges.find((c) => c.type === 'dns-01');
|
|
103
200
|
if (!challenge) {
|
|
104
201
|
throw new Error(`No DNS-01 challenge found for ${domain}`);
|
|
105
202
|
}
|
|
@@ -155,8 +252,10 @@ export class DnsServer {
|
|
|
155
252
|
// Update HTTPS server with new certificate
|
|
156
253
|
this.options.httpsCert = certificate;
|
|
157
254
|
this.options.httpsKey = privateKey;
|
|
158
|
-
// Restart HTTPS server with new certificate
|
|
159
|
-
|
|
255
|
+
// Restart HTTPS server with new certificate (only if not in manual HTTPS mode)
|
|
256
|
+
if (!this.options.manualHttpsMode) {
|
|
257
|
+
await this.restartHttpsServer();
|
|
258
|
+
}
|
|
160
259
|
// Clean up challenge handlers
|
|
161
260
|
for (const handler of challengeHandlers) {
|
|
162
261
|
this.unregisterHandler(handler.pattern, ['TXT']);
|
|
@@ -214,10 +313,16 @@ export class DnsServer {
|
|
|
214
313
|
key: this.options.httpsKey,
|
|
215
314
|
cert: this.options.httpsCert,
|
|
216
315
|
}, this.handleHttpsRequest.bind(this));
|
|
217
|
-
|
|
218
|
-
|
|
316
|
+
if (!this.options.manualHttpsMode) {
|
|
317
|
+
const httpsInterface = this.options.httpsBindInterface || '0.0.0.0';
|
|
318
|
+
this.httpsServer.listen(this.options.httpsPort, httpsInterface, () => {
|
|
319
|
+
console.log(`HTTPS DNS server restarted on ${httpsInterface}:${this.options.httpsPort} with test certificate`);
|
|
320
|
+
resolve();
|
|
321
|
+
});
|
|
322
|
+
}
|
|
323
|
+
else {
|
|
219
324
|
resolve();
|
|
220
|
-
}
|
|
325
|
+
}
|
|
221
326
|
return;
|
|
222
327
|
}
|
|
223
328
|
}
|
|
@@ -226,10 +331,16 @@ export class DnsServer {
|
|
|
226
331
|
key: this.options.httpsKey,
|
|
227
332
|
cert: this.options.httpsCert,
|
|
228
333
|
}, this.handleHttpsRequest.bind(this));
|
|
229
|
-
|
|
230
|
-
|
|
334
|
+
if (!this.options.manualHttpsMode) {
|
|
335
|
+
const httpsInterface = this.options.httpsBindInterface || '0.0.0.0';
|
|
336
|
+
this.httpsServer.listen(this.options.httpsPort, httpsInterface, () => {
|
|
337
|
+
console.log(`HTTPS DNS server restarted on ${httpsInterface}:${this.options.httpsPort} with new certificate`);
|
|
338
|
+
resolve();
|
|
339
|
+
});
|
|
340
|
+
}
|
|
341
|
+
else {
|
|
231
342
|
resolve();
|
|
232
|
-
}
|
|
343
|
+
}
|
|
233
344
|
}
|
|
234
345
|
catch (err) {
|
|
235
346
|
console.error('Error creating HTTPS server with new certificate:', err);
|
|
@@ -258,6 +369,22 @@ export class DnsServer {
|
|
|
258
369
|
}
|
|
259
370
|
return authorizedDomains;
|
|
260
371
|
}
|
|
372
|
+
/**
|
|
373
|
+
* Validate if a string is a valid IP address (IPv4 or IPv6)
|
|
374
|
+
*/
|
|
375
|
+
isValidIpAddress(ip) {
|
|
376
|
+
// IPv4 pattern
|
|
377
|
+
const ipv4Pattern = /^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/;
|
|
378
|
+
// IPv6 pattern (simplified but more comprehensive)
|
|
379
|
+
const ipv6Pattern = /^(::1|::)$|^([0-9a-fA-F]{1,4}:){7}[0-9a-fA-F]{1,4}$/;
|
|
380
|
+
return ipv4Pattern.test(ip) || ipv6Pattern.test(ip);
|
|
381
|
+
}
|
|
382
|
+
/**
|
|
383
|
+
* Determine if an IP address is IPv6
|
|
384
|
+
*/
|
|
385
|
+
isIPv6(ip) {
|
|
386
|
+
return ip.includes(':');
|
|
387
|
+
}
|
|
261
388
|
/**
|
|
262
389
|
* Check if the server is authoritative for a domain
|
|
263
390
|
*/
|
|
@@ -513,38 +640,69 @@ export class DnsServer {
|
|
|
513
640
|
}
|
|
514
641
|
}
|
|
515
642
|
async start() {
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
}, this.handleHttpsRequest.bind(this));
|
|
520
|
-
this.udpServer = plugins.dgram.createSocket('udp4');
|
|
521
|
-
this.udpServer.on('message', (msg, rinfo) => {
|
|
522
|
-
const request = dnsPacket.decode(msg);
|
|
523
|
-
const response = this.processDnsRequest(request);
|
|
524
|
-
const responseData = dnsPacket.encode(response);
|
|
525
|
-
this.udpServer.send(responseData, rinfo.port, rinfo.address);
|
|
526
|
-
});
|
|
527
|
-
this.udpServer.on('error', (err) => {
|
|
528
|
-
console.error(`UDP Server error:\n${err.stack}`);
|
|
529
|
-
this.udpServer.close();
|
|
530
|
-
});
|
|
531
|
-
const udpListeningDeferred = plugins.smartpromise.defer();
|
|
532
|
-
const httpsListeningDeferred = plugins.smartpromise.defer();
|
|
533
|
-
try {
|
|
534
|
-
this.udpServer.bind(this.options.udpPort, '0.0.0.0', () => {
|
|
535
|
-
console.log(`UDP DNS server running on port ${this.options.udpPort}`);
|
|
536
|
-
udpListeningDeferred.resolve();
|
|
537
|
-
});
|
|
538
|
-
this.httpsServer.listen(this.options.httpsPort, () => {
|
|
539
|
-
console.log(`HTTPS DNS server running on port ${this.options.httpsPort}`);
|
|
540
|
-
httpsListeningDeferred.resolve();
|
|
541
|
-
});
|
|
643
|
+
// Initialize servers based on what's needed
|
|
644
|
+
if (!this.options.manualUdpMode) {
|
|
645
|
+
this.initializeUdpServer();
|
|
542
646
|
}
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
647
|
+
if (!this.options.manualHttpsMode) {
|
|
648
|
+
this.initializeHttpsServer();
|
|
649
|
+
}
|
|
650
|
+
// Handle different mode combinations
|
|
651
|
+
const udpManual = this.options.manualUdpMode || false;
|
|
652
|
+
const httpsManual = this.options.manualHttpsMode || false;
|
|
653
|
+
if (udpManual && httpsManual) {
|
|
654
|
+
console.log('DNS server started in full manual mode - ready to accept connections');
|
|
655
|
+
return;
|
|
656
|
+
}
|
|
657
|
+
else if (udpManual && !httpsManual) {
|
|
658
|
+
console.log('DNS server started with manual UDP mode and automatic HTTPS binding');
|
|
659
|
+
}
|
|
660
|
+
else if (!udpManual && httpsManual) {
|
|
661
|
+
console.log('DNS server started with automatic UDP binding and manual HTTPS mode');
|
|
662
|
+
}
|
|
663
|
+
// Validate interface addresses if provided
|
|
664
|
+
const udpInterface = this.options.udpBindInterface || '0.0.0.0';
|
|
665
|
+
const httpsInterface = this.options.httpsBindInterface || '0.0.0.0';
|
|
666
|
+
if (this.options.udpBindInterface && !this.isValidIpAddress(this.options.udpBindInterface)) {
|
|
667
|
+
throw new Error(`Invalid UDP bind interface: ${this.options.udpBindInterface}`);
|
|
668
|
+
}
|
|
669
|
+
if (this.options.httpsBindInterface && !this.isValidIpAddress(this.options.httpsBindInterface)) {
|
|
670
|
+
throw new Error(`Invalid HTTPS bind interface: ${this.options.httpsBindInterface}`);
|
|
671
|
+
}
|
|
672
|
+
const promises = [];
|
|
673
|
+
// Bind UDP if not in manual UDP mode
|
|
674
|
+
if (!udpManual) {
|
|
675
|
+
const udpListeningDeferred = plugins.smartpromise.defer();
|
|
676
|
+
promises.push(udpListeningDeferred.promise);
|
|
677
|
+
try {
|
|
678
|
+
this.udpServer.bind(this.options.udpPort, udpInterface, () => {
|
|
679
|
+
console.log(`UDP DNS server running on ${udpInterface}:${this.options.udpPort}`);
|
|
680
|
+
udpListeningDeferred.resolve();
|
|
681
|
+
});
|
|
682
|
+
}
|
|
683
|
+
catch (err) {
|
|
684
|
+
console.error('Error starting UDP DNS server:', err);
|
|
685
|
+
udpListeningDeferred.reject(err);
|
|
686
|
+
}
|
|
687
|
+
}
|
|
688
|
+
// Bind HTTPS if not in manual HTTPS mode
|
|
689
|
+
if (!httpsManual) {
|
|
690
|
+
const httpsListeningDeferred = plugins.smartpromise.defer();
|
|
691
|
+
promises.push(httpsListeningDeferred.promise);
|
|
692
|
+
try {
|
|
693
|
+
this.httpsServer.listen(this.options.httpsPort, httpsInterface, () => {
|
|
694
|
+
console.log(`HTTPS DNS server running on ${httpsInterface}:${this.options.httpsPort}`);
|
|
695
|
+
httpsListeningDeferred.resolve();
|
|
696
|
+
});
|
|
697
|
+
}
|
|
698
|
+
catch (err) {
|
|
699
|
+
console.error('Error starting HTTPS DNS server:', err);
|
|
700
|
+
httpsListeningDeferred.reject(err);
|
|
701
|
+
}
|
|
702
|
+
}
|
|
703
|
+
if (promises.length > 0) {
|
|
704
|
+
await Promise.all(promises);
|
|
546
705
|
}
|
|
547
|
-
await Promise.all([udpListeningDeferred.promise, httpsListeningDeferred.promise]);
|
|
548
706
|
}
|
|
549
707
|
async stop() {
|
|
550
708
|
const doneUdp = plugins.smartpromise.defer();
|
|
@@ -576,6 +734,8 @@ export class DnsServer {
|
|
|
576
734
|
doneHttps.resolve();
|
|
577
735
|
}
|
|
578
736
|
await Promise.all([doneUdp.promise, doneHttps.promise]);
|
|
737
|
+
this.udpServerInitialized = false;
|
|
738
|
+
this.httpsServerInitialized = false;
|
|
579
739
|
}
|
|
580
740
|
// Helper methods
|
|
581
741
|
qtypeToNumber(type) {
|
|
@@ -619,4 +779,4 @@ export class DnsServer {
|
|
|
619
779
|
return Buffer.concat([...buffers, Buffer.from([0])]); // Add root label
|
|
620
780
|
}
|
|
621
781
|
}
|
|
622
|
-
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2xhc3Nlcy5kbnNzZXJ2ZXIuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi90c19zZXJ2ZXIvY2xhc3Nlcy5kbnNzZXJ2ZXIudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxLQUFLLE9BQU8sTUFBTSxjQUFjLENBQUM7QUFDeEMsT0FBTyxFQUFFLE1BQU0sRUFBRSxNQUFNLHFCQUFxQixDQUFDO0FBQzdDLE9BQU8sS0FBSyxTQUFTLE1BQU0sWUFBWSxDQUFDO0FBa0R4QyxNQUFNLE9BQU8sU0FBUztJQVVwQixZQUFvQixPQUEwQjtRQUExQixZQUFPLEdBQVAsT0FBTyxDQUFtQjtRQVB0QyxhQUFRLEdBQWtCLEVBQUUsQ0FBQztRQVFuQyxvQkFBb0I7UUFDcEIsSUFBSSxDQUFDLE1BQU0sR0FBRyxJQUFJLE1BQU0sQ0FBQztZQUN2QixJQUFJLEVBQUUsT0FBTyxDQUFDLFVBQVU7WUFDeEIsU0FBUyxFQUFFLE9BQU8sRUFBRSwwQ0FBMEM7WUFDOUQsT0FBTyxFQUFFLEdBQUc7WUFDWixJQUFJLEVBQUUsR0FBRztTQUNWLENBQUMsQ0FBQztRQUVILGlDQUFpQztRQUNqQyxNQUFNLEVBQUUsUUFBUSxFQUFFLFlBQVksRUFBRSxHQUFHLElBQUksQ0FBQyxNQUFNLENBQUMsZUFBZSxFQUFFLENBQUM7UUFFakUsNkNBQTZDO1FBQzdDLElBQUksQ0FBQyxZQUFZLEdBQUcsSUFBSSxDQUFDLGlCQUFpQixDQUFDLFlBQVksQ0FBQyxDQUFDO1FBQ3pELElBQUksQ0FBQyxNQUFNLEdBQUcsSUFBSSxDQUFDLGFBQWEsQ0FBQyxJQUFJLENBQUMsWUFBWSxDQUFDLENBQUM7SUFDdEQsQ0FBQztJQUVNLGVBQWUsQ0FDcEIsYUFBcUIsRUFDckIsV0FBcUIsRUFDckIsT0FBMkQ7UUFFM0QsSUFBSSxDQUFDLFFBQVEsQ0FBQyxJQUFJLENBQUMsRUFBRSxhQUFhLEVBQUUsV0FBVyxFQUFFLE9BQU8sRUFBRSxDQUFDLENBQUM7SUFDOUQsQ0FBQztJQUVE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
|
|
782
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2xhc3Nlcy5kbnNzZXJ2ZXIuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi90c19zZXJ2ZXIvY2xhc3Nlcy5kbnNzZXJ2ZXIudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxLQUFLLE9BQU8sTUFBTSxjQUFjLENBQUM7QUFDeEMsT0FBTyxFQUFFLE1BQU0sRUFBRSxNQUFNLHFCQUFxQixDQUFDO0FBQzdDLE9BQU8sS0FBSyxTQUFTLE1BQU0sWUFBWSxDQUFDO0FBMkN4QyxNQUFNLE9BQU8sU0FBUztJQWNwQixZQUFvQixPQUEwQjtRQUExQixZQUFPLEdBQVAsT0FBTyxDQUFtQjtRQVh0QyxhQUFRLEdBQWtCLEVBQUUsQ0FBQztRQU9yQyxtQ0FBbUM7UUFDM0IseUJBQW9CLEdBQVksS0FBSyxDQUFDO1FBQ3RDLDJCQUFzQixHQUFZLEtBQUssQ0FBQztRQUc5QyxvQkFBb0I7UUFDcEIsSUFBSSxDQUFDLE1BQU0sR0FBRyxJQUFJLE1BQU0sQ0FBQztZQUN2QixJQUFJLEVBQUUsT0FBTyxDQUFDLFVBQVU7WUFDeEIsU0FBUyxFQUFFLE9BQU8sRUFBRSwwQ0FBMEM7WUFDOUQsT0FBTyxFQUFFLEdBQUc7WUFDWixJQUFJLEVBQUUsR0FBRztTQUNWLENBQUMsQ0FBQztRQUVILGlDQUFpQztRQUNqQyxNQUFNLEVBQUUsWUFBWSxFQUFFLEdBQUcsSUFBSSxDQUFDLE1BQU0sQ0FBQyxlQUFlLEVBQUUsQ0FBQztRQUV2RCw2Q0FBNkM7UUFDN0MsSUFBSSxDQUFDLFlBQVksR0FBRyxJQUFJLENBQUMsaUJBQWlCLENBQUMsWUFBWSxDQUFDLENBQUM7UUFDekQsSUFBSSxDQUFDLE1BQU0sR0FBRyxJQUFJLENBQUMsYUFBYSxDQUFDLElBQUksQ0FBQyxZQUFZLENBQUMsQ0FBQztJQUN0RCxDQUFDO0lBRUQ7OztPQUdHO0lBQ0ksaUJBQWlCO1FBQ3RCLElBQUksQ0FBQyxtQkFBbUIsRUFBRSxDQUFDO1FBQzNCLElBQUksQ0FBQyxxQkFBcUIsRUFB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
|
|
@@ -3,8 +3,9 @@ import dgram from 'dgram';
|
|
|
3
3
|
import fs from 'fs';
|
|
4
4
|
import http from 'http';
|
|
5
5
|
import https from 'https';
|
|
6
|
+
import * as net from 'net';
|
|
6
7
|
import * as path from 'path';
|
|
7
|
-
export { crypto, fs, http, https,
|
|
8
|
+
export { crypto, dgram, fs, http, https, net, path, };
|
|
8
9
|
import * as smartpromise from '@push.rocks/smartpromise';
|
|
9
10
|
export { smartpromise, };
|
|
10
11
|
import elliptic from 'elliptic';
|
|
@@ -4,8 +4,9 @@ import dgram from 'dgram';
|
|
|
4
4
|
import fs from 'fs';
|
|
5
5
|
import http from 'http';
|
|
6
6
|
import https from 'https';
|
|
7
|
+
import * as net from 'net';
|
|
7
8
|
import * as path from 'path';
|
|
8
|
-
export { crypto, fs, http, https,
|
|
9
|
+
export { crypto, dgram, fs, http, https, net, path, };
|
|
9
10
|
// @push.rocks scope
|
|
10
11
|
import * as smartpromise from '@push.rocks/smartpromise';
|
|
11
12
|
export { smartpromise, };
|
|
@@ -14,4 +15,4 @@ import elliptic from 'elliptic';
|
|
|
14
15
|
import * as dnsPacket from 'dns-packet';
|
|
15
16
|
import * as minimatch from 'minimatch';
|
|
16
17
|
export { dnsPacket, elliptic, minimatch, };
|
|
17
|
-
//# sourceMappingURL=data:application/json;base64,
|
|
18
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicGx1Z2lucy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uL3RzX3NlcnZlci9wbHVnaW5zLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLGNBQWM7QUFDZCxPQUFPLE1BQU0sTUFBTSxRQUFRLENBQUM7QUFDNUIsT0FBTyxLQUFLLE1BQU0sT0FBTyxDQUFDO0FBQzFCLE9BQU8sRUFBRSxNQUFNLElBQUksQ0FBQztBQUNwQixPQUFPLElBQUksTUFBTSxNQUFNLENBQUM7QUFDeEIsT0FBTyxLQUFLLE1BQU0sT0FBTyxDQUFDO0FBQzFCLE9BQU8sS0FBSyxHQUFHLE1BQU0sS0FBSyxDQUFDO0FBQzNCLE9BQU8sS0FBSyxJQUFJLE1BQU0sTUFBTSxDQUFDO0FBRTdCLE9BQU8sRUFDTCxNQUFNLEVBQ04sS0FBSyxFQUNMLEVBQUUsRUFDRixJQUFJLEVBQ0osS0FBSyxFQUNMLEdBQUcsRUFDSCxJQUFJLEdBQ0wsQ0FBQTtBQUVELG9CQUFvQjtBQUNwQixPQUFPLEtBQUssWUFBWSxNQUFNLDBCQUEwQixDQUFDO0FBRXpELE9BQU8sRUFDTCxZQUFZLEdBQ2IsQ0FBQTtBQUVELGNBQWM7QUFDZCxPQUFPLFFBQVEsTUFBTSxVQUFVLENBQUM7QUFDaEMsT0FBTyxLQUFLLFNBQVMsTUFBTSxZQUFZLENBQUM7QUFDeEMsT0FBTyxLQUFLLFNBQVMsTUFBTSxXQUFXLENBQUM7QUFFdkMsT0FBTyxFQUNMLFNBQVMsRUFDVCxRQUFRLEVBQ1IsU0FBUyxHQUNWLENBQUEifQ==
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@push.rocks/smartdns",
|
|
3
|
-
"version": "7.
|
|
3
|
+
"version": "7.4.0",
|
|
4
4
|
"private": false,
|
|
5
5
|
"description": "A robust TypeScript library providing advanced DNS management and resolution capabilities including support for DNSSEC, custom DNS servers, and integration with various DNS providers.",
|
|
6
6
|
"exports": {
|
|
@@ -73,7 +73,7 @@
|
|
|
73
73
|
],
|
|
74
74
|
"type": "module",
|
|
75
75
|
"scripts": {
|
|
76
|
-
"test": "(tstest test/)",
|
|
76
|
+
"test": "(tstest test/ --verbose --timeout 60)",
|
|
77
77
|
"build": "(tsbuild tsfolders --web --allowimplicitany)",
|
|
78
78
|
"buildDocs": "tsdoc"
|
|
79
79
|
}
|
package/readme.md
CHANGED
|
@@ -190,6 +190,17 @@ const dnsServer = new DnsServer({
|
|
|
190
190
|
dnssecZone: 'example.com' // Optional: enable DNSSEC for this zone
|
|
191
191
|
});
|
|
192
192
|
|
|
193
|
+
// For enhanced security, bind to specific interfaces
|
|
194
|
+
const secureServer = new DnsServer({
|
|
195
|
+
udpPort: 53,
|
|
196
|
+
httpsPort: 443,
|
|
197
|
+
httpsKey: 'path/to/key.pem',
|
|
198
|
+
httpsCert: 'path/to/cert.pem',
|
|
199
|
+
dnssecZone: 'example.com',
|
|
200
|
+
udpBindInterface: '127.0.0.1', // Bind UDP to localhost only
|
|
201
|
+
httpsBindInterface: '127.0.0.1' // Bind HTTPS to localhost only
|
|
202
|
+
});
|
|
203
|
+
|
|
193
204
|
// Register a handler for all subdomains of example.com
|
|
194
205
|
dnsServer.registerHandler('*.example.com', ['A'], (question) => ({
|
|
195
206
|
name: question.name,
|
|
@@ -295,6 +306,215 @@ await dnsServer.start();
|
|
|
295
306
|
console.log('DNS Server with Let\'s Encrypt SSL started!');
|
|
296
307
|
```
|
|
297
308
|
|
|
309
|
+
### Manual Socket Handling
|
|
310
|
+
|
|
311
|
+
The DNS server supports manual socket handling for advanced use cases like clustering, load balancing, and custom transport implementations. You can control UDP and HTTPS socket handling independently.
|
|
312
|
+
|
|
313
|
+
#### Configuration Options
|
|
314
|
+
|
|
315
|
+
```typescript
|
|
316
|
+
export interface IDnsServerOptions {
|
|
317
|
+
// ... standard options ...
|
|
318
|
+
manualUdpMode?: boolean; // Handle UDP sockets manually
|
|
319
|
+
manualHttpsMode?: boolean; // Handle HTTPS sockets manually
|
|
320
|
+
}
|
|
321
|
+
```
|
|
322
|
+
|
|
323
|
+
#### Basic Manual Socket Usage
|
|
324
|
+
|
|
325
|
+
```typescript
|
|
326
|
+
import { DnsServer } from '@push.rocks/smartdns/server';
|
|
327
|
+
import * as dgram from 'dgram';
|
|
328
|
+
import * as net from 'net';
|
|
329
|
+
|
|
330
|
+
// Create server with manual UDP mode
|
|
331
|
+
const dnsServer = new DnsServer({
|
|
332
|
+
httpsKey: '...',
|
|
333
|
+
httpsCert: '...',
|
|
334
|
+
httpsPort: 853,
|
|
335
|
+
udpPort: 53,
|
|
336
|
+
dnssecZone: 'example.com',
|
|
337
|
+
manualUdpMode: true // UDP manual, HTTPS automatic
|
|
338
|
+
});
|
|
339
|
+
|
|
340
|
+
await dnsServer.start(); // HTTPS binds, UDP doesn't
|
|
341
|
+
|
|
342
|
+
// Create your own UDP socket
|
|
343
|
+
const udpSocket = dgram.createSocket('udp4');
|
|
344
|
+
|
|
345
|
+
// Handle incoming UDP messages
|
|
346
|
+
udpSocket.on('message', (msg, rinfo) => {
|
|
347
|
+
dnsServer.handleUdpMessage(msg, rinfo, (response, responseRinfo) => {
|
|
348
|
+
// Send response using your socket
|
|
349
|
+
udpSocket.send(response, responseRinfo.port, responseRinfo.address);
|
|
350
|
+
});
|
|
351
|
+
});
|
|
352
|
+
|
|
353
|
+
// Bind to custom port or multiple interfaces
|
|
354
|
+
udpSocket.bind(5353, '0.0.0.0');
|
|
355
|
+
```
|
|
356
|
+
|
|
357
|
+
#### Manual HTTPS Socket Handling
|
|
358
|
+
|
|
359
|
+
```typescript
|
|
360
|
+
// Create server with manual HTTPS mode
|
|
361
|
+
const dnsServer = new DnsServer({
|
|
362
|
+
httpsKey: '...',
|
|
363
|
+
httpsCert: '...',
|
|
364
|
+
httpsPort: 853,
|
|
365
|
+
udpPort: 53,
|
|
366
|
+
dnssecZone: 'example.com',
|
|
367
|
+
manualHttpsMode: true // HTTPS manual, UDP automatic
|
|
368
|
+
});
|
|
369
|
+
|
|
370
|
+
await dnsServer.start(); // UDP binds, HTTPS doesn't
|
|
371
|
+
|
|
372
|
+
// Create your own TCP server
|
|
373
|
+
const tcpServer = net.createServer((socket) => {
|
|
374
|
+
// Pass TCP sockets to DNS server
|
|
375
|
+
dnsServer.handleHttpsSocket(socket);
|
|
376
|
+
});
|
|
377
|
+
|
|
378
|
+
tcpServer.listen(8853, '0.0.0.0');
|
|
379
|
+
```
|
|
380
|
+
|
|
381
|
+
#### Full Manual Mode
|
|
382
|
+
|
|
383
|
+
Control both protocols manually for complete flexibility:
|
|
384
|
+
|
|
385
|
+
```typescript
|
|
386
|
+
const dnsServer = new DnsServer({
|
|
387
|
+
httpsKey: '...',
|
|
388
|
+
httpsCert: '...',
|
|
389
|
+
httpsPort: 853,
|
|
390
|
+
udpPort: 53,
|
|
391
|
+
dnssecZone: 'example.com',
|
|
392
|
+
manualUdpMode: true,
|
|
393
|
+
manualHttpsMode: true
|
|
394
|
+
});
|
|
395
|
+
|
|
396
|
+
await dnsServer.start(); // Neither protocol binds
|
|
397
|
+
|
|
398
|
+
// Set up your own socket handling for both protocols
|
|
399
|
+
// Perfect for custom routing, load balancing, or clustering
|
|
400
|
+
```
|
|
401
|
+
|
|
402
|
+
#### Advanced Use Cases
|
|
403
|
+
|
|
404
|
+
##### Load Balancing Across Multiple UDP Sockets
|
|
405
|
+
|
|
406
|
+
```typescript
|
|
407
|
+
// Create multiple UDP sockets for different CPU cores
|
|
408
|
+
const sockets = [];
|
|
409
|
+
const numCPUs = require('os').cpus().length;
|
|
410
|
+
|
|
411
|
+
for (let i = 0; i < numCPUs; i++) {
|
|
412
|
+
const socket = dgram.createSocket({
|
|
413
|
+
type: 'udp4',
|
|
414
|
+
reuseAddr: true // Allow multiple sockets on same port
|
|
415
|
+
});
|
|
416
|
+
|
|
417
|
+
socket.on('message', (msg, rinfo) => {
|
|
418
|
+
dnsServer.handleUdpMessage(msg, rinfo, (response, rinfo) => {
|
|
419
|
+
socket.send(response, rinfo.port, rinfo.address);
|
|
420
|
+
});
|
|
421
|
+
});
|
|
422
|
+
|
|
423
|
+
socket.bind(53);
|
|
424
|
+
sockets.push(socket);
|
|
425
|
+
}
|
|
426
|
+
```
|
|
427
|
+
|
|
428
|
+
##### Clustering with Worker Processes
|
|
429
|
+
|
|
430
|
+
```typescript
|
|
431
|
+
import cluster from 'cluster';
|
|
432
|
+
import { DnsServer } from '@push.rocks/smartdns/server';
|
|
433
|
+
|
|
434
|
+
if (cluster.isPrimary) {
|
|
435
|
+
// Master process accepts connections
|
|
436
|
+
const server = net.createServer({ pauseOnConnect: true });
|
|
437
|
+
|
|
438
|
+
// Distribute connections to workers
|
|
439
|
+
server.on('connection', (socket) => {
|
|
440
|
+
const worker = getNextWorker(); // Round-robin or custom logic
|
|
441
|
+
worker.send('socket', socket);
|
|
442
|
+
});
|
|
443
|
+
|
|
444
|
+
server.listen(853);
|
|
445
|
+
} else {
|
|
446
|
+
// Worker process handles DNS
|
|
447
|
+
const dnsServer = new DnsServer({
|
|
448
|
+
httpsKey: '...',
|
|
449
|
+
httpsCert: '...',
|
|
450
|
+
httpsPort: 853,
|
|
451
|
+
udpPort: 53,
|
|
452
|
+
dnssecZone: 'example.com',
|
|
453
|
+
manualHttpsMode: true
|
|
454
|
+
});
|
|
455
|
+
|
|
456
|
+
process.on('message', (msg, socket) => {
|
|
457
|
+
if (msg === 'socket') {
|
|
458
|
+
dnsServer.handleHttpsSocket(socket);
|
|
459
|
+
}
|
|
460
|
+
});
|
|
461
|
+
|
|
462
|
+
await dnsServer.start();
|
|
463
|
+
}
|
|
464
|
+
```
|
|
465
|
+
|
|
466
|
+
##### Custom Transport Protocol
|
|
467
|
+
|
|
468
|
+
```typescript
|
|
469
|
+
// Use DNS server with custom transport (e.g., WebSocket)
|
|
470
|
+
import WebSocket from 'ws';
|
|
471
|
+
|
|
472
|
+
const wss = new WebSocket.Server({ port: 8080 });
|
|
473
|
+
const dnsServer = new DnsServer({
|
|
474
|
+
httpsKey: '...',
|
|
475
|
+
httpsCert: '...',
|
|
476
|
+
httpsPort: 853,
|
|
477
|
+
udpPort: 53,
|
|
478
|
+
dnssecZone: 'example.com',
|
|
479
|
+
manualUdpMode: true,
|
|
480
|
+
manualHttpsMode: true
|
|
481
|
+
});
|
|
482
|
+
|
|
483
|
+
await dnsServer.start();
|
|
484
|
+
|
|
485
|
+
wss.on('connection', (ws) => {
|
|
486
|
+
ws.on('message', (data) => {
|
|
487
|
+
// Process DNS query from WebSocket
|
|
488
|
+
const response = dnsServer.processRawDnsPacket(Buffer.from(data));
|
|
489
|
+
ws.send(response);
|
|
490
|
+
});
|
|
491
|
+
});
|
|
492
|
+
```
|
|
493
|
+
|
|
494
|
+
##### Multi-Interface Binding
|
|
495
|
+
|
|
496
|
+
```typescript
|
|
497
|
+
// Bind to multiple network interfaces manually
|
|
498
|
+
const interfaces = [
|
|
499
|
+
{ address: '192.168.1.100', type: 'udp4' },
|
|
500
|
+
{ address: '10.0.0.50', type: 'udp4' },
|
|
501
|
+
{ address: '::1', type: 'udp6' }
|
|
502
|
+
];
|
|
503
|
+
|
|
504
|
+
interfaces.forEach(({ address, type }) => {
|
|
505
|
+
const socket = dgram.createSocket(type);
|
|
506
|
+
|
|
507
|
+
socket.on('message', (msg, rinfo) => {
|
|
508
|
+
console.log(`Query received on ${address}`);
|
|
509
|
+
dnsServer.handleUdpMessage(msg, rinfo, (response, rinfo) => {
|
|
510
|
+
socket.send(response, rinfo.port, rinfo.address);
|
|
511
|
+
});
|
|
512
|
+
});
|
|
513
|
+
|
|
514
|
+
socket.bind(53, address);
|
|
515
|
+
});
|
|
516
|
+
```
|
|
517
|
+
|
|
298
518
|
### Handling Different Protocols
|
|
299
519
|
|
|
300
520
|
#### UDP DNS Server
|
|
@@ -363,6 +583,56 @@ await dnsServer.start();
|
|
|
363
583
|
// https://localhost:8443/dns-query
|
|
364
584
|
```
|
|
365
585
|
|
|
586
|
+
### Interface Binding
|
|
587
|
+
|
|
588
|
+
For enhanced security and network isolation, you can bind the DNS server to specific network interfaces instead of all available interfaces.
|
|
589
|
+
|
|
590
|
+
#### Localhost-Only Binding
|
|
591
|
+
|
|
592
|
+
Bind to localhost for development or local-only DNS services:
|
|
593
|
+
|
|
594
|
+
```typescript
|
|
595
|
+
const localServer = new DnsServer({
|
|
596
|
+
udpPort: 5353,
|
|
597
|
+
httpsPort: 8443,
|
|
598
|
+
httpsKey: cert.key,
|
|
599
|
+
httpsCert: cert.cert,
|
|
600
|
+
dnssecZone: 'local.test',
|
|
601
|
+
udpBindInterface: '127.0.0.1', // IPv4 localhost
|
|
602
|
+
httpsBindInterface: '127.0.0.1'
|
|
603
|
+
});
|
|
604
|
+
|
|
605
|
+
// Or use IPv6 localhost
|
|
606
|
+
const ipv6LocalServer = new DnsServer({
|
|
607
|
+
// ... other options
|
|
608
|
+
udpBindInterface: '::1', // IPv6 localhost
|
|
609
|
+
httpsBindInterface: '::1'
|
|
610
|
+
});
|
|
611
|
+
```
|
|
612
|
+
|
|
613
|
+
#### Specific Interface Binding
|
|
614
|
+
|
|
615
|
+
Bind to a specific network interface in multi-homed servers:
|
|
616
|
+
|
|
617
|
+
```typescript
|
|
618
|
+
const interfaceServer = new DnsServer({
|
|
619
|
+
udpPort: 53,
|
|
620
|
+
httpsPort: 443,
|
|
621
|
+
httpsKey: cert.key,
|
|
622
|
+
httpsCert: cert.cert,
|
|
623
|
+
dnssecZone: 'example.com',
|
|
624
|
+
udpBindInterface: '192.168.1.100', // Specific internal interface
|
|
625
|
+
httpsBindInterface: '10.0.0.50' // Different interface for HTTPS
|
|
626
|
+
});
|
|
627
|
+
```
|
|
628
|
+
|
|
629
|
+
#### Security Considerations
|
|
630
|
+
|
|
631
|
+
- **Default Behavior**: If not specified, servers bind to all interfaces (`0.0.0.0`)
|
|
632
|
+
- **Localhost Binding**: Use `127.0.0.1` or `::1` for development and testing
|
|
633
|
+
- **Production**: Consider binding to specific internal interfaces for security
|
|
634
|
+
- **Validation**: Invalid IP addresses will throw an error during server startup
|
|
635
|
+
|
|
366
636
|
### Advanced Handler Patterns
|
|
367
637
|
|
|
368
638
|
#### Pattern-Based Routing
|
|
@@ -512,6 +782,7 @@ await tap.start();
|
|
|
512
782
|
5. **Monitoring**: Log DNS queries for debugging and analytics
|
|
513
783
|
6. **Rate Limiting**: Implement rate limiting for public DNS servers
|
|
514
784
|
7. **Caching**: Respect TTL values and implement proper caching
|
|
785
|
+
8. **Manual Sockets**: Use manual socket handling for clustering and load balancing
|
|
515
786
|
|
|
516
787
|
### Performance Considerations
|
|
517
788
|
|
|
@@ -519,6 +790,7 @@ await tap.start();
|
|
|
519
790
|
- The DNS server handles concurrent UDP and HTTPS requests efficiently
|
|
520
791
|
- DNSSEC signatures are generated on-demand to reduce memory usage
|
|
521
792
|
- Pattern matching uses caching for improved performance
|
|
793
|
+
- Manual socket handling enables horizontal scaling across CPU cores
|
|
522
794
|
|
|
523
795
|
### Security Considerations
|
|
524
796
|
|
|
@@ -528,6 +800,8 @@ await tap.start();
|
|
|
528
800
|
- Implement access controls for DNS server handlers
|
|
529
801
|
- Use Let's Encrypt for automatic SSL certificate management
|
|
530
802
|
- Never expose internal network information through DNS
|
|
803
|
+
- Bind to specific interfaces in production environments
|
|
804
|
+
- Use manual socket handling for custom security layers
|
|
531
805
|
|
|
532
806
|
This comprehensive library provides everything needed for both DNS client operations and running production-grade DNS servers with modern security features in TypeScript.
|
|
533
807
|
|
package/readme.plan.md
ADDED
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
# DNS Server Interface Binding Implementation Plan
|
|
2
|
+
|
|
3
|
+
Command to reread CLAUDE.md: `cat /home/philkunz/.claude/CLAUDE.md`
|
|
4
|
+
|
|
5
|
+
## Overview ✅ COMPLETED
|
|
6
|
+
Enable specific interface binding for the DNSServer class to allow binding to specific network interfaces instead of all interfaces (0.0.0.0).
|
|
7
|
+
|
|
8
|
+
## Implementation Status: COMPLETED ✅
|
|
9
|
+
|
|
10
|
+
### What was implemented:
|
|
11
|
+
|
|
12
|
+
✅ **1. Updated IDnsServerOptions Interface**
|
|
13
|
+
- Added optional `udpBindInterface?: string` property (defaults to '0.0.0.0')
|
|
14
|
+
- Added optional `httpsBindInterface?: string` property (defaults to '0.0.0.0')
|
|
15
|
+
- Located in `ts_server/classes.dnsserver.ts:5-11`
|
|
16
|
+
|
|
17
|
+
✅ **2. Modified DnsServer.start() Method**
|
|
18
|
+
- Updated UDP server binding to use `this.options.udpBindInterface || '0.0.0.0'`
|
|
19
|
+
- Updated HTTPS server listening to use `this.options.httpsBindInterface || '0.0.0.0'`
|
|
20
|
+
- Added IP address validation before binding
|
|
21
|
+
- Updated console logging to show specific interface being bound
|
|
22
|
+
- Located in `ts_server/classes.dnsserver.ts:699-752`
|
|
23
|
+
|
|
24
|
+
✅ **3. Added IP Address Validation**
|
|
25
|
+
- Created `isValidIpAddress()` method supporting IPv4 and IPv6
|
|
26
|
+
- Validates interface addresses before binding
|
|
27
|
+
- Throws meaningful error messages for invalid addresses
|
|
28
|
+
- Located in `ts_server/classes.dnsserver.ts:392-398`
|
|
29
|
+
|
|
30
|
+
✅ **4. Updated Documentation**
|
|
31
|
+
- Added dedicated "Interface Binding" section to readme.md
|
|
32
|
+
- Included examples for localhost-only binding (`127.0.0.1`, `::1`)
|
|
33
|
+
- Documented security considerations and use cases
|
|
34
|
+
- Added examples for specific interface binding
|
|
35
|
+
|
|
36
|
+
✅ **5. Added Comprehensive Tests**
|
|
37
|
+
- **localhost binding test**: Verifies binding to `127.0.0.1` instead of `0.0.0.0`
|
|
38
|
+
- **Invalid IP validation test**: Ensures invalid IP addresses are rejected
|
|
39
|
+
- **IPv6 support test**: Tests `::1` binding (with graceful fallback if IPv6 unavailable)
|
|
40
|
+
- **Backwards compatibility**: Existing tests continue to work with default behavior
|
|
41
|
+
- Located in `test/test.server.ts`
|
|
42
|
+
|
|
43
|
+
✅ **6. Updated restartHttpsServer Method**
|
|
44
|
+
- Modified to respect interface binding options during certificate updates
|
|
45
|
+
- Ensures Let's Encrypt certificate renewal maintains interface binding
|
|
46
|
+
|
|
47
|
+
## ✅ Implementation Results
|
|
48
|
+
|
|
49
|
+
### Test Results
|
|
50
|
+
All interface binding functionality has been successfully tested:
|
|
51
|
+
|
|
52
|
+
```bash
|
|
53
|
+
✅ should bind to localhost interface only (318ms)
|
|
54
|
+
- UDP DNS server running on 127.0.0.1:8085
|
|
55
|
+
- HTTPS DNS server running on 127.0.0.1:8084
|
|
56
|
+
|
|
57
|
+
✅ should reject invalid IP addresses (151ms)
|
|
58
|
+
- Validates IP address format correctly
|
|
59
|
+
- Throws meaningful error messages
|
|
60
|
+
|
|
61
|
+
✅ should work with IPv6 localhost if available
|
|
62
|
+
- Gracefully handles IPv6 unavailability in containerized environments
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
### Benefits Achieved
|
|
66
|
+
- ✅ Enhanced security by allowing localhost-only binding
|
|
67
|
+
- ✅ Support for multi-homed servers with specific interface requirements
|
|
68
|
+
- ✅ Better isolation in containerized environments
|
|
69
|
+
- ✅ Backwards compatible (defaults to current behavior)
|
|
70
|
+
- ✅ IP address validation with clear error messages
|
|
71
|
+
- ✅ IPv4 and IPv6 support
|
|
72
|
+
|
|
73
|
+
## Example Usage (Now Available)
|
|
74
|
+
```typescript
|
|
75
|
+
// Bind to localhost only
|
|
76
|
+
const dnsServer = new DnsServer({
|
|
77
|
+
httpsKey: cert.key,
|
|
78
|
+
httpsCert: cert.cert,
|
|
79
|
+
httpsPort: 443,
|
|
80
|
+
udpPort: 53,
|
|
81
|
+
dnssecZone: 'example.com',
|
|
82
|
+
udpBindInterface: '127.0.0.1',
|
|
83
|
+
httpsBindInterface: '127.0.0.1'
|
|
84
|
+
});
|
|
85
|
+
|
|
86
|
+
// Bind to specific interface
|
|
87
|
+
const dnsServer = new DnsServer({
|
|
88
|
+
// ... other options
|
|
89
|
+
udpBindInterface: '192.168.1.100',
|
|
90
|
+
httpsBindInterface: '192.168.1.100'
|
|
91
|
+
});
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
## Files to Modify
|
|
95
|
+
1. `ts_server/classes.dnsserver.ts` - Interface and implementation
|
|
96
|
+
2. `readme.md` - Documentation updates
|
|
97
|
+
3. `test/test.server.ts` - Add interface binding tests
|
|
98
|
+
|
|
99
|
+
## Testing Strategy
|
|
100
|
+
- Unit tests for interface validation
|
|
101
|
+
- Integration tests for binding behavior
|
|
102
|
+
- Error handling tests for invalid interfaces
|
|
103
|
+
- Backwards compatibility tests
|
package/ts/00_commitinfo_data.ts
CHANGED
|
@@ -3,6 +3,6 @@
|
|
|
3
3
|
*/
|
|
4
4
|
export const commitinfo = {
|
|
5
5
|
name: '@push.rocks/smartdns',
|
|
6
|
-
version: '7.
|
|
6
|
+
version: '7.4.0',
|
|
7
7
|
description: 'A robust TypeScript library providing advanced DNS management and resolution capabilities including support for DNSSEC, custom DNS servers, and integration with various DNS providers.'
|
|
8
8
|
}
|