@serve.zone/dcrouter 13.17.9 → 13.19.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.
Files changed (43) hide show
  1. package/dist_serve/bundle.js +6 -5
  2. package/dist_ts/00_commitinfo_data.js +1 -1
  3. package/dist_ts/classes.dcrouter.d.ts +9 -5
  4. package/dist_ts/classes.dcrouter.js +152 -120
  5. package/dist_ts/config/classes.route-config-manager.d.ts +13 -5
  6. package/dist_ts/config/classes.route-config-manager.js +76 -36
  7. package/dist_ts/db/documents/classes.route.doc.d.ts +2 -0
  8. package/dist_ts/db/documents/classes.route.doc.js +11 -2
  9. package/dist_ts/email/classes.email-domain.manager.d.ts +7 -0
  10. package/dist_ts/email/classes.email-domain.manager.js +118 -55
  11. package/dist_ts/email/classes.smartmta-storage-manager.d.ts +13 -0
  12. package/dist_ts/email/classes.smartmta-storage-manager.js +101 -0
  13. package/dist_ts/email/email-dns-records.d.ts +14 -0
  14. package/dist_ts/email/email-dns-records.js +34 -0
  15. package/dist_ts/email/index.d.ts +2 -0
  16. package/dist_ts/email/index.js +3 -1
  17. package/dist_ts/opsserver/handlers/email-ops.handler.js +6 -15
  18. package/dist_ts/opsserver/handlers/route-management.handler.js +5 -7
  19. package/dist_ts/opsserver/handlers/stats.handler.js +41 -7
  20. package/dist_ts_interfaces/data/route-management.d.ts +2 -0
  21. package/dist_ts_migrations/index.js +25 -1
  22. package/dist_ts_web/00_commitinfo_data.js +1 -1
  23. package/dist_ts_web/appstate.js +13 -4
  24. package/dist_ts_web/elements/network/ops-view-routes.d.ts +2 -0
  25. package/dist_ts_web/elements/network/ops-view-routes.js +44 -21
  26. package/package.json +2 -2
  27. package/readme.md +190 -1543
  28. package/ts/00_commitinfo_data.ts +1 -1
  29. package/ts/classes.dcrouter.ts +190 -138
  30. package/ts/config/classes.route-config-manager.ts +97 -42
  31. package/ts/db/documents/classes.route.doc.ts +7 -0
  32. package/ts/email/classes.email-domain.manager.ts +136 -51
  33. package/ts/email/classes.smartmta-storage-manager.ts +108 -0
  34. package/ts/email/email-dns-records.ts +53 -0
  35. package/ts/email/index.ts +2 -0
  36. package/ts/opsserver/handlers/email-ops.handler.ts +5 -19
  37. package/ts/opsserver/handlers/route-management.handler.ts +4 -6
  38. package/ts/opsserver/handlers/stats.handler.ts +43 -7
  39. package/ts_apiclient/readme.md +69 -195
  40. package/ts_web/00_commitinfo_data.ts +1 -1
  41. package/ts_web/appstate.ts +16 -4
  42. package/ts_web/elements/network/ops-view-routes.ts +47 -29
  43. package/ts_web/readme.md +41 -242
package/readme.md CHANGED
@@ -1,139 +1,44 @@
1
1
  # @serve.zone/dcrouter
2
2
 
3
- ![](https://code.foss.global/serve.zone/docs/raw/branch/main/dcrouter.png)
3
+ ![dcrouter banner](https://code.foss.global/serve.zone/docs/raw/branch/main/dcrouter.png)
4
4
 
5
- **dcrouter: The all-in-one gateway for your datacenter.** 🚀
5
+ `dcrouter` is a TypeScript control plane for running a serious multi-protocol edge or datacenter gateway from one process. It orchestrates HTTP/HTTPS and TCP routing through SmartProxy, email through smartmta, authoritative DNS and DNS-over-HTTPS, RADIUS, remote ingress tunnels, VPN access control, a typed Ops API, and a web dashboard.
6
6
 
7
- A comprehensive traffic routing solution that provides unified gateway capabilities for HTTP/HTTPS, TCP/SNI, email (SMTP), DNS, RADIUS, VPN, and remote edge ingress — all from a single process. Designed for enterprises requiring robust traffic management, automatic TLS certificate provisioning, VPN-based access control, distributed edge networking, and enterprise-grade email infrastructure.
7
+ It is built for operators who want one place to define routes, expose services, manage certificates, register domains and DNS providers, control VPN-only access, and inspect what is going on in production.
8
8
 
9
9
  ## Issue Reporting and Security
10
10
 
11
11
  For reporting bugs, issues, or security vulnerabilities, please visit [community.foss.global/](https://community.foss.global/). This is the central community hub for all issue reporting. Developers who sign and comply with our contribution agreement and go through identification can also get a [code.foss.global/](https://code.foss.global/) account to submit Pull Requests directly.
12
12
 
13
- ## Table of Contents
14
-
15
- - [Features](#features)
16
- - [Installation](#installation)
17
- - [Quick Start](#quick-start)
18
- - [Architecture](#architecture)
19
- - [Configuration Reference](#configuration-reference)
20
- - [HTTP/HTTPS & TCP/SNI Routing](#httphttps--tcpsni-routing)
21
- - [HTTP/3 (QUIC) Support](#http3-quic-support)
22
- - [Email System](#email-system)
23
- - [DNS Server](#dns-server)
24
- - [RADIUS Server](#radius-server)
25
- - [Remote Ingress](#remote-ingress)
26
- - [VPN Access Control](#vpn-access-control)
27
- - [Certificate Management](#certificate-management)
28
- - [Storage & Database](#storage--database)
29
- - [Security Features](#security-features)
30
- - [OpsServer Dashboard](#opsserver-dashboard)
31
- - [API Client](#api-client)
32
- - [API Reference](#api-reference)
33
- - [Sub-Modules](#sub-modules)
34
- - [Testing](#testing)
35
- - [Docker / OCI Container Deployment](#docker--oci-container-deployment)
36
- - [License and Legal Information](#license-and-legal-information)
37
-
38
- ## Features
39
-
40
- ### 🌐 Universal Traffic Router
41
- - **HTTP/HTTPS routing** with domain matching, path-based forwarding, and automatic TLS
42
- - **HTTP/3 (QUIC) enabled by default** — qualifying HTTPS routes automatically get QUIC/H3 support with zero configuration
43
- - **TCP/SNI proxy** for any protocol with TLS termination or passthrough
44
- - **DNS server** (Rust-powered via [SmartDNS](https://code.foss.global/push.rocks/smartdns)) with authoritative zones, dynamic record management, and DNS-over-HTTPS
45
- - **Multi-protocol support** on the same infrastructure via [SmartProxy](https://code.foss.global/push.rocks/smartproxy)
46
-
47
- ### 📧 Complete Email Infrastructure (powered by [smartmta](https://code.foss.global/push.rocks/smartmta))
48
- - **Multi-domain SMTP server** on standard ports (25, 587, 465)
49
- - **Pattern-based email routing** with four action types: forward, process, deliver, reject
50
- - **DKIM signing & verification**, SPF, DMARC authentication stack
51
- - **Enterprise deliverability** with IP warmup schedules and sender reputation tracking
52
- - **Bounce handling** with automatic suppression lists
53
- - **Hierarchical rate limiting** — global, per-domain, per-sender
54
-
55
- ### 🔒 Enterprise Security
56
- - **Automatic TLS certificates** via ACME (smartacme v9) with Cloudflare DNS-01 challenges
57
- - **Smart certificate scheduling** — per-domain deduplication, controlled parallelism, and account rate limiting handled automatically
58
- - **Per-domain exponential backoff** — failed provisioning attempts are tracked and backed off to avoid hammering ACME servers
59
- - **IP reputation checking** with caching and configurable thresholds
60
- - **Content scanning** for spam, viruses, and malicious attachments
61
- - **Security event logging** with structured audit trails
62
-
63
- ### 📡 RADIUS Server
64
- - **MAC Authentication Bypass (MAB)** for network device authentication
65
- - **VLAN assignment** based on exact MAC, OUI prefix, or wildcard patterns
66
- - **RADIUS accounting** for session tracking, traffic metering, and billing
67
- - **Real-time management** via OpsServer API
68
-
69
- ### 🌍 Remote Ingress (powered by [remoteingress](https://code.foss.global/serve.zone/remoteingress))
70
- - **Distributed edge networking** — accept traffic at remote edge nodes and tunnel it to the hub
71
- - **Edge registration CRUD** with secret-based authentication
72
- - **Auto-derived ports** — edges automatically pick up ports from routes tagged with `remoteIngress.enabled`
73
- - **Connection tokens** — generate a single opaque base64url token containing hubHost, hubPort, edgeId, and secret for easy edge provisioning
74
- - **Real-time status monitoring** — connected/disconnected state, public IP, active tunnels, heartbeat tracking
75
- - **OpsServer dashboard** with enable/disable, edit, secret regeneration, token copy, and delete actions
76
-
77
- ### 🔐 VPN Access Control (powered by [smartvpn](https://code.foss.global/push.rocks/smartvpn))
78
- - **WireGuard + native transports** — standard WireGuard clients (iOS, Android, macOS, Windows, Linux) plus custom WebSocket/QUIC tunnels
79
- - **Route-level VPN gating** — mark any route with `vpn: { enabled: true }` to restrict access to VPN clients only, or `vpn: { enabled: true, mandatory: false }` to add VPN clients alongside existing access rules
80
- - **Tag-based access control** — assign `serverDefinedClientTags` to clients and restrict routes with `allowedServerDefinedClientTags`
81
- - **Constructor-defined clients** — pre-define VPN clients with tags in config for declarative, code-driven setup
82
- - **Rootless operation** — uses userspace NAT (smoltcp) with no root required
83
- - **Destination policy** — configurable `forceTarget`, `block`, or `allow` with allowList/blockList for granular traffic control
84
- - **Client management** — create, enable, disable, rotate keys, export WireGuard/SmartVPN configs via OpsServer API and dashboard
85
- - **IP-based enforcement** — VPN clients get IPs from a configurable subnet; SmartProxy enforces `ipAllowList` per route
86
- - **PROXY protocol v2** — the NAT engine sends PP v2 on outbound connections to preserve VPN client identity
87
-
88
- ### ⚡ High Performance
89
- - **Rust-powered proxy engine** via SmartProxy for maximum throughput
90
- - **Rust-powered MTA engine** via smartmta (TypeScript + Rust hybrid) for reliable email delivery
91
- - **Rust-powered DNS engine** via SmartDNS for high-performance UDP and DNS-over-HTTPS
92
- - **Connection pooling** for outbound SMTP and backend services
93
- - **Socket-handler mode** — direct socket passing eliminates internal port hops
94
- - **Real-time metrics** via SmartMetrics (CPU, memory, connections, throughput)
95
-
96
- ### 💾 Unified Database
97
- - **Two deployment modes**: embedded LocalSmartDb (zero-config) or external MongoDB
98
- - **15 document classes** covering routes, certs, VPN, RADIUS, security profiles, network targets, and caches
99
- - **Automatic TTL-based cleanup** for cached emails and IP reputation data
100
- - **Reusable references** — security profiles and network targets that propagate changes to all referencing routes
101
-
102
- ### 🖥️ OpsServer Dashboard
103
- - **Web-based management interface** with real-time monitoring
104
- - **JWT authentication** with session persistence
105
- - **Live views** for connections, email queues, DNS queries, RADIUS sessions, certificates, remote ingress edges, VPN clients, and security events
106
- - **Domain-centric certificate overview** with backoff status and one-click reprovisioning
107
- - **Remote ingress management** with connection token generation and one-click copy
108
- - **Security profiles & network targets** — reusable security configurations and host:port targets with propagation to referencing routes
109
- - **Global warning banners** when database is disabled (management features unavailable)
110
- - **Read-only configuration display** for system overview
111
- - **Smart tab visibility handling** — auto-pauses all polling, WebSocket connections, and chart updates when the browser tab is hidden, preventing resource waste and tab freezing
112
-
113
- ### 🔧 Programmatic API Client
114
- - **Object-oriented API** — resource classes (`Route`, `Certificate`, `ApiToken`, `RemoteIngress`, `Email`) with instance methods
115
- - **Builder pattern** — fluent `.setName().setMatch().save()` chains for creating routes, tokens, and edges
116
- - **Auto-injected auth** — JWT identity and API tokens included automatically in every request
117
- - **Dual auth modes** — login with credentials (JWT) or pass an API token for programmatic access
118
- - **Full coverage** — wraps every OpsServer endpoint with typed request/response pairs
13
+ ## Why dcrouter
14
+
15
+ - 🌐 Run HTTP/HTTPS, TCP/SNI, email, DNS, RADIUS, VPN, and remote ingress from one orchestrated service.
16
+ - 🔐 Keep certificates, routes, tokens, domains, and reusable route references in one management plane.
17
+ - 🧠 Use system-managed routes for config-, email-, and DNS-derived traffic, plus API-managed routes for dynamic additions.
18
+ - 📊 Get an Ops UI and TypedRequest API for monitoring, automation, and day-2 operations.
19
+ - Lean on Rust-backed data planes where it matters: proxying, DNS, email delivery, remote ingress, and VPN.
20
+
21
+ ## What It Covers
22
+
23
+ | Area | What dcrouter does |
24
+ | --- | --- |
25
+ | HTTP / HTTPS / TCP | SmartProxy-based routing, TLS termination or passthrough, path/domain matching, optional HTTP/3 augmentation |
26
+ | Email | smartmta-based SMTP ingress and delivery, route-based email handling, DKIM-aware domain support |
27
+ | DNS | Authoritative DNS, DNS-over-HTTPS bootstrap routes, provider-backed and dcrouter-hosted domains and records |
28
+ | Certificates | ACME-aware certificate management with dashboard and API support |
29
+ | Access control | Source profiles, network targets, VPN-gated routes, API tokens, admin auth |
30
+ | Network edge | Remote ingress hub for edge nodes tunneling traffic into the router |
31
+ | Operations | Web dashboard, TypedRequest API, logs, metrics, health, route and token management |
119
32
 
120
33
  ## Installation
121
34
 
122
35
  ```bash
123
36
  pnpm add @serve.zone/dcrouter
124
- # or
125
- npm install @serve.zone/dcrouter
126
37
  ```
127
38
 
128
- ### Prerequisites
129
-
130
- - **Node.js 20+** with ES module support
131
- - Valid domain with DNS control (for ACME certificate automation)
132
- - Cloudflare API token (for DNS-01 challenges) — optional
133
-
134
39
  ## Quick Start
135
40
 
136
- ### Basic HTTP/HTTPS Router
41
+ This is the smallest realistic setup: one HTTP route, embedded database enabled, and the Ops dashboard on port `3000`.
137
42
 
138
43
  ```typescript
139
44
  import { DcRouter } from '@serve.zone/dcrouter';
@@ -142,1533 +47,275 @@ const router = new DcRouter({
142
47
  smartProxyConfig: {
143
48
  routes: [
144
49
  {
145
- name: 'web-app',
146
- match: { domains: ['example.com', 'www.example.com'], ports: [443] },
147
- action: {
148
- type: 'forward',
149
- targets: [{ host: '192.168.1.10', port: 8080 }],
150
- tls: { mode: 'terminate', certificate: 'auto' }
151
- }
152
- }
153
- ],
154
- acme: {
155
- email: 'admin@example.com',
156
- enabled: true,
157
- useProduction: true
158
- }
159
- }
160
- });
161
-
162
- await router.start();
163
- ```
164
-
165
- ### Basic Email Server
166
-
167
- ```typescript
168
- import { DcRouter } from '@serve.zone/dcrouter';
169
-
170
- const router = new DcRouter({
171
- emailConfig: {
172
- ports: [25, 587, 465],
173
- hostname: 'mail.example.com',
174
- domains: [
175
- {
176
- domain: 'example.com',
177
- dnsMode: 'external-dns'
178
- }
179
- ],
180
- routes: [
181
- {
182
- name: 'process-all',
183
- match: { recipients: '*@example.com' },
184
- action: {
185
- type: 'process',
186
- process: { scan: true, dkim: true, queue: 'normal' }
187
- }
188
- }
189
- ]
190
- }
191
- });
192
-
193
- await router.start();
194
- ```
195
-
196
- ### Full Stack with Dashboard
197
-
198
- ```typescript
199
- import { DcRouter } from '@serve.zone/dcrouter';
200
-
201
- const router = new DcRouter({
202
- // HTTP/HTTPS routing
203
- smartProxyConfig: {
204
- routes: [
205
- {
206
- name: 'website',
207
- match: { domains: ['example.com'], ports: [443] },
50
+ name: 'app',
51
+ match: {
52
+ domains: ['app.example.com'],
53
+ ports: [80],
54
+ },
208
55
  action: {
209
56
  type: 'forward',
210
- targets: [{ host: '192.168.1.10', port: 80 }],
211
- tls: { mode: 'terminate', certificate: 'auto' }
212
- }
213
- }
214
- ],
215
- acme: { email: 'ssl@example.com', enabled: true, useProduction: true }
216
- },
217
-
218
- // Email system (powered by smartmta)
219
- emailConfig: {
220
- ports: [25, 587, 465],
221
- hostname: 'mail.example.com',
222
- domains: [{ domain: 'example.com', dnsMode: 'external-dns' }],
223
- routes: [
224
- {
225
- name: 'inbound-mail',
226
- match: { recipients: '*@example.com' },
227
- action: { type: 'process', process: { scan: true, dkim: true, queue: 'normal' } }
228
- }
229
- ]
230
- },
231
-
232
- // Authoritative DNS
233
- dnsNsDomains: ['ns1.example.com', 'ns2.example.com'],
234
- dnsScopes: ['example.com'],
235
- publicIp: '203.0.113.1',
236
- dnsRecords: [
237
- { name: 'example.com', type: 'A', value: '203.0.113.1' },
238
- { name: 'www.example.com', type: 'CNAME', value: 'example.com' }
239
- ],
240
-
241
- // RADIUS authentication
242
- radiusConfig: {
243
- authPort: 1812,
244
- acctPort: 1813,
245
- clients: [
246
- { name: 'switch-1', ipRange: '192.168.1.0/24', secret: 'radius-secret', enabled: true }
57
+ targets: [{ host: '127.0.0.1', port: 3001 }],
58
+ },
59
+ },
247
60
  ],
248
- vlanAssignment: {
249
- defaultVlan: 100,
250
- allowUnknownMacs: true,
251
- mappings: [
252
- { mac: 'aa:bb:cc:dd:ee:ff', vlan: 10, enabled: true },
253
- { mac: 'aa:bb:cc', vlan: 20, enabled: true } // OUI prefix
254
- ]
255
- },
256
- accounting: { enabled: true, retentionDays: 30 }
257
61
  },
258
-
259
- // Remote Ingress — edge nodes tunnel traffic to this hub
260
- remoteIngressConfig: {
62
+ dbConfig: {
261
63
  enabled: true,
262
- tunnelPort: 8443,
263
- hubDomain: 'hub.example.com',
264
64
  },
265
-
266
- // VPN — restrict sensitive routes to VPN clients
267
- vpnConfig: {
268
- enabled: true,
269
- serverEndpoint: 'vpn.example.com',
270
- clients: [
271
- { clientId: 'dev-laptop', serverDefinedClientTags: ['engineering'] },
272
- ],
273
- },
274
-
275
- // Unified database (embedded LocalSmartDb or external MongoDB)
276
- dbConfig: { enabled: true },
277
-
278
- // TLS & ACME
279
- tls: { contactEmail: 'admin@example.com' },
280
- dnsChallenge: { cloudflareApiKey: process.env.CLOUDFLARE_API_KEY }
65
+ opsServerPort: 3000,
281
66
  });
282
67
 
283
68
  await router.start();
284
- // OpsServer dashboard available at http://localhost:3000
285
- ```
286
-
287
- ## Architecture
288
-
289
- ### System Overview
290
-
291
- ```mermaid
292
- graph TB
293
- subgraph "External Traffic"
294
- HTTP[HTTP/HTTPS Clients]
295
- SMTP[SMTP Clients]
296
- TCP[TCP Clients]
297
- DNS[DNS Queries]
298
- RAD[RADIUS Clients]
299
- EDGE[Edge Nodes]
300
- VPN[VPN Clients]
301
- end
302
-
303
- subgraph "DcRouter Core"
304
- DC[DcRouter Orchestrator]
305
- SP[SmartProxy Engine<br/><i>Rust-powered</i>]
306
- ES[smartmta Email Server<br/><i>TypeScript + Rust</i>]
307
- DS[SmartDNS Server<br/><i>Rust-powered</i>]
308
- RS[SmartRadius Server]
309
- RI[RemoteIngress Hub<br/><i>Rust data plane</i>]
310
- VS[SmartVPN Server<br/><i>Rust data plane</i>]
311
- CM[Certificate Manager<br/><i>smartacme v9</i>]
312
- OS[OpsServer Dashboard]
313
- MM[Metrics Manager]
314
- DB2[DcRouterDb<br/><i>smartdata + smartdb</i>]
315
- end
316
-
317
- subgraph "Backend Services"
318
- WEB[Web Services]
319
- MAIL[Mail Servers]
320
- DB[Databases]
321
- API[Internal APIs]
322
- end
323
-
324
- HTTP --> SP
325
- TCP --> SP
326
- SMTP --> ES
327
- DNS --> DS
328
- RAD --> RS
329
- EDGE --> RI
330
- VPN --> VS
331
-
332
- DC --> SP
333
- DC --> ES
334
- DC --> DS
335
- DC --> RS
336
- DC --> RI
337
- DC --> VS
338
- DC --> CM
339
- DC --> OS
340
- DC --> MM
341
- DC --> DB2
342
-
343
- SP --> WEB
344
- SP --> API
345
- ES --> MAIL
346
- ES --> DB
347
- RI --> SP
348
-
349
- CM -.-> SP
350
- CM -.-> ES
351
- ```
352
-
353
- ### Core Components
354
-
355
- | Component | Package | Description |
356
- |-----------|---------|-------------|
357
- | **DcRouter** | `@serve.zone/dcrouter` | Central orchestrator — starts, stops, and coordinates all services |
358
- | **SmartProxy** | `@push.rocks/smartproxy` | High-performance HTTP/HTTPS and TCP/SNI proxy with route-based config (Rust engine) |
359
- | **UnifiedEmailServer** | `@push.rocks/smartmta` | Full SMTP server with pattern-based routing, DKIM, queue management (TypeScript + Rust) |
360
- | **DNS Server** | `@push.rocks/smartdns` | Authoritative DNS with dynamic records and DKIM TXT auto-generation (Rust engine) |
361
- | **SmartAcme** | `@push.rocks/smartacme` | ACME certificate management with per-domain dedup, concurrency control, and rate limiting |
362
- | **RADIUS Server** | `@push.rocks/smartradius` | Network authentication with MAB, VLAN assignment, and accounting |
363
- | **RemoteIngress** | `@serve.zone/remoteingress` | Distributed edge tunneling with Rust data plane and TS management |
364
- | **OpsServer** | `@api.global/typedserver` | Web dashboard + TypedRequest API for monitoring and management |
365
- | **MetricsManager** | `@push.rocks/smartmetrics` | Real-time metrics collection (CPU, memory, email, DNS, security) |
366
- | **DcRouterDb** | `@push.rocks/smartdata` + `@push.rocks/smartdb` | Unified database — embedded LocalSmartDb or external MongoDB for all persistence |
367
-
368
- ### How It Works
369
-
370
- DcRouter acts purely as an **orchestrator** — it doesn't implement protocols itself. Instead, it wires together best-in-class packages for each protocol:
371
-
372
- 1. **On `start()`**: DcRouter initializes OpsServer (default port 3000, configurable via `opsServerPort`), then spins up SmartProxy, smartmta, SmartDNS, SmartRadius, RemoteIngress, and SmartVPN based on which configs are provided. Services start in dependency order via `ServiceManager`.
373
- 2. **During operation**: Each service handles its own protocol independently. SmartProxy uses a Rust-powered engine for maximum throughput. smartmta uses a hybrid TypeScript + Rust architecture for reliable email delivery. RemoteIngress runs a Rust data plane for edge tunnel networking. SmartVPN runs a Rust data plane for WireGuard and custom transports. SmartAcme v9 handles all certificate operations with built-in concurrency control and rate limiting.
374
- 3. **On `stop()`**: All services are gracefully shut down in parallel, including cleanup of HTTP agents and DNS clients.
375
-
376
- ### Rust-Powered Architecture
377
-
378
- DcRouter itself is a pure TypeScript orchestrator, but several of its core sub-components ship with **compiled Rust binaries** for performance-critical paths. At runtime each package detects the platform, unpacks the correct binary, and communicates with TypeScript over IPC/FFI — so you get the ergonomics of TypeScript with the throughput of native code.
379
-
380
- | Component | Rust Binary | What It Handles |
381
- |-----------|-------------|-----------------|
382
- | **SmartProxy** | `smartproxy-bin` | All TCP/TLS/HTTP proxy networking, NFTables integration, connection metrics |
383
- | **smartmta** | `mailer-bin` | SMTP server + client, DKIM/SPF/DMARC, content scanning, IP reputation |
384
- | **SmartDNS** | `smartdns-bin` | DNS server (UDP + DNS-over-HTTPS), DNSSEC, DNS client resolution |
385
- | **RemoteIngress** | `remoteingress-bin` | Edge tunnel data plane, multiplexed streams, heartbeat management |
386
- | **SmartVPN** | `smartvpn_daemon` | WireGuard (boringtun), Noise IK handshake, QUIC/WS transports, userspace NAT (smoltcp) |
387
- | **SmartRadius** | — | Pure TypeScript (no Rust component) |
388
-
389
- ## Configuration Reference
390
-
391
- ### `IDcRouterOptions`
392
-
393
- ```typescript
394
- interface IDcRouterOptions {
395
- // ── Base ───────────────────────────────────────────────────────
396
- /** Base directory for all dcrouter data. Defaults to ~/.serve.zone/dcrouter */
397
- baseDir?: string;
398
-
399
- // ── Traffic Routing ────────────────────────────────────────────
400
- /** SmartProxy config for HTTP/HTTPS and TCP/SNI routing */
401
- smartProxyConfig?: ISmartProxyOptions;
402
-
403
- // ── Email ──────────────────────────────────────────────────────
404
- /** Unified email server configuration (smartmta) */
405
- emailConfig?: IUnifiedEmailServerOptions;
406
-
407
- /** Custom email port mapping overrides */
408
- emailPortConfig?: {
409
- portMapping?: Record<number, number>;
410
- portSettings?: Record<number, any>;
411
- receivedEmailsPath?: string;
412
- };
413
-
414
- // ── DNS ────────────────────────────────────────────────────────
415
- /** Nameserver domains — get A records automatically */
416
- dnsNsDomains?: string[];
417
- /** Domains this server is authoritative for */
418
- dnsScopes?: string[];
419
- /** Public IP for NS A records */
420
- publicIp?: string;
421
- /** Ingress proxy IPs (hides real server IP) */
422
- proxyIps?: string[];
423
- /** Custom DNS records */
424
- dnsRecords?: Array<{
425
- name: string;
426
- type: 'A' | 'AAAA' | 'CNAME' | 'MX' | 'TXT' | 'NS' | 'SOA';
427
- value: string;
428
- ttl?: number;
429
- useIngressProxy?: boolean;
430
- }>;
431
-
432
- // ── RADIUS ─────────────────────────────────────────────────────
433
- /** RADIUS server for network authentication */
434
- radiusConfig?: {
435
- authPort?: number; // default: 1812
436
- acctPort?: number; // default: 1813
437
- clients: IRadiusClient[];
438
- vlanAssignment?: IVlanManagerConfig;
439
- accounting?: { enabled: boolean; retentionDays?: number };
440
- };
441
-
442
- // ── Remote Ingress ─────────────────────────────────────────────
443
- /** Remote Ingress hub for edge tunnel connections */
444
- remoteIngressConfig?: {
445
- enabled?: boolean; // default: false
446
- tunnelPort?: number; // default: 8443
447
- hubDomain?: string; // External hostname for connection tokens
448
- tls?: {
449
- certPath?: string;
450
- keyPath?: string;
451
- };
452
- };
453
-
454
- // ── VPN ───────────────────────────────────────────────────────
455
- /** VPN server for route-level access control */
456
- vpnConfig?: {
457
- enabled?: boolean; // default: false
458
- subnet?: string; // default: '10.8.0.0/24'
459
- wgListenPort?: number; // default: 51820
460
- dns?: string[]; // DNS servers pushed to VPN clients
461
- serverEndpoint?: string; // Hostname in generated client configs
462
- clients?: Array<{ // Pre-defined VPN clients
463
- clientId: string;
464
- serverDefinedClientTags?: string[];
465
- description?: string;
466
- }>;
467
- destinationPolicy?: { // Traffic routing policy
468
- default: 'forceTarget' | 'block' | 'allow';
469
- target?: string; // IP for forceTarget (default: '127.0.0.1')
470
- allowList?: string[]; // Pass through directly
471
- blockList?: string[]; // Always block (overrides allowList)
472
- };
473
- };
474
-
475
- // ── HTTP/3 (QUIC) ────────────────────────────────────────────
476
- /** HTTP/3 config — enabled by default on qualifying HTTPS routes */
477
- http3?: {
478
- enabled?: boolean; // default: true
479
- quicSettings?: {
480
- maxIdleTimeout?: number; // default: 30000ms
481
- maxConcurrentBidiStreams?: number; // default: 100
482
- maxConcurrentUniStreams?: number; // default: 100
483
- initialCongestionWindow?: number;
484
- };
485
- altSvc?: {
486
- port?: number; // default: listening port
487
- maxAge?: number; // default: 86400s
488
- };
489
- udpSettings?: {
490
- sessionTimeout?: number; // default: 60000ms
491
- maxSessionsPerIP?: number; // default: 1000
492
- maxDatagramSize?: number; // default: 65535
493
- };
494
- };
495
-
496
- // ── OpsServer ────────────────────────────────────────────────
497
- /** Port for the OpsServer web dashboard (default: 3000) */
498
- opsServerPort?: number;
499
-
500
- // ── TLS & Certificates ────────────────────────────────────────
501
- tls?: {
502
- contactEmail: string;
503
- domain?: string;
504
- certPath?: string;
505
- keyPath?: string;
506
- };
507
- dnsChallenge?: { cloudflareApiKey?: string };
508
-
509
- // ── Database ────────────────────────────────────────────────────
510
- /** Unified database for all persistence (routes, certs, VPN, RADIUS, etc.) */
511
- dbConfig?: {
512
- enabled?: boolean; // default: true
513
- mongoDbUrl?: string; // External MongoDB URL (omit for embedded LocalSmartDb)
514
- storagePath?: string; // default: '~/.serve.zone/dcrouter/tsmdb'
515
- dbName?: string; // default: 'dcrouter'
516
- cleanupIntervalHours?: number; // default: 1
517
- seedOnEmpty?: boolean; // Seed default profiles/targets if DB is empty
518
- seedData?: object; // Custom seed data
519
- };
520
- }
521
- ```
522
-
523
- ## HTTP/HTTPS & TCP/SNI Routing
524
-
525
- DcRouter uses [SmartProxy](https://code.foss.global/push.rocks/smartproxy) for all HTTP/HTTPS and TCP/SNI routing. Routes are pattern-matched by domain, port, or both.
526
-
527
- ### HTTPS with Auto-TLS
528
-
529
- ```typescript
530
- {
531
- name: 'api-gateway',
532
- match: { domains: ['api.example.com'], ports: [443] },
533
- action: {
534
- type: 'forward',
535
- targets: [{ host: '192.168.1.20', port: 8080 }],
536
- tls: { mode: 'terminate', certificate: 'auto' }
537
- }
538
- }
539
- ```
540
-
541
- ### TLS Passthrough (SNI Routing)
542
-
543
- ```typescript
544
- {
545
- name: 'secure-backend',
546
- match: { domains: ['secure.example.com'], ports: [8443] },
547
- action: {
548
- type: 'forward',
549
- targets: [{ host: '192.168.1.40', port: 8443 }],
550
- tls: { mode: 'passthrough' }
551
- }
552
- }
553
- ```
554
-
555
- ### TCP Port Range Forwarding
556
-
557
- ```typescript
558
- {
559
- name: 'database-cluster',
560
- match: { ports: [{ from: 5432, to: 5439 }] },
561
- action: {
562
- type: 'forward',
563
- targets: [{ host: '192.168.1.30', port: 'preserve' }],
564
- security: { ipAllowList: ['192.168.1.0/24'] }
565
- }
566
- }
567
69
  ```
568
70
 
569
- ### HTTP Redirect
71
+ Once the router is running, you can:
570
72
 
571
- ```typescript
572
- {
573
- name: 'http-to-https',
574
- match: { ports: [80] },
575
- action: { type: 'redirect', redirect: { to: 'https://{domain}{path}' } }
576
- }
577
- ```
73
+ - open the Ops dashboard on `http://localhost:3000`
74
+ - inspect the route in the System Routes view
75
+ - add API-managed routes through the dashboard or API client
76
+ - enable DNS, email, VPN, remote ingress, or RADIUS by adding the corresponding config blocks
578
77
 
579
- ## HTTP/3 (QUIC) Support
78
+ ## Mental Model
580
79
 
581
- DcRouter ships with **HTTP/3 enabled by default** 🚀. All qualifying HTTPS routes on port 443 are automatically augmented with QUIC/H3 configuration no extra setup needed. Under the hood, SmartProxy's native HTTP/3 support (via `IRouteQuic`) handles QUIC transport, Alt-Svc advertisement, and HTTP/3 negotiation.
80
+ `dcrouter` is not a toy reverse proxy with a few side features. It is an orchestrator that wires multiple specialized services into one management plane.
582
81
 
583
- ### How It Works
82
+ | Layer | Responsibility |
83
+ | --- | --- |
84
+ | `DcRouter` | Startup order, shutdown, service wiring, configuration assembly, route hydration |
85
+ | SmartProxy | HTTP/HTTPS, TCP/SNI, TLS, HTTP/3-capable route execution |
86
+ | smartmta | SMTP ingress, queueing, DKIM-aware email processing and delivery |
87
+ | SmartDNS | Authoritative DNS and DoH request handling |
88
+ | smartradius | Network authentication, VLAN assignment, accounting |
89
+ | remoteingress | Edge tunnel registrations and runtime forwarding into the hub |
90
+ | smartvpn | VPN server and client access mediation for protected routes |
91
+ | OpsServer + dashboard | Typed API and browser UI for operations |
92
+ | smartdata-backed DB | Persistent routes, tokens, domains, records, profiles, cert metadata, caches |
584
93
 
585
- When DcRouter assembles routes in `setupSmartProxy()`, it automatically augments qualifying routes with:
586
- - `match.transport: 'all'` — listen on both TCP (HTTP/1.1 + HTTP/2) and UDP (QUIC/HTTP/3) on the same port
587
- - `action.udp.quic` — QUIC configuration with `enableHttp3: true` and `altSvcMaxAge: 86400`
94
+ ## Route Model
588
95
 
589
- Browsers that support HTTP/3 will discover it via the `Alt-Svc` header on initial TCP responses, then upgrade to QUIC for subsequent requests.
96
+ Routes fall into two ownership classes:
590
97
 
591
- ### What Gets Augmented
98
+ | Route kind | Origin | Ownership | What users can do |
99
+ | --- | --- | --- | --- |
100
+ | System routes | `config`, `email`, `dns` | Derived from config or runtime-managed subsystems | View and toggle only |
101
+ | API routes | `api` | Created through route-management API | Create, edit, delete, toggle |
592
102
 
593
- A route qualifies for HTTP/3 augmentation when **all** of these are true:
594
- - Port includes **443** (single number, array, or range)
595
- - Action type is **`forward`** (not `socket-handler`)
596
- - **TLS is enabled** (passthrough, terminate, or terminate-and-reencrypt)
597
- - Route is **not** an email route (ports 25/587/465)
598
- - Route doesn't already have `transport: 'all'` or existing `udp.quic` config
103
+ Important details:
599
104
 
600
- ### Zero-Config (Default Behavior)
105
+ - system routes are persisted with a stable `systemKey`
106
+ - config-, email-, and DNS-derived routes show up in the System Routes view
107
+ - DoH routes are persisted as system-route templates and get their live socket handlers attached at apply time
108
+ - system routes are managed by the system, not edited directly by operators
601
109
 
602
- ```typescript
603
- // HTTP/3 is ON by default — this route automatically gets QUIC/H3:
604
- const router = new DcRouter({
605
- smartProxyConfig: {
606
- routes: [{
607
- name: 'web-app',
608
- match: { domains: ['example.com'], ports: [443] },
609
- action: {
610
- type: 'forward',
611
- targets: [{ host: '192.168.1.10', port: 8080 }],
612
- tls: { mode: 'terminate', certificate: 'auto' }
613
- }
614
- }]
615
- }
616
- });
617
- ```
110
+ ## Core Features
618
111
 
619
- ### Per-Route Opt-Out
112
+ ### Traffic Routing
620
113
 
621
- Disable HTTP/3 on a specific route using `action.options.http3`:
114
+ - Domain-, port-, and path-based SmartProxy routes
115
+ - HTTP/HTTPS reverse proxying and generic TCP/SNI forwarding
116
+ - Optional HTTP/3 augmentation for qualifying HTTPS routes
117
+ - Reusable source profiles and network targets for route composition
118
+ - Remote ingress aware routing for edge-delivered traffic
622
119
 
623
- ```typescript
624
- {
625
- name: 'legacy-app',
626
- match: { domains: ['legacy.example.com'], ports: [443] },
627
- action: {
628
- type: 'forward',
629
- targets: [{ host: '192.168.1.50', port: 8080 }],
630
- tls: { mode: 'terminate', certificate: 'auto' },
631
- options: { http3: false } // ← This route stays TCP-only
632
- }
633
- }
634
- ```
120
+ ### Email
635
121
 
636
- ### Global Opt-Out
122
+ - smartmta-based inbound email handling
123
+ - Route-based mail actions such as forward, process, deliver, reject
124
+ - DKIM-aware domain handling and DNS record generation support
125
+ - Email-domain management through the Ops API and UI
126
+ - Queue, resend, failure, and delivery inspection through the dashboard and API
637
127
 
638
- Disable HTTP/3 across all routes:
128
+ ### DNS
639
129
 
640
- ```typescript
641
- const router = new DcRouter({
642
- http3: { enabled: false },
643
- smartProxyConfig: { routes: [/* ... */] }
644
- });
645
- ```
130
+ - Authoritative scopes via `dnsScopes`
131
+ - Bootstrap nameserver domains via `dnsNsDomains`
132
+ - DNS-over-HTTPS endpoints for `/dns-query` and `/resolve`
133
+ - Managed domains, managed records, and provider-backed DNS integrations
134
+ - Internal email DNS record generation for `internal-dns` email domains
646
135
 
647
- ### Custom QUIC Settings
136
+ ### Certificates and ACME
648
137
 
649
- Fine-tune QUIC parameters globally:
138
+ - Certificate overview and operations through OpsServer
139
+ - Import, export, delete, and reprovision flows
140
+ - DB-backed ACME configuration management
141
+ - Integration with managed DNS for certificate provisioning flows
142
+ - Routes can declare `certificate: 'auto'`, but actual automated issuance depends on ACME being configured in the management plane
650
143
 
651
- ```typescript
652
- const router = new DcRouter({
653
- http3: {
654
- quicSettings: {
655
- maxIdleTimeout: 60000, // 60s idle timeout
656
- maxConcurrentBidiStreams: 200, // More parallel streams
657
- maxConcurrentUniStreams: 50,
658
- },
659
- altSvc: {
660
- maxAge: 3600, // 1 hour Alt-Svc cache
661
- },
662
- udpSettings: {
663
- sessionTimeout: 120000, // 2 min UDP session timeout
664
- maxSessionsPerIP: 500,
665
- }
666
- },
667
- smartProxyConfig: { routes: [/* ... */] }
668
- });
669
- ```
144
+ ### VPN, RADIUS, and Remote Ingress
670
145
 
671
- ### Programmatic Routes
146
+ - VPN-gated routes with target-profile-based access matching
147
+ - WireGuard-oriented VPN management with dcrouter-side client lifecycle support
148
+ - RADIUS MAB, VLAN assignment, and accounting
149
+ - Remote ingress hub for edge nodes tunneling traffic into central routes
672
150
 
673
- Routes added at runtime via the Route Management API also get HTTP/3 augmentation automatically — the `RouteConfigManager` applies the same augmentation logic when merging programmatic routes.
151
+ ### Operations Plane
674
152
 
675
- ## Email System
153
+ - Web dashboard with overview, network, routes, access, security, domains, certificates, logs, and email views
154
+ - TypedRequest API for automation and external control
155
+ - API tokens with scoped access
156
+ - Metrics, health, logs, and per-feature operational views
676
157
 
677
- The email system is powered by [`@push.rocks/smartmta`](https://code.foss.global/push.rocks/smartmta), a TypeScript + Rust hybrid MTA. DcRouter configures and orchestrates smartmta's **UnifiedEmailServer**, which handles SMTP sessions, route matching, delivery queuing, DKIM signing, and all email processing.
158
+ ## Configuration Overview
678
159
 
679
- ### Email Domain Configuration
160
+ The main entry point is `IDcRouterOptions`.
680
161
 
681
- Domains define _infrastructure_ how DNS and DKIM are handled for each domain:
162
+ | Option | Purpose |
163
+ | --- | --- |
164
+ | `smartProxyConfig` | Main HTTP/HTTPS and TCP/SNI routing configuration |
165
+ | `emailConfig` | smartmta server config and email routes |
166
+ | `emailPortConfig` | External-to-internal email port mapping and email storage path tuning |
167
+ | `dnsNsDomains` | Nameserver hostnames used for NS bootstrap and DoH routes |
168
+ | `dnsScopes` | Authoritative DNS zones managed by dcrouter |
169
+ | `dnsRecords` | Static constructor-defined records |
170
+ | `publicIp` / `proxyIps` | DNS A-record exposure strategy |
171
+ | `dbConfig` | Embedded or external Mongo-backed persistence and seeding |
172
+ | `radiusConfig` | RADIUS authentication, VLAN, and accounting setup |
173
+ | `remoteIngressConfig` | Edge tunnel hub setup |
174
+ | `vpnConfig` | VPN server and client access configuration |
175
+ | `http3` | Global HTTP/3 behavior for qualifying routes |
176
+ | `opsServerPort` | Dashboard and TypedRequest API port |
682
177
 
683
- #### Forward Mode
684
- Simple forwarding without local DNS management:
685
- ```typescript
686
- {
687
- domain: 'forwarded.com',
688
- dnsMode: 'forward',
689
- dns: { forward: { skipDnsValidation: true, targetDomain: 'mail.target.com' } }
690
- }
691
- ```
178
+ ## Example: Enabling DNS, Email, and VPN
692
179
 
693
- #### Internal DNS Mode
694
- Uses DcRouter's built-in DNS server (requires `dnsNsDomains` + `dnsScopes`):
695
180
  ```typescript
696
- {
697
- domain: 'mail.example.com',
698
- dnsMode: 'internal-dns',
699
- dns: { internal: { mxPriority: 10, ttl: 3600 } },
700
- dkim: { selector: 'mail2024', keySize: 2048, rotateKeys: true, rotationInterval: 90 }
701
- }
702
- ```
703
-
704
- #### External DNS Mode
705
- Uses existing DNS infrastructure with validation:
706
- ```typescript
707
- {
708
- domain: 'mail.external.com',
709
- dnsMode: 'external-dns',
710
- dns: { external: { requiredRecords: ['MX', 'SPF', 'DKIM', 'DMARC'] } },
711
- rateLimits: {
712
- inbound: { messagesPerMinute: 100, connectionsPerIp: 10 },
713
- outbound: { messagesPerMinute: 200 }
714
- }
715
- }
716
- ```
717
-
718
- ### Email Route Actions
719
-
720
- Routes define _behavior_ — what happens when an email matches:
721
-
722
- #### Forward 📤
723
- Routes emails to an external SMTP server:
724
- ```typescript
725
- {
726
- name: 'forward-to-internal',
727
- match: { recipients: '*@company.com' },
728
- action: {
729
- type: 'forward',
730
- forward: {
731
- host: 'internal-mail.company.com',
732
- port: 25,
733
- auth: { user: 'relay-user', pass: 'relay-pass' },
734
- addHeaders: { 'X-Forwarded-By': 'dcrouter' }
735
- }
736
- }
737
- }
738
- ```
739
-
740
- #### Process ⚙️
741
- Full MTA processing with content scanning and delivery queues:
742
- ```typescript
743
- {
744
- name: 'process-notifications',
745
- match: { recipients: '*@notifications.company.com' },
746
- action: {
747
- type: 'process',
748
- process: { scan: true, dkim: true, queue: 'priority' }
749
- }
750
- }
751
- ```
752
-
753
- #### Deliver 📥
754
- Local mailbox delivery:
755
- ```typescript
756
- {
757
- name: 'deliver-local',
758
- match: { recipients: '*@local.company.com' },
759
- action: { type: 'deliver' }
760
- }
761
- ```
762
-
763
- #### Reject 🚫
764
- Reject with custom SMTP response code:
765
- ```typescript
766
- {
767
- name: 'reject-spam-domain',
768
- match: { senders: '*@spam-domain.com', sizeRange: { min: 1000000 } },
769
- action: {
770
- type: 'reject',
771
- reject: { code: 550, message: 'Message rejected due to policy' }
772
- }
773
- }
774
- ```
775
-
776
- ### Route Matching
777
-
778
- Routes support powerful matching criteria:
779
-
780
- ```typescript
781
- // Recipient patterns
782
- match: { recipients: '*@example.com' } // All addresses at domain
783
- match: { recipients: 'admin@*' } // "admin" at any domain
784
- match: { senders: ['*@trusted.com', '*@vip.com'] } // Multiple sender patterns
785
-
786
- // IP-based matching (CIDR)
787
- match: { clientIp: '192.168.0.0/16' }
788
- match: { clientIp: ['10.0.0.0/8', '172.16.0.0/12'] }
789
-
790
- // Authentication state
791
- match: { authenticated: true }
792
-
793
- // Header matching
794
- match: { headers: { 'X-Priority': 'high', 'Subject': /urgent|emergency/i } }
795
-
796
- // Size and content
797
- match: { sizeRange: { min: 1000, max: 5000000 }, hasAttachments: true }
798
- match: { subject: /invoice|receipt/i }
799
- ```
800
-
801
- ### Email Security Stack
802
-
803
- - **DKIM** — Automatic key generation, signing, and rotation for all domains
804
- - **SPF** — Sender Policy Framework verification on inbound mail
805
- - **DMARC** — Domain-based Message Authentication verification
806
- - **IP Reputation** — Real-time IP reputation checking with caching
807
- - **Content Scanning** — Spam, virus, and attachment scanning
808
- - **Rate Limiting** — Hierarchical limits (global → domain → sender)
809
- - **Bounce Management** — Automatic bounce detection and suppression lists
810
-
811
- ### Email Deliverability
812
-
813
- - **IP Warmup Manager** — Multi-stage warmup schedules for new IPs
814
- - **Sender Reputation Monitor** — Per-domain reputation tracking and scoring
815
- - **Connection Pooling** — Pooled outbound SMTP connections per destination
816
-
817
- ## DNS Server
818
-
819
- DcRouter includes an authoritative DNS server built on [smartdns](https://code.foss.global/push.rocks/smartdns). It handles standard UDP DNS on port 53 and DNS-over-HTTPS via SmartProxy socket handler.
820
-
821
- ### Enabling DNS
822
-
823
- DNS is activated when both `dnsNsDomains` and `dnsScopes` are configured:
824
-
825
- ```typescript
826
- const router = new DcRouter({
827
- dnsNsDomains: ['ns1.example.com', 'ns2.example.com'],
828
- dnsScopes: ['example.com'],
829
- publicIp: '203.0.113.1',
830
- dnsRecords: [
831
- { name: 'example.com', type: 'A', value: '203.0.113.1' },
832
- { name: 'www.example.com', type: 'CNAME', value: 'example.com' },
833
- { name: 'example.com', type: 'MX', value: '10:mail.example.com' },
834
- { name: 'example.com', type: 'TXT', value: 'v=spf1 a mx ~all' }
835
- ]
836
- });
837
- ```
838
-
839
- ### Automatic DNS Records
840
-
841
- DcRouter auto-generates:
842
- - **NS records** for all domains in `dnsScopes`
843
- - **SOA records** for authoritative zones
844
- - **A records** for nameserver domains (`dnsNsDomains`)
845
- - **MX, SPF, DKIM, DMARC records** for email domains with `internal-dns` mode
846
- - **ACME challenge records** for certificate provisioning
847
-
848
- ### Ingress Proxy Support
849
-
850
- When `proxyIps` is configured, A records with `useIngressProxy: true` (default) will use the proxy IP instead of the real server IP — hiding your origin:
851
-
852
- ```typescript
853
- {
854
- proxyIps: ['198.51.100.1', '198.51.100.2'],
855
- dnsRecords: [
856
- { name: 'example.com', type: 'A', value: '203.0.113.1' }, // Will resolve to 198.51.100.1
857
- { name: 'ns1.example.com', type: 'A', value: '203.0.113.1', useIngressProxy: false } // Stays real IP
858
- ]
859
- }
860
- ```
861
-
862
- ## RADIUS Server
863
-
864
- DcRouter includes a RADIUS server for network access control, built on [smartradius](https://code.foss.global/push.rocks/smartradius).
865
-
866
- ### Configuration
867
-
868
- ```typescript
869
- const router = new DcRouter({
870
- radiusConfig: {
871
- authPort: 1812,
872
- acctPort: 1813,
873
- clients: [
874
- {
875
- name: 'core-switch',
876
- ipRange: '192.168.1.0/24',
877
- secret: 'shared-secret',
878
- enabled: true
879
- }
880
- ],
881
- vlanAssignment: {
882
- defaultVlan: 100,
883
- allowUnknownMacs: true,
884
- mappings: [
885
- { mac: 'aa:bb:cc:dd:ee:ff', vlan: 10, enabled: true }, // Exact MAC
886
- { mac: 'aa:bb:cc', vlan: 20, enabled: true }, // OUI prefix
887
- ]
888
- },
889
- accounting: {
890
- enabled: true,
891
- retentionDays: 30
892
- }
893
- }
894
- });
895
- ```
896
-
897
- ### Components
898
-
899
- | Component | Purpose |
900
- |-----------|---------|
901
- | **RadiusServer** | Main RADIUS server handling auth + accounting requests |
902
- | **VlanManager** | MAC-to-VLAN mapping with exact, OUI, and wildcard patterns |
903
- | **AccountingManager** | Session tracking, traffic metering, start/stop/interim updates |
904
-
905
- ### OpsServer API
906
-
907
- RADIUS is fully manageable at runtime via the OpsServer API:
908
- - Client management (add/remove/list NAS devices)
909
- - VLAN mapping CRUD operations
910
- - Session monitoring and forced disconnects
911
- - Accounting summaries and statistics
912
-
913
- ## Remote Ingress
914
-
915
- DcRouter can act as a **hub** for distributed edge nodes using [`@serve.zone/remoteingress`](https://code.foss.global/serve.zone/remoteingress). Edge nodes accept incoming traffic at remote locations and tunnel it back to the hub over a single multiplexed connection. This is ideal for scenarios where you need to accept traffic at multiple geographic locations but process it centrally.
916
-
917
- ### Enabling Remote Ingress
181
+ import { DcRouter } from '@serve.zone/dcrouter';
918
182
 
919
- ```typescript
920
183
  const router = new DcRouter({
921
- remoteIngressConfig: {
922
- enabled: true,
923
- tunnelPort: 8443,
924
- hubDomain: 'hub.example.com', // Embedded in connection tokens
925
- },
926
- // Routes tagged with remoteIngress are auto-derived to edge listen ports
927
184
  smartProxyConfig: {
928
185
  routes: [
929
186
  {
930
- name: 'web-via-edge',
931
- match: { domains: ['app.example.com'], ports: [443] },
932
- action: {
933
- type: 'forward',
934
- targets: [{ host: '192.168.1.10', port: 8080 }],
935
- tls: { mode: 'terminate', certificate: 'auto' }
187
+ name: 'web-app',
188
+ match: {
189
+ domains: ['app.example.com'],
190
+ ports: [443],
936
191
  },
937
- remoteIngress: { enabled: true } // Edges will listen on port 443
938
- }
939
- ]
940
- }
941
- });
942
-
943
- await router.start();
944
- ```
945
-
946
- ### Edge Registration
947
-
948
- Edges are registered via the OpsServer API (or dashboard UI). Each edge gets a unique ID and secret:
949
-
950
- ```typescript
951
- // Via TypedRequest API
952
- const createReq = new TypedRequest<IReq_CreateRemoteIngress>(
953
- 'https://hub:3000/typedrequest', 'createRemoteIngress'
954
- );
955
- const { edge } = await createReq.fire({
956
- identity,
957
- name: 'edge-nyc-01',
958
- autoDerivePorts: true,
959
- tags: ['us-east'],
960
- });
961
- // edge.secret is returned only on creation — save it!
962
- ```
963
-
964
- ### Connection Tokens 🔑
965
-
966
- Instead of configuring edges with four separate values (hubHost, hubPort, edgeId, secret), DcRouter can generate a single **connection token** — an opaque base64url string that encodes everything:
967
-
968
- ```typescript
969
- // Via TypedRequest API
970
- const tokenReq = new TypedRequest<IReq_GetRemoteIngressConnectionToken>(
971
- 'https://hub:3000/typedrequest', 'getRemoteIngressConnectionToken'
972
- );
973
- const { token } = await tokenReq.fire({ identity, edgeId: 'edge-uuid' });
974
- // token = "eyJoIjoiaHViLmV4YW1wbGUuY29tIiwicCI6ODQ0MywiZSI6I..."
975
-
976
- // On the edge side, just pass the token:
977
- const edge = new RemoteIngressEdge({ token });
978
- await edge.start();
979
- ```
980
-
981
- The token is generated using `remoteingress.encodeConnectionToken()` and contains `{ hubHost, hubPort, edgeId, secret }`. The `hubHost` comes from `remoteIngressConfig.hubDomain` (or can be overridden per-request).
982
-
983
- In the OpsServer dashboard, click **"Copy Token"** on any edge row to copy the connection token to your clipboard.
984
-
985
- ### Auto-Derived Ports
986
-
987
- When routes have `remoteIngress: { enabled: true }`, edges with `autoDerivePorts: true` (default) automatically pick up those routes' ports. You can also use `edgeFilter` to restrict which edges get which ports:
988
-
989
- ```typescript
990
- {
991
- name: 'web-route',
992
- match: { ports: [443] },
993
- action: { /* ... */ },
994
- remoteIngress: {
995
- enabled: true,
996
- edgeFilter: ['us-east', 'edge-uuid-123'] // Only edges with matching id or tags
997
- }
998
- }
999
- ```
1000
-
1001
- ### Dashboard Actions
1002
-
1003
- The OpsServer Remote Ingress view provides:
1004
-
1005
- | Action | Description |
1006
- |--------|-------------|
1007
- | **Create Edge Node** | Register a new edge with name, ports, tags |
1008
- | **Enable / Disable** | Toggle an edge on or off |
1009
- | **Edit** | Modify name, manual ports, auto-derive setting, tags |
1010
- | **Regenerate Secret** | Issue a new secret (invalidates the old one) |
1011
- | **Copy Token** | Generate and copy a base64url connection token to clipboard |
1012
- | **Delete** | Remove the edge registration |
1013
-
1014
- ## VPN Access Control
1015
-
1016
- DcRouter integrates [`@push.rocks/smartvpn`](https://code.foss.global/push.rocks/smartvpn) to provide VPN-based route access control. VPN clients connect via standard WireGuard or native WebSocket/QUIC transports, receive an IP from a configurable subnet, and can then access routes that are restricted to VPN-only traffic.
1017
-
1018
- ### How It Works
1019
-
1020
- 1. **SmartVPN daemon** runs inside dcrouter with a Rust data plane (WireGuard via `boringtun`, custom protocol via Noise IK)
1021
- 2. Clients connect and get assigned an IP from the VPN subnet (e.g. `10.8.0.0/24`)
1022
- 3. **Smart split tunnel** — generated WireGuard configs auto-include the VPN subnet plus DNS-resolved IPs of VPN-gated domains. Domains from routes with `vpn.enabled` are resolved at config generation time, so clients route only the necessary traffic through the tunnel
1023
- 4. Routes with `vpn: { enabled: true }` get `security.ipAllowList` dynamically injected (re-computed on every client change). With `mandatory: true` (default), the allowlist is replaced; with `mandatory: false`, VPN IPs are appended to existing rules
1024
- 5. When `allowedServerDefinedClientTags` is set, only matching client IPs are injected (not the whole subnet)
1025
- 6. SmartProxy enforces the allowlist — only authorized VPN clients can access protected routes
1026
- 7. All VPN traffic is forced through SmartProxy via userspace NAT with PROXY protocol v2 — no root required
1027
-
1028
- ### Destination Policy
1029
-
1030
- By default, VPN client traffic is redirected to localhost (SmartProxy) via `forceTarget`. You can customize this with a destination policy:
1031
-
1032
- ```typescript
1033
- // Default: all traffic → SmartProxy
1034
- destinationPolicy: { default: 'forceTarget', target: '127.0.0.1' }
1035
-
1036
- // Allow direct access to a backend subnet
1037
- destinationPolicy: {
1038
- default: 'forceTarget',
1039
- target: '127.0.0.1',
1040
- allowList: ['192.168.190.*'], // direct access to this subnet
1041
- blockList: ['192.168.190.1'], // except the gateway
1042
- }
1043
-
1044
- // Block everything except specific IPs
1045
- destinationPolicy: {
1046
- default: 'block',
1047
- allowList: ['10.0.0.*', '192.168.1.*'],
1048
- }
1049
- ```
1050
-
1051
- ### Configuration
1052
-
1053
- ```typescript
1054
- const router = new DcRouter({
1055
- vpnConfig: {
1056
- enabled: true,
1057
- subnet: '10.8.0.0/24', // VPN client IP pool (default)
1058
- wgListenPort: 51820, // WireGuard UDP port (default)
1059
- serverEndpoint: 'vpn.example.com', // Hostname in generated client configs
1060
- dns: ['1.1.1.1', '8.8.8.8'], // DNS servers pushed to clients
1061
-
1062
- // Pre-define VPN clients with server-defined tags
1063
- clients: [
1064
- { clientId: 'alice-laptop', serverDefinedClientTags: ['engineering'], description: 'Dev laptop' },
1065
- { clientId: 'bob-phone', serverDefinedClientTags: ['engineering', 'mobile'] },
1066
- { clientId: 'carol-desktop', serverDefinedClientTags: ['finance'] },
1067
- ],
1068
-
1069
- // Optional: customize destination policy (default: forceTarget → localhost)
1070
- // destinationPolicy: { default: 'forceTarget', target: '127.0.0.1', allowList: ['192.168.1.*'] },
1071
- },
1072
- smartProxyConfig: {
1073
- routes: [
1074
- // 🔐 VPN-only: any VPN client can access
1075
- {
1076
- name: 'internal-app',
1077
- match: { domains: ['internal.example.com'], ports: [443] },
1078
192
  action: {
1079
193
  type: 'forward',
1080
- targets: [{ host: '192.168.1.50', port: 8080 }],
194
+ targets: [{ host: '127.0.0.1', port: 8080 }],
1081
195
  tls: { mode: 'terminate', certificate: 'auto' },
1082
196
  },
1083
- vpn: { enabled: true },
1084
197
  },
1085
- // 🔐 VPN + tag-restricted: only 'engineering' tagged clients
198
+ ],
199
+ },
200
+ emailConfig: {
201
+ hostname: 'mail.example.com',
202
+ ports: [25, 587, 465],
203
+ domains: [
1086
204
  {
1087
- name: 'eng-dashboard',
1088
- match: { domains: ['eng.example.com'], ports: [443] },
1089
- action: {
1090
- type: 'forward',
1091
- targets: [{ host: '192.168.1.51', port: 8080 }],
1092
- tls: { mode: 'terminate', certificate: 'auto' },
1093
- },
1094
- vpn: { enabled: true, allowedServerDefinedClientTags: ['engineering'] },
1095
- // → alice + bob can access, carol cannot
205
+ domain: 'example.com',
206
+ dnsMode: 'internal-dns',
1096
207
  },
1097
- // 🌐 Public: no VPN
208
+ ],
209
+ routes: [
1098
210
  {
1099
- name: 'public-site',
1100
- match: { domains: ['example.com'], ports: [443] },
211
+ name: 'inbound-mail',
212
+ match: { recipients: '*@example.com' },
1101
213
  action: {
1102
214
  type: 'forward',
1103
- targets: [{ host: '192.168.1.10', port: 80 }],
1104
- tls: { mode: 'terminate', certificate: 'auto' },
215
+ forward: { host: 'mail-backend.example.com', port: 25 },
1105
216
  },
1106
217
  },
1107
218
  ],
1108
219
  },
1109
- });
1110
- ```
1111
-
1112
- ### Client Tags
1113
-
1114
- SmartVPN distinguishes between two types of client tags:
1115
-
1116
- | Tag Type | Set By | Purpose |
1117
- |----------|--------|---------|
1118
- | `serverDefinedClientTags` | Admin (via config or API) | **Trusted** — used for route access control |
1119
- | `clientDefinedClientTags` | Connecting client | **Informational** — displayed in dashboard, never used for security |
1120
-
1121
- Routes with `allowedServerDefinedClientTags` only permit VPN clients whose admin-assigned tags match. Clients cannot influence their own server-defined tags.
1122
-
1123
- ### Client Management via OpsServer
1124
-
1125
- The OpsServer dashboard and API provide full VPN client lifecycle management:
1126
-
1127
- - **Create client** — generates WireGuard keypairs, assigns IP, returns a ready-to-use `.conf` file
1128
- - **QR code** — scan with the WireGuard mobile app (iOS/Android) for instant setup
1129
- - **Enable / Disable** — toggle client access without deleting
1130
- - **Rotate keys** — generate fresh keypairs (invalidates old ones)
1131
- - **Export config** — download in WireGuard (`.conf`), SmartVPN (`.json`), or scan as QR code
1132
- - **Telemetry** — per-client bytes sent/received, keepalives, rate limiting
1133
- - **Delete** — remove a client and revoke access
1134
-
1135
- Standard WireGuard clients on any platform (iOS, Android, macOS, Windows, Linux) can connect using the generated `.conf` file or by scanning the QR code — no custom VPN software needed.
1136
-
1137
- ## Certificate Management
1138
-
1139
- DcRouter uses [`@push.rocks/smartacme`](https://code.foss.global/push.rocks/smartacme) v9 for ACME certificate provisioning. smartacme v9 brings significant improvements over previous versions:
1140
-
1141
- ### How It Works
1142
-
1143
- When a `dnsChallenge` is configured (e.g. with a Cloudflare API key), DcRouter creates a SmartAcme instance that handles DNS-01 challenges for automatic certificate provisioning. SmartProxy calls the `certProvisionFunction` whenever a route needs a TLS certificate, and SmartAcme takes care of the rest.
1144
-
1145
- ```typescript
1146
- const router = new DcRouter({
1147
- smartProxyConfig: {
1148
- routes: [
220
+ dnsNsDomains: ['ns1.example.com', 'ns2.example.com'],
221
+ dnsScopes: ['example.com'],
222
+ publicIp: '203.0.113.10',
223
+ vpnConfig: {
224
+ enabled: true,
225
+ serverEndpoint: 'vpn.example.com',
226
+ clients: [
1149
227
  {
1150
- name: 'secure-app',
1151
- match: { domains: ['app.example.com'], ports: [443] },
1152
- action: {
1153
- type: 'forward',
1154
- targets: [{ host: '192.168.1.10', port: 8080 }],
1155
- tls: { mode: 'terminate', certificate: 'auto' } // ← triggers ACME provisioning
1156
- }
1157
- }
228
+ clientId: 'ops-laptop',
229
+ description: 'Operations laptop',
230
+ },
1158
231
  ],
1159
- acme: { email: 'admin@example.com', enabled: true, useProduction: true }
1160
232
  },
1161
- tls: { contactEmail: 'admin@example.com' },
1162
- dnsChallenge: { cloudflareApiKey: process.env.CLOUDFLARE_API_KEY }
233
+ dbConfig: {
234
+ enabled: true,
235
+ },
1163
236
  });
1164
- ```
1165
-
1166
- ### smartacme v9 Features
1167
-
1168
- | Feature | Description |
1169
- |---------|-------------|
1170
- | **Per-domain deduplication** | Concurrent requests for the same domain share a single ACME operation |
1171
- | **Global concurrency cap** | Default 5 parallel ACME operations to prevent overload |
1172
- | **Account rate limiting** | Sliding window (250 orders / 3 hours) to stay within ACME provider limits |
1173
- | **Structured errors** | `AcmeError` with `isRetryable`, `isRateLimited`, `retryAfter` fields |
1174
- | **Clean shutdown** | `stop()` properly destroys HTTP agents and DNS clients |
1175
-
1176
- ### Per-Domain Backoff
1177
-
1178
- DcRouter's `CertProvisionScheduler` adds **per-domain exponential backoff** on top of smartacme's built-in protections. If a DNS-01 challenge fails for a domain:
1179
-
1180
- 1. The failure is recorded (persisted to storage)
1181
- 2. The domain enters backoff: `min(failures² × 1 hour, 24 hours)`
1182
- 3. Subsequent requests for that domain are rejected until the backoff expires
1183
- 4. On success, the backoff is cleared
1184
-
1185
- This prevents hammering ACME servers for domains with persistent issues (e.g. missing DNS delegation).
1186
-
1187
- ### Fallback to HTTP-01
1188
-
1189
- If DNS-01 fails, the `certProvisionFunction` returns `'http01'` to tell SmartProxy to fall back to HTTP-01 challenge validation. This provides a safety net for domains where DNS-01 isn't viable.
1190
-
1191
- ### Certificate Storage
1192
-
1193
- Certificates are persisted via the `StorageBackedCertManager` which uses DcRouter's `StorageManager`. This means certs survive restarts and don't need to be re-provisioned unless they expire.
1194
-
1195
- ### Dashboard
1196
-
1197
- The OpsServer includes a **Certificates** view showing:
1198
- - All domains with their certificate status (valid, expiring, expired, failed)
1199
- - Certificate source (ACME, provision function, static)
1200
- - Expiry dates and issuer information
1201
- - Backoff status for failed domains
1202
- - One-click reprovisioning per domain
1203
- - Certificate import and export
1204
-
1205
- ## Storage & Database
1206
-
1207
- DcRouter uses a **unified database** (`DcRouterDb`) powered by [`@push.rocks/smartdata`](https://code.foss.global/push.rocks/smartdata) + [`@push.rocks/smartdb`](https://code.foss.global/push.rocks/smartdb) for all persistence. It supports two modes:
1208
-
1209
- ### Embedded LocalSmartDb (Default)
1210
-
1211
- Zero-config, file-based MongoDB-compatible database — no external services needed:
1212
-
1213
- ```typescript
1214
- dbConfig: { enabled: true }
1215
- // Data stored at ~/.serve.zone/dcrouter/tsmdb by default
1216
- ```
1217
-
1218
- ### External MongoDB
1219
-
1220
- Connect to an existing MongoDB instance:
1221
237
 
1222
- ```typescript
1223
- dbConfig: {
1224
- enabled: true,
1225
- mongoDbUrl: 'mongodb://localhost:27017',
1226
- dbName: 'dcrouter',
1227
- }
1228
- ```
1229
-
1230
- ### Disabling the Database
1231
-
1232
- For static, constructor-only deployments where no runtime management is needed:
1233
-
1234
- ```typescript
1235
- dbConfig: { enabled: false }
1236
- // Routes come exclusively from constructor config — no CRUD, no persistence
1237
- // OpsServer still runs but management features are disabled
1238
- ```
1239
-
1240
- ### What's Stored
1241
-
1242
- DcRouterDb persists all runtime state across 15 document classes:
1243
-
1244
- | Category | Documents | Purpose |
1245
- |----------|-----------|---------|
1246
- | **Routes** | `StoredRouteDoc`, `RouteOverrideDoc` | Programmatic routes and hardcoded route overrides |
1247
- | **Certificates** | `ProxyCertDoc`, `AcmeCertDoc`, `CertBackoffDoc` | TLS certs, ACME state, per-domain backoff |
1248
- | **Auth** | `ApiTokenDoc` | API token storage |
1249
- | **Remote Ingress** | `RemoteIngressEdgeDoc` | Edge node registrations |
1250
- | **VPN** | `VpnServerKeysDoc`, `VpnClientDoc` | Server keys and client registrations |
1251
- | **RADIUS** | `VlanMappingsDoc`, `AccountingSessionDoc` | VLAN mappings and accounting sessions |
1252
- | **References** | `SecurityProfileDoc`, `NetworkTargetDoc` | Reusable security profiles and network targets |
1253
- | **Cache** | `CachedEmailDoc`, `CachedIpReputationDoc` | TTL-based caches with automatic cleanup |
1254
-
1255
- ## Security Features
1256
-
1257
- ### IP Reputation Checking
1258
-
1259
- Automatic IP reputation checks on inbound connections with configurable caching:
1260
-
1261
- ```typescript
1262
- // IP reputation is checked automatically for inbound SMTP connections.
1263
- // Results are cached according to cacheConfig.ttlConfig.ipReputation.
1264
- ```
1265
-
1266
- ### Rate Limiting
1267
-
1268
- Hierarchical rate limits with three levels of specificity:
1269
-
1270
- ```typescript
1271
- // Global defaults (via emailConfig.defaults.rateLimits)
1272
- defaults: {
1273
- rateLimits: {
1274
- inbound: { messagesPerMinute: 50, connectionsPerIp: 5, recipientsPerMessage: 50 },
1275
- outbound: { messagesPerMinute: 100 }
1276
- }
1277
- }
1278
-
1279
- // Per-domain overrides (in domain config)
1280
- {
1281
- domain: 'high-volume.com',
1282
- rateLimits: {
1283
- outbound: { messagesPerMinute: 500 } // Override for this domain
1284
- }
1285
- }
1286
- ```
1287
-
1288
- **Precedence**: Domain-specific > Pattern-specific > Global
1289
-
1290
- ### Content Scanning
1291
-
1292
- ```typescript
1293
- action: {
1294
- type: 'process',
1295
- options: {
1296
- contentScanning: true,
1297
- scanners: [
1298
- { type: 'spam', threshold: 5.0, action: 'tag' },
1299
- { type: 'virus', action: 'reject' },
1300
- { type: 'attachment', blockedExtensions: ['.exe', '.bat', '.scr'], action: 'reject' }
1301
- ]
1302
- }
1303
- }
238
+ await router.start();
1304
239
  ```
1305
240
 
1306
- ## OpsServer Dashboard
241
+ ## Operations API and Dashboard
1307
242
 
1308
- The OpsServer provides a web-based management interface served on port 3000 by default (configurable via `opsServerPort`). It's built with modern web components using [@design.estate/dees-catalog](https://code.foss.global/design.estate/dees-catalog).
243
+ With the database enabled, dcrouter exposes a management plane for:
1309
244
 
1310
- ### Dashboard Views
245
+ - routes and route toggles
246
+ - API tokens
247
+ - source profiles and network targets
248
+ - DNS providers, domains, and records
249
+ - ACME configuration and certificate lifecycle
250
+ - email domains and email operations
251
+ - VPN clients, remote ingress edges, and RADIUS data
1311
252
 
1312
- | View | Description |
1313
- |------|-------------|
1314
- | 📊 **Overview** | Real-time server stats, CPU/memory, connection counts, email throughput |
1315
- | 🌐 **Network** | Active connections, top IPs, throughput rates, SmartProxy metrics |
1316
- | 📧 **Email** | Queue monitoring (queued/sent/failed), bounce records, security incidents |
1317
- | 🛣️ **Routes** | Merged route list (hardcoded + programmatic), create/edit/toggle/override routes |
1318
- | 🔑 **API Tokens** | Token management with scopes, create/revoke/roll/toggle |
1319
- | 🔐 **Certificates** | Domain-centric certificate overview, status, backoff info, reprovisioning, import/export |
1320
- | 🌍 **RemoteIngress** | Edge node management, connection status, token generation, enable/disable |
1321
- | 🔐 **VPN** | VPN client management, server status, create/toggle/export/rotate/delete clients |
1322
- | 🛡️ **Security Profiles** | Reusable security configurations (IP allow/block lists, rate limits) |
1323
- | 🎯 **Network Targets** | Reusable host:port destinations for route references |
1324
- | 📡 **RADIUS** | NAS client management, VLAN mappings, session monitoring, accounting |
1325
- | 📜 **Logs** | Real-time log viewer with level filtering and search |
1326
- | ⚙️ **Configuration** | Read-only view of current system configuration |
1327
- | 🛡️ **Security** | IP reputation, rate limit status, blocked connections |
253
+ The browser dashboard is built from the `ts_web` package and is served by OpsServer. The same backend is accessible programmatically via TypedRequest or the dedicated API client package.
1328
254
 
1329
- ### API Endpoints
255
+ ## Programmatic API Client
1330
256
 
1331
- All management is done via TypedRequest over HTTP POST to `/typedrequest`:
1332
-
1333
- ```typescript
1334
- // Authentication
1335
- 'adminLoginWithUsernameAndPassword' // Login with credentials → returns JWT identity
1336
- 'verifyIdentity' // Verify JWT token validity
1337
- 'adminLogout' // End admin session
1338
-
1339
- // Statistics & Health
1340
- 'getServerStatistics' // Uptime, CPU, memory, connections
1341
- 'getHealthStatus' // System health check
1342
- 'getCombinedMetrics' // All metrics in one call
1343
-
1344
- // Email Operations
1345
- 'getAllEmails' // List all emails (queued/sent/failed)
1346
- 'getEmailDetail' // Full detail for a specific email
1347
- 'resendEmail' // Re-queue a failed email
1348
-
1349
- // Certificates
1350
- 'getCertificateOverview' // Domain-centric certificate status
1351
- 'reprovisionCertificate' // Reprovision by route name (legacy)
1352
- 'reprovisionCertificateDomain' // Reprovision by domain (preferred)
1353
- 'importCertificate' // Import a certificate
1354
- 'exportCertificate' // Export a certificate
1355
- 'deleteCertificate' // Delete a certificate
1356
-
1357
- // Remote Ingress
1358
- 'getRemoteIngresses' // List all edge registrations
1359
- 'createRemoteIngress' // Register a new edge
1360
- 'updateRemoteIngress' // Update edge settings
1361
- 'deleteRemoteIngress' // Remove an edge
1362
- 'regenerateRemoteIngressSecret' // Issue a new secret
1363
- 'getRemoteIngressStatus' // Runtime status of all edges
1364
- 'getRemoteIngressConnectionToken' // Generate a connection token for an edge
1365
-
1366
- // Route Management (JWT or API token auth)
1367
- 'getMergedRoutes' // List all routes (hardcoded + programmatic)
1368
- 'createRoute' // Create a new programmatic route
1369
- 'updateRoute' // Update a programmatic route
1370
- 'deleteRoute' // Delete a programmatic route
1371
- 'toggleRoute' // Enable/disable a programmatic route
1372
- 'setRouteOverride' // Override a hardcoded route
1373
- 'removeRouteOverride' // Remove a hardcoded route override
1374
-
1375
- // API Token Management (admin JWT only)
1376
- 'createApiToken' // Create API token → returns raw value once
1377
- 'listApiTokens' // List all tokens (without secrets)
1378
- 'revokeApiToken' // Delete an API token
1379
- 'rollApiToken' // Regenerate token secret
1380
- 'toggleApiToken' // Enable/disable a token
1381
-
1382
- // Configuration (read-only)
1383
- 'getConfiguration' // Current system config
1384
-
1385
- // Logs
1386
- 'getRecentLogs' // Retrieve system logs with filtering
1387
- 'getLogStream' // Stream live logs
1388
-
1389
- // VPN
1390
- 'getVpnClients' // List all registered VPN clients
1391
- 'getVpnStatus' // VPN server status (running, subnet, port, keys)
1392
- 'createVpnClient' // Create client → returns WireGuard config (shown once)
1393
- 'deleteVpnClient' // Remove a VPN client
1394
- 'enableVpnClient' // Enable a disabled client
1395
- 'disableVpnClient' // Disable a client
1396
- 'rotateVpnClientKey' // Generate new keys (invalidates old ones)
1397
- 'exportVpnClientConfig' // Export WireGuard (.conf) or SmartVPN (.json) config
1398
- 'getVpnClientTelemetry' // Per-client bytes sent/received, keepalives
1399
-
1400
- // RADIUS
1401
- 'getRadiusSessions' // Active RADIUS sessions
1402
- 'getRadiusClients' // List NAS clients
1403
- 'getRadiusStatistics' // RADIUS stats
1404
- 'setRadiusClient' // Add/update NAS client
1405
- 'removeRadiusClient' // Remove NAS client
1406
- 'getVlanMappings' // List VLAN mappings
1407
- 'setVlanMapping' // Add/update VLAN mapping
1408
- 'removeVlanMapping' // Remove VLAN mapping
1409
- 'testVlanAssignment' // Test what VLAN a MAC gets
1410
-
1411
- // Security Profiles
1412
- 'getSecurityProfiles' // List all security profiles
1413
- 'getSecurityProfile' // Get a single profile by ID
1414
- 'createSecurityProfile' // Create a reusable security profile
1415
- 'updateSecurityProfile' // Update a profile (propagates to referencing routes)
1416
- 'deleteSecurityProfile' // Delete a profile (with optional force)
1417
- 'getSecurityProfileUsage' // Get routes referencing a profile
1418
-
1419
- // Network Targets
1420
- 'getNetworkTargets' // List all network targets
1421
- 'getNetworkTarget' // Get a single target by ID
1422
- 'createNetworkTarget' // Create a reusable host:port target
1423
- 'updateNetworkTarget' // Update a target (propagates to referencing routes)
1424
- 'deleteNetworkTarget' // Delete a target (with optional force)
1425
- 'getNetworkTargetUsage' // Get routes referencing a target
1426
- ```
1427
-
1428
- ## API Client
1429
-
1430
- DcRouter ships with a typed, object-oriented API client for programmatic management of a running instance. Install it separately or import from the main package:
257
+ Use the API client when you want automation or integration code instead of clicking through the dashboard.
1431
258
 
1432
259
  ```bash
1433
260
  pnpm add @serve.zone/dcrouter-apiclient
1434
- # or import from the main package:
1435
- # import { DcRouterApiClient } from '@serve.zone/dcrouter/apiclient';
1436
261
  ```
1437
262
 
1438
- ### Quick Example
1439
-
1440
263
  ```typescript
1441
264
  import { DcRouterApiClient } from '@serve.zone/dcrouter/apiclient';
1442
265
 
1443
- const client = new DcRouterApiClient({ baseUrl: 'https://dcrouter.example.com' });
266
+ const client = new DcRouterApiClient({
267
+ baseUrl: 'https://dcrouter.example.com',
268
+ });
269
+
1444
270
  await client.login('admin', 'password');
1445
271
 
1446
- // OO resource instances with methods
1447
272
  const { routes } = await client.routes.list();
1448
- await routes[0].toggle(false);
273
+ const systemRoutes = routes.filter((route) => route.origin !== 'api');
274
+
275
+ if (systemRoutes[0]) {
276
+ await systemRoutes[0].toggle(false);
277
+ }
1449
278
 
1450
- // Builder pattern for creation
1451
- const newRoute = await client.routes.build()
279
+ await client.routes.build()
1452
280
  .setName('api-gateway')
1453
281
  .setMatch({ ports: 443, domains: ['api.example.com'] })
1454
- .setAction({ type: 'forward', targets: [{ host: 'backend', port: 8080 }] })
1455
- .setTls({ mode: 'terminate', certificate: 'auto' })
1456
- .save();
1457
-
1458
- // Manage certificates
1459
- const { certificates, summary } = await client.certificates.list();
1460
- await certificates[0].reprovision();
1461
-
1462
- // Create API tokens with builder
1463
- const token = await client.apiTokens.build()
1464
- .setName('ci-token')
1465
- .setScopes(['routes:read', 'routes:write'])
1466
- .setExpiresInDays(90)
282
+ .setAction({ type: 'forward', targets: [{ host: '127.0.0.1', port: 8081 }] })
1467
283
  .save();
1468
- console.log(token.tokenValue); // only available at creation
1469
-
1470
- // Remote ingress edges
1471
- const edge = await client.remoteIngress.build()
1472
- .setName('edge-nyc-01')
1473
- .setListenPorts([80, 443])
1474
- .save();
1475
- const connToken = await edge.getConnectionToken();
1476
-
1477
- // Read-only managers
1478
- const health = await client.stats.getHealth();
1479
- const config = await client.config.get();
1480
- const { logs } = await client.logs.getRecent({ level: 'error', limit: 50 });
1481
- ```
1482
-
1483
- ### Resource Managers
1484
-
1485
- | Manager | Operations |
1486
- |---------|-----------|
1487
- | `client.routes` | `list()`, `create()`, `build()` → Route: `update()`, `delete()`, `toggle()`, `setOverride()`, `removeOverride()` |
1488
- | `client.certificates` | `list()`, `import()` → Certificate: `reprovision()`, `delete()`, `export()` |
1489
- | `client.apiTokens` | `list()`, `create()`, `build()` → ApiToken: `revoke()`, `roll()`, `toggle()` |
1490
- | `client.remoteIngress` | `list()`, `getStatuses()`, `create()`, `build()` → RemoteIngress: `update()`, `delete()`, `regenerateSecret()`, `getConnectionToken()` |
1491
- | `client.stats` | `getServer()`, `getEmail()`, `getDns()`, `getSecurity()`, `getConnections()`, `getQueues()`, `getHealth()`, `getNetwork()`, `getCombined()` |
1492
- | `client.config` | `get(section?)` |
1493
- | `client.logs` | `getRecent()`, `getStream()` |
1494
- | `client.emails` | `list()` → Email: `getDetail()`, `resend()` |
1495
- | `client.radius` | `.clients`, `.vlans`, `.sessions` sub-managers + `getStatistics()`, `getAccountingSummary()` |
1496
-
1497
- See the [full API client documentation](./ts_apiclient/readme.md) for detailed usage of every manager, builder, and resource class.
1498
-
1499
- ## API Reference
1500
-
1501
- ### DcRouter Class
1502
-
1503
- ```typescript
1504
- import { DcRouter } from '@serve.zone/dcrouter';
1505
-
1506
- const router = new DcRouter(options: IDcRouterOptions);
1507
284
  ```
1508
285
 
1509
- #### Methods
1510
-
1511
- | Method | Description |
1512
- |--------|-------------|
1513
- | `start(): Promise<void>` | Start all configured services |
1514
- | `stop(): Promise<void>` | Gracefully stop all services |
1515
- | `updateSmartProxyConfig(config): Promise<void>` | Hot-update SmartProxy routes |
1516
- | `updateEmailConfig(config): Promise<void>` | Hot-update email configuration |
1517
- | `updateEmailRoutes(routes): Promise<void>` | Update email routing rules at runtime |
1518
- | `updateRadiusConfig(config): Promise<void>` | Hot-update RADIUS configuration |
1519
- | `getStats(): any` | Get real-time statistics from all services |
1520
-
1521
- #### Properties
1522
-
1523
- | Property | Type | Description |
1524
- |----------|------|-------------|
1525
- | `options` | `IDcRouterOptions` | Current configuration |
1526
- | `smartProxy` | `SmartProxy` | SmartProxy instance |
1527
- | `smartAcme` | `SmartAcme` | SmartAcme v9 certificate manager instance |
1528
- | `emailServer` | `UnifiedEmailServer` | Email server instance (from smartmta) |
1529
- | `dnsServer` | `DnsServer` | DNS server instance |
1530
- | `radiusServer` | `RadiusServer` | RADIUS server instance |
1531
- | `remoteIngressManager` | `RemoteIngressManager` | Edge registration CRUD manager |
1532
- | `tunnelManager` | `TunnelManager` | Tunnel lifecycle and status manager |
1533
- | `vpnManager` | `VpnManager` | VPN server lifecycle and client CRUD manager |
1534
- | `opsServer` | `OpsServer` | OpsServer/dashboard instance |
1535
- | `metricsManager` | `MetricsManager` | Metrics collector |
1536
- | `dcRouterDb` | `DcRouterDb` | Unified database instance (smartdata + smartdb) |
1537
- | `routeConfigManager` | `RouteConfigManager` | Programmatic route CRUD manager |
1538
- | `apiTokenManager` | `ApiTokenManager` | API token management |
1539
- | `referenceResolver` | `ReferenceResolver` | Security profile and network target resolver |
1540
-
1541
- ### Re-exported Types
1542
-
1543
- DcRouter re-exports key types for convenience:
286
+ See `./ts_apiclient/readme.md` for the dedicated API-client package docs.
1544
287
 
1545
- ```typescript
1546
- import {
1547
- DcRouter,
1548
- IDcRouterOptions,
1549
- UnifiedEmailServer,
1550
- type IUnifiedEmailServerOptions,
1551
- type IEmailRoute,
1552
- type IEmailDomainConfig,
1553
- type IHttp3Config,
1554
- } from '@serve.zone/dcrouter';
1555
- ```
1556
-
1557
- ## Sub-Modules
288
+ ## Published Modules
1558
289
 
1559
- DcRouter is published as a monorepo with separately-installable interface and web packages:
290
+ This repository publishes multiple modules from the same codebase.
1560
291
 
1561
- | Package | Description | Install |
1562
- |---------|-------------|---------|
1563
- | [`@serve.zone/dcrouter`](https://www.npmjs.com/package/@serve.zone/dcrouter) | Main package the full router | `pnpm add @serve.zone/dcrouter` |
1564
- | [`@serve.zone/dcrouter-interfaces`](https://www.npmjs.com/package/@serve.zone/dcrouter-interfaces) | TypedRequest interfaces for the OpsServer API | `pnpm add @serve.zone/dcrouter-interfaces` |
1565
- | [`@serve.zone/dcrouter-apiclient`](https://www.npmjs.com/package/@serve.zone/dcrouter-apiclient) | OO API client with builder pattern | `pnpm add @serve.zone/dcrouter-apiclient` |
1566
- | [`@serve.zone/dcrouter-web`](https://www.npmjs.com/package/@serve.zone/dcrouter-web) | Web dashboard components | `pnpm add @serve.zone/dcrouter-web` |
292
+ | Module | Purpose | Docs |
293
+ | --- | --- | --- |
294
+ | `@serve.zone/dcrouter` | Main orchestrator and server package | `./readme.md` |
295
+ | `@serve.zone/dcrouter-interfaces` | Shared TypedRequest request and data interfaces | `./ts_interfaces/readme.md` |
296
+ | `@serve.zone/dcrouter-migrations` | Startup migration runner for dcrouter data | `./ts_migrations/readme.md` |
297
+ | `@serve.zone/dcrouter-web` | Web dashboard entry and UI components | `./ts_web/readme.md` |
298
+ | `@serve.zone/dcrouter-apiclient` | Typed OO API client | `./ts_apiclient/readme.md` |
1567
299
 
1568
- You can also import directly from the main package:
1569
-
1570
- ```typescript
1571
- import { data, requests } from '@serve.zone/dcrouter/interfaces';
1572
- import { DcRouterApiClient } from '@serve.zone/dcrouter/apiclient';
1573
- ```
1574
-
1575
- ## Testing
1576
-
1577
- DcRouter includes a comprehensive test suite covering all system components:
300
+ ## Development and Testing
1578
301
 
1579
302
  ```bash
1580
- # Run all tests
303
+ pnpm run build
1581
304
  pnpm test
1582
-
1583
- # Run a specific test file
1584
- tstest test/test.jwt-auth.ts --verbose
1585
-
1586
- # Run with extended timeout
1587
- tstest test/test.opsserver-api.ts --verbose --timeout 60
1588
305
  ```
1589
306
 
1590
- ### Test Coverage
1591
-
1592
- | Test File | Area | Tests |
1593
- |-----------|------|-------|
1594
- | `test.apiclient.ts` | API client instantiation, builders, resource hydration, exports | 18 |
1595
- | `test.contentscanner.ts` | Content scanning (spam, phishing, malware, attachments) | 13 |
1596
- | `test.dcrouter.email.ts` | Email config, domain and route setup | 4 |
1597
- | `test.dns-server-config.ts` | DNS record parsing, grouping, extraction | 5 |
1598
- | `test.dns-socket-handler.ts` | DNS socket handler and route generation | 6 |
1599
- | `test.errors.ts` | Error classes, handler, retry utilities | 5 |
1600
- | `test.http3-augmentation.ts` | HTTP/3 route augmentation, qualification, opt-in/out, QUIC settings | 20 |
1601
- | `test.ipreputationchecker.ts` | IP reputation, DNSBL, caching, risk classification | 10 |
1602
- | `test.jwt-auth.ts` | JWT login, verification, logout, invalid credentials | 8 |
1603
- | `test.opsserver-api.ts` | Health, statistics, configuration, log APIs | 8 |
1604
- | `test.protected-endpoint.ts` | Admin auth, identity verification, public endpoints | 8 |
1605
- | `test.reference-resolver.ts` | Security profiles, network targets, route resolution | 20 |
1606
- | `test.security-profiles-api.ts` | Profile/target API endpoints, auth enforcement | 13 |
1607
-
1608
- ## Docker / OCI Container Deployment
1609
-
1610
- DcRouter ships with a production-ready `Dockerfile` and supports environment-variable-driven configuration for OCI container deployments. The container image includes tini as PID 1 (via the base image), proper health checks, and configurable resource limits. When `DCROUTER_MODE=OCI_CONTAINER` is set, DcRouter automatically reads configuration from environment variables (and optionally from a JSON config file).
1611
-
1612
- ### Running with Docker
307
+ Target a single test file while working on one area:
1613
308
 
1614
309
  ```bash
1615
- docker run -d \
1616
- --ulimit nofile=65536:65536 \
1617
- -e DCROUTER_TLS_EMAIL=admin@example.com \
1618
- -e DCROUTER_PUBLIC_IP=203.0.113.1 \
1619
- -e DCROUTER_DNS_NS_DOMAINS=ns1.example.com,ns2.example.com \
1620
- -e DCROUTER_DNS_SCOPES=example.com \
1621
- -p 80:80 -p 443:443 -p 25:25 -p 587:587 -p 465:465 \
1622
- -p 53:53/udp -p 3000:3000 -p 8443:8443 \
1623
- code.foss.global/serve.zone/dcrouter:latest
310
+ tstest test/test.dns-runtime-routes.node.ts --verbose
1624
311
  ```
1625
312
 
1626
- > **Production tip:** Always set `--ulimit nofile=65536:65536` for production deployments. DcRouter will log a warning at startup if the file descriptor limit is below 65536.
1627
-
1628
- ### Environment Variables
1629
-
1630
- | Variable | Description | Default | Example |
1631
- |----------|-------------|---------|---------|
1632
- | `DCROUTER_MODE` | Container mode (set automatically in image) | `OCI_CONTAINER` | — |
1633
- | `DCROUTER_CONFIG_PATH` | Path to JSON config file (env vars override) | — | `/config/dcrouter.json` |
1634
- | `DCROUTER_BASE_DIR` | Base data directory | `~/.serve.zone/dcrouter` | `/data/dcrouter` |
1635
- | `DCROUTER_TLS_EMAIL` | ACME contact email | — | `admin@example.com` |
1636
- | `DCROUTER_TLS_DOMAIN` | Primary TLS domain | — | `example.com` |
1637
- | `DCROUTER_PUBLIC_IP` | Public IP for DNS records | — | `203.0.113.1` |
1638
- | `DCROUTER_PROXY_IPS` | Comma-separated ingress proxy IPs | — | `198.51.100.1,198.51.100.2` |
1639
- | `DCROUTER_DNS_NS_DOMAINS` | Comma-separated nameserver domains | — | `ns1.example.com,ns2.example.com` |
1640
- | `DCROUTER_DNS_SCOPES` | Comma-separated authoritative domains | — | `example.com,other.com` |
1641
- | `DCROUTER_EMAIL_HOSTNAME` | SMTP server hostname | — | `mail.example.com` |
1642
- | `DCROUTER_EMAIL_PORTS` | Comma-separated email ports | — | `25,587,465` |
1643
- | `DCROUTER_CACHE_ENABLED` | Enable/disable cache database | `true` | `false` |
1644
- | `DCROUTER_HEAP_SIZE` | Node.js V8 heap size in MB | `512` | `1024` |
1645
- | `DCROUTER_MAX_CONNECTIONS` | Global max concurrent connections | `50000` | `100000` |
1646
- | `DCROUTER_MAX_CONNECTIONS_PER_IP` | Max connections per source IP | `100` | `200` |
1647
- | `DCROUTER_CONNECTION_RATE_LIMIT` | Max new connections/min per IP | `600` | `1200` |
1648
-
1649
- ### Exposed Ports
1650
-
1651
- The container exposes all service ports:
1652
-
1653
- | Port(s) | Protocol | Service |
1654
- |---------|----------|---------|
1655
- | 80, 443 | TCP | HTTP/HTTPS (SmartProxy) |
1656
- | 25, 587, 465 | TCP | SMTP, Submission, SMTPS |
1657
- | 53 | TCP/UDP | DNS |
1658
- | 1812, 1813 | UDP | RADIUS auth/acct |
1659
- | 3000 | TCP | OpsServer dashboard |
1660
- | 8443 | TCP | Remote ingress tunnels |
1661
- | 51820 | UDP | WireGuard VPN |
1662
- | 29000–30000 | TCP | Dynamic port range |
1663
-
1664
- ### Building the Image
1665
-
1666
- ```bash
1667
- pnpm run build:docker # Build the container image
1668
- pnpm run release:docker # Push to registry
1669
- ```
313
+ ## Notes for Operators
1670
314
 
1671
- The Docker build supports multi-platform (`linux/amd64`, `linux/arm64`) via [tsdocker](https://code.foss.global/git.zone/tsdocker).
315
+ - Database-backed management features depend on `dbConfig.enabled !== false`.
316
+ - If you disable the DB, constructor-configured services still run, but persistent management features are limited.
317
+ - Nameserver domains are still required for DNS bootstrap and DoH route generation.
318
+ - HTTP/3 is enabled by default for qualifying HTTPS routes unless disabled globally or per route.
1672
319
 
1673
320
  ## License and Legal Information
1674
321