Files

@push.rocks/smartdns/server

DNS server module for @push.rocks/smartdns — a full-featured authoritative DNS server powered by a Rust backend with DNSSEC, DNS-over-HTTPS, and Let's Encrypt integration.

Import

import { DnsServer } from '@push.rocks/smartdns/server';

Architecture

The server delegates network I/O, DNS packet parsing/encoding, and DNSSEC signing to a compiled Rust binary (rustdns). TypeScript retains the public API, handler registration, and ACME certificate orchestration.

Communication happens via JSON-over-stdin/stdout IPC using @push.rocks/smartrust's RustBridge. DNS queries that need handler resolution are forwarded from Rust to TypeScript with correlation IDs, then results are sent back for response assembly and DNSSEC signing.

Rust Crate Structure

Crate Purpose
rustdns Main binary with IPC management loop
rustdns-protocol DNS wire format parsing/encoding, RDATA encode/decode
rustdns-server Async UDP + HTTPS servers (tokio, hyper, rustls)
rustdns-dnssec ECDSA/ED25519 key generation and RRset signing

Classes

DnsServer

The primary class. Manages handler registration, server lifecycle, and certificate retrieval.

const server = new DnsServer({
  udpPort: 53,
  httpsPort: 443,
  httpsKey: '...pem...',
  httpsCert: '...pem...',
  dnssecZone: 'example.com',
  primaryNameserver: 'ns1.example.com',
});

Options

Option Type Default Description
udpPort number UDP DNS port
httpsPort number HTTPS DoH port
httpsKey string TLS private key (PEM)
httpsCert string TLS certificate (PEM)
dnssecZone string Zone to enable DNSSEC for
primaryNameserver string ns1.{zone} SOA mname field
udpBindInterface string 0.0.0.0 IP to bind UDP
httpsBindInterface string 0.0.0.0 IP to bind HTTPS
manualUdpMode boolean false Don't auto-bind UDP
manualHttpsMode boolean false Don't auto-bind HTTPS
enableLocalhostHandling boolean true Handle RFC 6761 localhost

Key Methods

Method Description
start() Spawn Rust binary and start listening
stop() Gracefully shut down
registerHandler(pattern, types, fn) Add a DNS handler (glob patterns via minimatch)
unregisterHandler(pattern, types) Remove a handler
handleUdpMessage(msg, rinfo, cb) Process a UDP message manually
processRawDnsPacket(buf) Sync packet processing (TS fallback)
processRawDnsPacketAsync(buf) Async packet processing (Rust bridge, includes DNSSEC)
retrieveSslCertificate(domains, opts) ACME DNS-01 certificate retrieval
filterAuthorizedDomains(domains) Filter domains the server is authoritative for

RustDnsBridge

Low-level IPC bridge to the rustdns binary. Used internally by DnsServer — typically not imported directly.

Emits events: dnsQuery, started, stopped, error.

Handler System

Handlers use glob patterns (via minimatch) for domain matching. Multiple handlers can contribute records to a single response.

server.registerHandler('*.example.com', ['A'], (question) => ({
  name: question.name,
  type: 'A',
  class: 'IN',
  ttl: 300,
  data: '10.0.0.1',
}));

When no handler matches, the server returns an automatic SOA record for the zone.

DNSSEC

Enabled automatically with the dnssecZone option. Supports:

  • ECDSAP256SHA256 (13) — default
  • ED25519 (15)
  • RSASHA256 (8)

Key generation, DNSKEY/RRSIG/NSEC record creation is fully handled by the Rust backend.

Dependencies

  • @push.rocks/smartrust — TypeScript-to-Rust IPC bridge
  • dns-packet — DNS wire format codec (used for TS fallback path)
  • minimatch — glob pattern matching for handlers
  • acme-client — Let's Encrypt ACME protocol