@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 bridgedns-packet— DNS wire format codec (used for TS fallback path)minimatch— glob pattern matching for handlersacme-client— Let's Encrypt ACME protocol