feat(rustdns-client): add Rust DNS client binary and TypeScript IPC bridge to enable UDP and DoH resolution, RDATA decoding, and DNSSEC AD/rcode support
This commit is contained in:
110
ts_server/readme.md
Normal file
110
ts_server/readme.md
Normal file
@@ -0,0 +1,110 @@
|
||||
# @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
|
||||
Reference in New Issue
Block a user