111 lines
3.9 KiB
Markdown
111 lines
3.9 KiB
Markdown
# @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
|
|
|
|
```typescript
|
|
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.
|
|
|
|
```typescript
|
|
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.
|
|
|
|
```typescript
|
|
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
|