@push.rocks/smartdns 7.12.0 → 8.0.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.
@@ -67,11 +67,12 @@ export class RustDnsBridge extends plugins.events.EventEmitter {
67
67
  /**
68
68
  * Send a DNS query result back to Rust.
69
69
  */
70
- async sendQueryResult(correlationId, answers, answered) {
70
+ async sendQueryResult(correlationId, answers, responseKind, authorityZone) {
71
71
  await this.bridge.sendCommand('dnsQueryResult', {
72
72
  correlationId,
73
73
  answers,
74
- answered,
74
+ responseKind,
75
+ authorityZone,
75
76
  });
76
77
  }
77
78
  /**
@@ -82,11 +83,14 @@ export class RustDnsBridge extends plugins.events.EventEmitter {
82
83
  }
83
84
  /**
84
85
  * Process a raw DNS packet via IPC (for manual/passthrough mode).
85
- * Returns the DNS response as a Buffer.
86
+ * Returns the DNS response as a Buffer. Pass `transport: 'udp'` when the
87
+ * response will be sent as a UDP datagram, so it is truncated (TC bit) to
88
+ * the client's advertised payload size instead of exceeding it.
86
89
  */
87
- async processPacket(packet) {
90
+ async processPacket(packet, transport) {
88
91
  const result = await this.bridge.sendCommand('processPacket', {
89
92
  packet: packet.toString('base64'),
93
+ transport,
90
94
  });
91
95
  return Buffer.from(result.packet, 'base64');
92
96
  }
@@ -133,4 +137,4 @@ function getPlatformSuffix() {
133
137
  }
134
138
  return null;
135
139
  }
136
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2xhc3Nlcy5ydXN0ZG5zYnJpZGdlLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vdHNfc2VydmVyL2NsYXNzZXMucnVzdGRuc2JyaWRnZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEtBQUssT0FBTyxNQUFNLGNBQWMsQ0FBQztBQXdFeEM7O0dBRUc7QUFDSCxNQUFNLE9BQU8sYUFBYyxTQUFRLE9BQU8sQ0FBQyxNQUFNLENBQUMsWUFBWTtJQUc1RDtRQUNFLEtBQUssRUFBRSxDQUFDO1FBRVIsTUFBTSxVQUFVLEdBQUcsT0FBTyxDQUFDLElBQUksQ0FBQyxPQUFPLENBQ3JDLE9BQU8sQ0FBQyxJQUFJLENBQUMsT0FBTyxDQUFDLElBQUksR0FBRyxDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUMsR0FBRyxDQUFDLENBQUMsUUFBUSxDQUFDLEVBQ3ZELElBQUksQ0FDTCxDQUFDO1FBRUYsMkVBQTJFO1FBQzNFLE1BQU0sY0FBYyxHQUFHLGlCQUFpQixFQUFFLENBQUM7UUFDM0MsTUFBTSxVQUFVLEdBQWEsRUFBRSxDQUFDO1FBRWhDLDBFQUEwRTtRQUMxRSxJQUFJLGNBQWMsRUFBRSxDQUFDO1lBQ25CLFVBQVUsQ0FBQyxJQUFJLENBQUMsT0FBTyxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsVUFBVSxFQUFFLFdBQVcsRUFBRSxXQUFXLGNBQWMsRUFBRSxDQUFDLENBQUMsQ0FBQztRQUMzRixDQUFDO1FBQ0QsMkNBQTJDO1FBQzNDLFVBQVUsQ0FBQyxJQUFJLENBQUMsT0FBTyxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsVUFBVSxFQUFFLFdBQVcsRUFBRSxTQUFTLENBQUMsQ0FBQyxDQUFDO1FBQ3ZFLHdCQUF3QjtRQUN4QixVQUFVLENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLFVBQVUsRUFBRSxNQUFNLEVBQUUsUUFBUSxFQUFFLFNBQVMsRUFBRSxTQUFTLENBQUMsQ0FBQyxDQUFDO1FB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
140
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2xhc3Nlcy5ydXN0ZG5zYnJpZGdlLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vdHNfc2VydmVyL2NsYXNzZXMucnVzdGRuc2JyaWRnZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEtBQUssT0FBTyxNQUFNLGNBQWMsQ0FBQztBQTBGeEM7O0dBRUc7QUFDSCxNQUFNLE9BQU8sYUFBYyxTQUFRLE9BQU8sQ0FBQyxNQUFNLENBQUMsWUFBWTtJQUc1RDtRQUNFLEtBQUssRUFBRSxDQUFDO1FBRVIsTUFBTSxVQUFVLEdBQUcsT0FBTyxDQUFDLElBQUksQ0FBQyxPQUFPLENBQ3JDLE9BQU8sQ0FBQyxJQUFJLENBQUMsT0FBTyxDQUFDLElBQUksR0FBRyxDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUMsR0FBRyxDQUFDLENBQUMsUUFBUSxDQUFDLEVBQ3ZELElBQUksQ0FDTCxDQUFDO1FBRUYsMkVBQTJFO1FBQzNFLE1BQU0sY0FBYyxHQUFHLGlCQUFpQixFQUFFLENBQUM7UUFDM0MsTUFBTSxVQUFVLEdBQWEsRUFBRSxDQUFDO1FBRWhDLDBFQUEwRTtRQUMxRSxJQUFJLGNBQWMsRUFBRSxDQUFDO1lBQ25CLFVBQVUsQ0FBQyxJQUFJLENBQUMsT0FBTyxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsVUFBVSxFQUFFLFdBQVcsRUFBRSxXQUFXLGNBQWMsRUFBRSxDQUFDLENBQUMsQ0FBQztRQUMzRixDQUFDO1FBQ0QsMkNBQTJDO1FBQzNDLFVBQVUsQ0FBQyxJQUFJLENBQUMsT0FBTyxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsVUFBVSxFQUFFLFdBQVcsRUFBRSxTQUFTLENBQUMsQ0FBQyxDQUFDO1FBQ3ZFLHdCQUF3QjtRQUN4QixVQUFVLENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLFVBQVUsRUFBRSxNQUFNLEVBQUUsUUFBUSxFQUFFLFNBQVMsRUFBRSxTQUFTLENBQUMsQ0FBQyxDQUFDO1FB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
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@push.rocks/smartdns",
3
- "version": "7.12.0",
3
+ "version": "8.0.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": {
package/readme.hints.md CHANGED
@@ -143,9 +143,129 @@ The test suite demonstrates:
143
143
  - Properly serializes both components for DNSSEC signature generation
144
144
  - Enables mail exchange records to be authenticated with DNSSEC
145
145
 
146
+ ## Authority Model (server)
147
+
148
+ Authority comes from **configuration**, never from the presence of a handler.
149
+
150
+ - `authoritativeZones` (falling back to `[dnssecZone]`) is the single source of
151
+ truth for the `aa` bit. An answer only carries `aa` when the queried name
152
+ falls inside one of those zones.
153
+ - `registerHandler(pattern, types, handler, options?)` takes
154
+ `options.authority`:
155
+ - `'authoritative'` (default) — the handler only contributes for names inside
156
+ a configured zone. A match outside every zone is **suppressed**, not
157
+ answered, and reported on the `refused` event. A registration that cannot
158
+ match any configured zone also logs a warning once, at registration time.
159
+ - `'non-authoritative'` — the handler may answer any matching name, but the
160
+ response never carries `aa` and is never DNSSEC-signed. This is the mode
161
+ for split-horizon / private-route overlays.
162
+ - `aa` is a per-message flag, so a single non-authoritative contribution
163
+ downgrades the whole response.
164
+
165
+ Why this matters: before v8, registering a handler *was* the public claim of
166
+ authority. A private-route overlay registered for a domain delegated elsewhere
167
+ made the public nameserver answer with `aa` and an RFC1918 address, while
168
+ refusing every other query type for the same name. Both halves came from the
169
+ same defect — two disagreeing sources of truth.
170
+
171
+ ### Response outcomes
172
+
173
+ `TDnsQueryResponseKind` maps one-to-one onto the wire:
174
+
175
+ | kind | rcode | `aa` | authority section |
176
+ | --- | --- | --- | --- |
177
+ | `answer` | 0 | yes | — |
178
+ | `nonAuthoritativeAnswer` | 0 | no | — |
179
+ | `authoritativeNegative` (NODATA) | 0 | yes | zone SOA |
180
+ | `authoritativeNameError` (NXDOMAIN) | 3 | yes | zone SOA |
181
+ | `refused` | 5 | no | — |
182
+ | `servfail` | 2 | no | — |
183
+
184
+ NXDOMAIN is only emitted when the name provably does not exist: no handler
185
+ pattern matches it for any type, it is not the apex of a configured zone, no
186
+ configured zone sits below it, and no handler pattern is anchored strictly
187
+ below it (literal `.name` suffix, or a wildcard that matches a probe label —
188
+ mid-label wildcards such as `x.*.example.com` are not fully inverted by this
189
+ check and can still leave an ancestor at NXDOMAIN). The apex always exists
190
+ (it answers its own SOA), and a name with covered descendants is an empty
191
+ non-terminal — both get NODATA, because NXDOMAIN denies the entire subtree
192
+ (RFC 8020) and a wrong one lets aggressive negative caching darken the zone.
193
+ A catch-all pattern such as `'*'` therefore suppresses NXDOMAIN entirely —
194
+ that is deliberate.
195
+
196
+ The zone apex answers its own SOA even with no registered SOA handler; an
197
+ authoritative server that cannot answer SOA for its own zone breaks negative
198
+ caching and resolver heuristics.
199
+
200
+ One deliberate exception to the table: RFC 6761 localhost handling (when
201
+ `enableLocalhostHandling` is on) answers `localhost` A/AAAA with `aa` set even
202
+ though `localhost` is outside every configured zone — special-use names are
203
+ authoritative by definition, not by delegation.
204
+
205
+ ## Handler Lifecycle
206
+
207
+ - `registerHandler` returns an `IDnsHandlerRegistration` with a unique `id` and
208
+ an `unregister()` that removes **only** that registration.
209
+ - `unregisterHandlerById(id)` and `unregisterHandlersByOwner(owner)` are the
210
+ precise teardown primitives; `listHandlers()` exposes the current set for
211
+ leak checks.
212
+ - `unregisterHandler(pattern, types)` is retained and unchanged: it still
213
+ removes *every* handler matching that pattern/type pair. It cannot distinguish
214
+ two consumers sharing a key — prefer the handle.
215
+ - ACME authorization follows the same rule: `filterAuthorizedDomains` /
216
+ `retrieveSslCertificate` admit exactly the domains inside a configured
217
+ authoritative zone. Handler registrations play no part — a DNS-01 challenge
218
+ for an out-of-zone domain could never validate, because its challenge TXT
219
+ handler would be suppressed.
220
+
221
+ ## Transport And Protocol Notes
222
+
223
+ - **EDNS0**: a request carrying an OPT record always gets an OPT back
224
+ (RFC 6891 6.1.1), advertising `DNS_ADVERTISED_UDP_PAYLOAD` (1232). Requests
225
+ without OPT get no OPT. Client-advertised payload sizes are clamped up to 512
226
+ so a hostile OPT cannot force pathological truncation.
227
+ - **Truncation**: UDP responses are truncated to the client's advertised payload
228
+ size with the TC bit set, so resolvers retry over TCP. Without this, oversized
229
+ datagrams were emitted and silently dropped by real networks. Truncation is
230
+ size arithmetic, never a re-encode per dropped record — the encoder does not
231
+ compress names, so record sizes are additive (`DnsPacket::encoded_len`).
232
+ `processRawDnsPacketAsync(packet, 'udp')` declares the same UDP bound for the
233
+ manual path (`handleUdpMessage` passes it automatically); without the hint no
234
+ size bound is applied, which is correct for TCP and DoH framing. Note the
235
+ manual-path deadlock under Known Limitations before relying on this.
236
+ - **RA** is cleared on every path — this server never recurses.
237
+ - **RDATA validation** fails closed: a handler returning an unencodable value
238
+ (for example a non-IPv4 string for an A record) produces SERVFAIL and an error
239
+ log, rather than a malformed record on the wire.
240
+ - **SOA serial** is fixed for the lifetime of the server process and passed to
241
+ Rust via `soaSerial`, so apex answers and negative authorities agree.
242
+
243
+ ## Observability
244
+
245
+ - `query` events carry `responseKind`, `authorityZone` and `suppressedHandlers`.
246
+ - `refused` events fire for every refusal and every suppressed handler match,
247
+ carrying the handler `id`, `domainPattern` and `owner`. Wire this up: the
248
+ original incident was invisible for weeks because nothing surfaced it.
249
+
146
250
  ## Known Limitations
147
251
 
148
252
  1. **Handler Deduplication**: If the same handler is registered multiple times, it will contribute duplicate records (this may be desired behavior for some use cases)
253
+ 2. **NXDOMAIN under catch-all patterns**: see the authority model above.
254
+ 3. **SOA serial does not track zone changes** — it is a process-lifetime
255
+ constant, not a change counter. Secondaries driven by AXFR/IXFR are not
256
+ supported.
257
+ 4. **Manual-path (`processPacket`) queries deadlock on handler resolution**
258
+ — pre-existing, not introduced by the v8 hardening. The IPC select loop in
259
+ `rust/crates/rustdns/src/management.rs` awaits `handle_request` inline, so
260
+ while `handle_process_packet` waits for the TypeScript `dnsQuery` callback
261
+ the loop can neither emit the query event nor read its result; every
262
+ handler-backed query through `processRawDnsPacketAsync` /
263
+ `handleUdpMessage` times out to SERVFAIL after 10 s. The built-in UDP, TCP
264
+ and DoH listeners are unaffected (they resolve outside the IPC request
265
+ loop). The `transport: 'udp'` truncation contract on this path is wired
266
+ and unit-tested but cannot be observed end-to-end until the loop spawns
267
+ `processPacket` handling instead of awaiting it inline. No test exercises
268
+ `processRawDnsPacketAsync`; fixing this needs its own release.
149
269
  ## Static Rust Binaries
150
270
 
151
271
  - The Rust binaries in `dist_rust/` are statically linked (static-pie) via `"static": true` in the `@git.zone/tsrust` block of `.smartconfig.json` (tsrust >= 1.4.1). They run on both glibc (Debian/Ubuntu) and musl (Alpine) systems.
package/readme.md CHANGED
@@ -263,6 +263,7 @@ interface IDnsServerOptions {
263
263
  httpsKey: string; // PEM private key (path or content)
264
264
  httpsCert: string; // PEM certificate (path or content)
265
265
  dnssecZone: string; // Zone for DNSSEC signing
266
+ authoritativeZones?: string[]; // Zones this server is authoritative for (default: [dnssecZone])
266
267
  primaryNameserver?: string; // SOA mname field (default: 'ns1.{dnssecZone}')
267
268
  udpBindInterface?: string; // IP to bind UDP (default: '0.0.0.0')
268
269
  tcpBindInterface?: string; // IP to bind TCP (defaults to udpBindInterface)
@@ -312,6 +313,8 @@ await server.start();
312
313
 
313
314
  Handlers use **glob patterns** (via `minimatch`) to match incoming query names. Multiple handlers can contribute records to the same response.
314
315
 
316
+ Registering a handler does **not** make the server authoritative for the matched names. Authority comes solely from `authoritativeZones` (falling back to `dnssecZone`): list every zone you serve there, or queries for it are withheld. A default-authority handler whose match falls outside every configured zone is suppressed and reported on the `refused` event; register with `{ authority: 'non-authoritative' }` to deliberately serve out-of-zone names without the `aa` bit or DNSSEC signatures.
317
+
315
318
  ```typescript
316
319
  // Exact domain
317
320
  server.registerHandler('example.com', ['A'], handler);
@@ -331,14 +334,15 @@ server.registerHandler('db-*.internal.example.com', ['A'], (question) => {
331
334
  };
332
335
  });
333
336
 
334
- // Catch-all
337
+ // Catch-all — '*' is anchored in no configured zone, so it must be
338
+ // registered non-authoritative or its out-of-zone answers are suppressed
335
339
  server.registerHandler('*', ['A'], (question) => ({
336
340
  name: question.name,
337
341
  type: 'A',
338
342
  class: 'IN',
339
343
  ttl: 300,
340
344
  data: '127.0.0.1',
341
- }));
345
+ }), { authority: 'non-authoritative' });
342
346
 
343
347
  // Multiple record types
344
348
  server.registerHandler('example.com', ['MX'], (question) => ({
@@ -349,11 +353,21 @@ server.registerHandler('example.com', ['MX'], (question) => ({
349
353
  data: { preference: 10, exchange: 'mail.example.com' },
350
354
  }));
351
355
 
352
- // Unregister a handler
356
+ // Unregister a handler: registerHandler returns a handle identifying
357
+ // exactly that registration
358
+ const registration = server.registerHandler('example.com', ['A'], handler);
359
+ registration.unregister();
360
+
361
+ // Precise teardown also works by id or owner label, and listHandlers()
362
+ // exposes the current set
363
+ server.registerHandler('example.com', ['TXT'], handler, { owner: 'acme-module' });
364
+ server.unregisterHandlersByOwner('acme-module');
365
+
366
+ // The coarse form removes EVERY handler on the pattern/type pair
353
367
  server.unregisterHandler('example.com', ['A']);
354
368
  ```
355
369
 
356
- When no handler matches, the server automatically returns an **SOA record** for the zone.
370
+ Negative answers are authoritative only inside configured zones: a name inside an authoritative zone that provably does not exist yields **NXDOMAIN** with the zone SOA in the AUTHORITY section; a name that exists — a covered name queried for a type no handler serves, the zone apex, or an empty non-terminal with covered names beneath it — yields **NODATA** with the SOA in AUTHORITY; names outside every configured zone are answered **REFUSED**.
357
371
 
358
372
  ### DNSSEC ✅
359
373
 
@@ -389,7 +403,7 @@ Supported algorithms: **ECDSAP256SHA256** (13), **ED25519** (15), **RSASHA256**
389
403
 
390
404
  ### SOA Records
391
405
 
392
- The server auto-generates SOA records for zones when no specific handler matches. Customize the primary nameserver:
406
+ The server carries the zone SOA in the AUTHORITY section of negative answers (NXDOMAIN and NODATA), and the zone apex answers its own SOA even without a registered SOA handler. Customize the primary nameserver:
393
407
 
394
408
  ```typescript
395
409
  const server = new DnsServer({
@@ -401,13 +415,13 @@ const server = new DnsServer({
401
415
  // Generated SOA includes:
402
416
  // mname: ns1.example.com
403
417
  // rname: hostmaster.example.com
404
- // serial: Unix timestamp
418
+ // serial: captured once at server construction, stable for the process lifetime
405
419
  // refresh: 3600, retry: 600, expire: 604800, minimum: 86400
406
420
  ```
407
421
 
408
422
  ### Let's Encrypt Integration 🔒
409
423
 
410
- Built-in ACME DNS-01 challenge support for automatic SSL certificates:
424
+ Built-in ACME DNS-01 challenge support for automatic SSL certificates. Challenge TXT handlers are registered at default authority, so DNS-01 validation only completes for domains inside `authoritativeZones` (or `dnssecZone`):
411
425
 
412
426
  ```typescript
413
427
  const server = new DnsServer({
@@ -504,6 +518,10 @@ Process individual DNS packets directly:
504
518
  ```typescript
505
519
  // Asynchronous (via Rust bridge — includes DNSSEC signing)
506
520
  const response = await server.processRawDnsPacketAsync(packetBuffer);
521
+
522
+ // When the response goes out as a UDP datagram, pass 'udp' so it is
523
+ // truncated (TC bit) to the client's advertised EDNS0 payload size
524
+ const udpResponse = await server.processRawDnsPacketAsync(packetBuffer, 'udp');
507
525
  ```
508
526
 
509
527
  Manual TCP callers must handle DNS-over-TCP's two-byte length prefix themselves and pass only the raw DNS packet payload to `processRawDnsPacketAsync()`.
@@ -3,6 +3,6 @@
3
3
  */
4
4
  export const commitinfo = {
5
5
  name: '@push.rocks/smartdns',
6
- version: '7.12.0',
6
+ version: '8.0.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
  }