@serve.zone/dcrouter 13.19.1 → 13.20.2
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.
- package/dist_serve/bundle.js +700 -690
- package/dist_ts/00_commitinfo_data.js +1 -1
- package/dist_ts/classes.dcrouter.d.ts +5 -0
- package/dist_ts/classes.dcrouter.js +34 -10
- package/dist_ts/config/classes.route-config-manager.d.ts +1 -0
- package/dist_ts/config/classes.route-config-manager.js +12 -2
- package/dist_ts/vpn/classes.vpn-manager.d.ts +5 -1
- package/dist_ts/vpn/classes.vpn-manager.js +55 -17
- package/dist_ts_web/00_commitinfo_data.js +1 -1
- package/dist_ts_web/elements/network/ops-view-routes.js +70 -10
- package/dist_ts_web/elements/network/ops-view-vpn.d.ts +3 -0
- package/dist_ts_web/elements/network/ops-view-vpn.js +44 -16
- package/package.json +1 -1
- package/readme.md +123 -155
- package/ts/00_commitinfo_data.ts +1 -1
- package/ts/classes.dcrouter.ts +51 -14
- package/ts/config/classes.route-config-manager.ts +16 -1
- package/ts/readme.md +46 -103
- package/ts/vpn/classes.vpn-manager.ts +66 -15
- package/ts_apiclient/readme.md +57 -59
- package/ts_web/00_commitinfo_data.ts +1 -1
- package/ts_web/elements/network/ops-view-routes.ts +71 -8
- package/ts_web/elements/network/ops-view-vpn.ts +50 -14
- package/ts_web/readme.md +27 -47
package/readme.md
CHANGED
|
@@ -2,33 +2,31 @@
|
|
|
2
2
|
|
|
3
3
|

|
|
4
4
|
|
|
5
|
-
`dcrouter` is a TypeScript control plane for running a serious multi-protocol edge or datacenter gateway from one process. It
|
|
5
|
+
`dcrouter` is a TypeScript control plane for running a serious multi-protocol edge or datacenter gateway from one process. It wires together SmartProxy for HTTP/HTTPS/TCP routing, smartmta for email, smartdns for authoritative DNS and DNS-over-HTTPS, smartradius, smartvpn, remote ingress tunnels, a TypedRequest API, and the Ops dashboard.
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
Use it when you want one place to define routes, manage domains and certificates, protect internal services, automate changes over an API, and operate the whole stack from a browser.
|
|
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
|
-
## Why
|
|
13
|
+
## Why It Works
|
|
14
14
|
|
|
15
|
-
- 🌐
|
|
16
|
-
-
|
|
17
|
-
-
|
|
18
|
-
-
|
|
19
|
-
- ⚡
|
|
15
|
+
- 🌐 One runtime for HTTP/HTTPS/TCP, SMTP, authoritative DNS + DoH, RADIUS, VPN, and remote ingress.
|
|
16
|
+
- 🧠 Constructor config becomes system-managed routes, while API-created routes stay editable and clearly separated.
|
|
17
|
+
- 🔐 Certificates, DNS providers, domains, records, API tokens, access profiles, and protected routes live in one management plane.
|
|
18
|
+
- 🖥️ The OpsServer UI and TypedRequest API are first-class parts of the package, not an afterthought.
|
|
19
|
+
- ⚡ Qualifying HTTPS forward routes on port `443` get HTTP/3 augmentation by default unless you opt out.
|
|
20
20
|
|
|
21
|
-
## What
|
|
21
|
+
## What You Get
|
|
22
22
|
|
|
23
23
|
| Area | What dcrouter does |
|
|
24
24
|
| --- | --- |
|
|
25
|
-
| HTTP / HTTPS / TCP | SmartProxy-based
|
|
26
|
-
| Email |
|
|
27
|
-
| DNS | Authoritative
|
|
28
|
-
|
|
|
29
|
-
|
|
|
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 |
|
|
25
|
+
| HTTP / HTTPS / TCP | SmartProxy-based reverse proxying, TLS termination or passthrough, path/domain/port matching, TCP/SNI forwarding |
|
|
26
|
+
| Email | SMTP ingress and delivery via `UnifiedEmailServer`, route-based mail actions, email-domain management, queue and resend operations |
|
|
27
|
+
| DNS | Authoritative zones, nameserver bootstrap records, DNS-over-HTTPS routes on `/dns-query` and `/resolve`, provider-backed domain management |
|
|
28
|
+
| Access and Edge | VPN-gated routes, RADIUS auth/accounting, remote ingress edge registrations and tunnel hub support |
|
|
29
|
+
| Operations | Browser dashboard, TypedRequest API, route management, tokens, certificates, logs, metrics, and health views |
|
|
32
30
|
|
|
33
31
|
## Installation
|
|
34
32
|
|
|
@@ -38,7 +36,7 @@ pnpm add @serve.zone/dcrouter
|
|
|
38
36
|
|
|
39
37
|
## Quick Start
|
|
40
38
|
|
|
41
|
-
This
|
|
39
|
+
This example stays on unprivileged ports so you can run it locally without root.
|
|
42
40
|
|
|
43
41
|
```typescript
|
|
44
42
|
import { DcRouter } from '@serve.zone/dcrouter';
|
|
@@ -47,10 +45,10 @@ const router = new DcRouter({
|
|
|
47
45
|
smartProxyConfig: {
|
|
48
46
|
routes: [
|
|
49
47
|
{
|
|
50
|
-
name: 'app',
|
|
48
|
+
name: 'local-app',
|
|
51
49
|
match: {
|
|
52
|
-
domains: ['
|
|
53
|
-
ports: [
|
|
50
|
+
domains: ['localhost'],
|
|
51
|
+
ports: [18080],
|
|
54
52
|
},
|
|
55
53
|
action: {
|
|
56
54
|
type: 'forward',
|
|
@@ -68,114 +66,61 @@ const router = new DcRouter({
|
|
|
68
66
|
await router.start();
|
|
69
67
|
```
|
|
70
68
|
|
|
71
|
-
|
|
72
|
-
|
|
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
|
|
77
|
-
|
|
78
|
-
## Mental Model
|
|
69
|
+
After startup:
|
|
79
70
|
|
|
80
|
-
|
|
71
|
+
- open the dashboard at `http://localhost:3000`
|
|
72
|
+
- log in with the current built-in credentials `admin` / `admin`
|
|
73
|
+
- send proxied traffic to `http://localhost:18080`
|
|
74
|
+
- stop gracefully with `await router.stop()`
|
|
81
75
|
|
|
82
|
-
|
|
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 |
|
|
93
|
-
|
|
94
|
-
## Route Model
|
|
76
|
+
## Route Ownership Model
|
|
95
77
|
|
|
96
|
-
|
|
78
|
+
dcrouter keeps route ownership explicit so automation does not accidentally stomp on system-generated traffic.
|
|
97
79
|
|
|
98
|
-
| Route
|
|
99
|
-
| --- | --- | --- |
|
|
100
|
-
|
|
|
101
|
-
|
|
|
80
|
+
| Route origin | Where it comes from | What you can do |
|
|
81
|
+
| --- | --- | --- |
|
|
82
|
+
| `config` | Constructor `smartProxyConfig.routes` and related seed config | View and toggle |
|
|
83
|
+
| `email` | Email listener and mail-routing derived routes | View and toggle |
|
|
84
|
+
| `dns` | Generated DoH and DNS-related routes | View and toggle |
|
|
85
|
+
| `api` | Created through the Ops UI or API client | Full CRUD |
|
|
102
86
|
|
|
103
87
|
Important details:
|
|
104
88
|
|
|
105
|
-
- system routes are persisted with
|
|
106
|
-
-
|
|
107
|
-
-
|
|
108
|
-
- system routes are managed by the system, not edited directly by operators
|
|
109
|
-
|
|
110
|
-
## Core Features
|
|
111
|
-
|
|
112
|
-
### Traffic Routing
|
|
113
|
-
|
|
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
|
|
119
|
-
|
|
120
|
-
### Email
|
|
121
|
-
|
|
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
|
|
127
|
-
|
|
128
|
-
### DNS
|
|
89
|
+
- system routes are persisted with stable `systemKey` values
|
|
90
|
+
- DNS-over-HTTPS routes are persisted and then hydrated with live socket handlers at runtime
|
|
91
|
+
- editing and deletion are reserved for `api` routes; system routes are toggle-only by design
|
|
129
92
|
|
|
130
|
-
|
|
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
|
|
93
|
+
## Configuration Cheat Sheet
|
|
135
94
|
|
|
136
|
-
|
|
137
|
-
|
|
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
|
|
143
|
-
|
|
144
|
-
### VPN, RADIUS, and Remote Ingress
|
|
145
|
-
|
|
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
|
|
150
|
-
|
|
151
|
-
### Operations Plane
|
|
152
|
-
|
|
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
|
|
157
|
-
|
|
158
|
-
## Configuration Overview
|
|
159
|
-
|
|
160
|
-
The main entry point is `IDcRouterOptions`.
|
|
95
|
+
The main entrypoint is `IDcRouterOptions`.
|
|
161
96
|
|
|
162
97
|
| Option | Purpose |
|
|
163
98
|
| --- | --- |
|
|
164
|
-
| `smartProxyConfig` | Main HTTP/HTTPS and TCP/SNI routing
|
|
165
|
-
| `emailConfig` |
|
|
166
|
-
| `emailPortConfig` | External-to-internal email port
|
|
167
|
-
| `
|
|
168
|
-
| `
|
|
169
|
-
| `
|
|
170
|
-
| `
|
|
171
|
-
| `
|
|
172
|
-
| `
|
|
173
|
-
| `
|
|
174
|
-
| `
|
|
175
|
-
| `
|
|
176
|
-
| `
|
|
177
|
-
|
|
178
|
-
|
|
99
|
+
| `smartProxyConfig` | Main HTTP/HTTPS and TCP/SNI routing config |
|
|
100
|
+
| `emailConfig` | Email hostname, ports, domains, and mail routing rules |
|
|
101
|
+
| `emailPortConfig` | External-to-internal email port remapping and received-email storage path |
|
|
102
|
+
| `tls` | ACME contact and static certificate paths |
|
|
103
|
+
| `dnsNsDomains` | Nameserver hostnames used for NS bootstrap and DoH route generation |
|
|
104
|
+
| `dnsScopes` | Domains served authoritatively by the embedded DNS server |
|
|
105
|
+
| `dnsRecords` | Static constructor-defined DNS records |
|
|
106
|
+
| `publicIp` / `proxyIps` | How A records are exposed for nameserver and service records |
|
|
107
|
+
| `dbConfig` | Embedded LocalSmartDb or external MongoDB-backed persistence |
|
|
108
|
+
| `radiusConfig` | RADIUS auth, VLAN assignment, and accounting |
|
|
109
|
+
| `remoteIngressConfig` | Remote ingress hub and edge tunnel setup |
|
|
110
|
+
| `vpnConfig` | VPN server and client definitions for protected route access |
|
|
111
|
+
| `http3` | Global HTTP/3 behavior for qualifying HTTPS routes |
|
|
112
|
+
| `opsServerPort` | Ops dashboard and TypedRequest API port |
|
|
113
|
+
|
|
114
|
+
## Important Behavior
|
|
115
|
+
|
|
116
|
+
- `dbConfig.enabled` defaults to `true`. If you do not provide `mongoDbUrl`, dcrouter starts an embedded local database automatically.
|
|
117
|
+
- If you disable the DB, constructor-driven traffic can still run, but DB-backed features such as persistent routes, tokens, ACME config, and managed domains do not start.
|
|
118
|
+
- Qualifying HTTPS forward routes on port `443` get HTTP/3 by default unless `http3.enabled === false` or the route opts out.
|
|
119
|
+
- DNS-over-HTTPS endpoints are generated on the first entry of `dnsNsDomains` at `/dns-query` and `/resolve`.
|
|
120
|
+
- Email listener ports are internally remapped by default, so common external ports such as `25`, `587`, and `465` end up on internal ports like `10025`, `10587`, and `10465`.
|
|
121
|
+
- Provider-backed domains can be managed in the Ops plane without being served by the embedded authoritative DNS server.
|
|
122
|
+
|
|
123
|
+
## Bigger Example
|
|
179
124
|
|
|
180
125
|
```typescript
|
|
181
126
|
import { DcRouter } from '@serve.zone/dcrouter';
|
|
@@ -195,6 +140,19 @@ const router = new DcRouter({
|
|
|
195
140
|
tls: { mode: 'terminate', certificate: 'auto' },
|
|
196
141
|
},
|
|
197
142
|
},
|
|
143
|
+
{
|
|
144
|
+
name: 'internal-admin',
|
|
145
|
+
match: {
|
|
146
|
+
domains: ['internal.example.com'],
|
|
147
|
+
ports: [443],
|
|
148
|
+
},
|
|
149
|
+
action: {
|
|
150
|
+
type: 'forward',
|
|
151
|
+
targets: [{ host: '127.0.0.1', port: 9090 }],
|
|
152
|
+
tls: { mode: 'terminate', certificate: 'auto' },
|
|
153
|
+
},
|
|
154
|
+
vpnOnly: true,
|
|
155
|
+
},
|
|
198
156
|
],
|
|
199
157
|
},
|
|
200
158
|
emailConfig: {
|
|
@@ -233,93 +191,103 @@ const router = new DcRouter({
|
|
|
233
191
|
dbConfig: {
|
|
234
192
|
enabled: true,
|
|
235
193
|
},
|
|
194
|
+
opsServerPort: 3000,
|
|
236
195
|
});
|
|
237
196
|
|
|
238
197
|
await router.start();
|
|
239
198
|
```
|
|
240
199
|
|
|
241
|
-
##
|
|
200
|
+
## Automation
|
|
242
201
|
|
|
243
|
-
|
|
202
|
+
dcrouter gives you three good integration layers:
|
|
244
203
|
|
|
245
|
-
-
|
|
246
|
-
-
|
|
247
|
-
-
|
|
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
|
|
204
|
+
- the browser dashboard served by `OpsServer`
|
|
205
|
+
- raw TypedRequest contracts via `@serve.zone/dcrouter/interfaces`
|
|
206
|
+
- a higher-level OO API client via `@serve.zone/dcrouter/apiclient` or `@serve.zone/dcrouter-apiclient`
|
|
252
207
|
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
## Programmatic API Client
|
|
256
|
-
|
|
257
|
-
Use the API client when you want automation or integration code instead of clicking through the dashboard.
|
|
208
|
+
### OO API Client Example
|
|
258
209
|
|
|
259
210
|
```bash
|
|
260
211
|
pnpm add @serve.zone/dcrouter-apiclient
|
|
261
212
|
```
|
|
262
213
|
|
|
263
214
|
```typescript
|
|
264
|
-
import { DcRouterApiClient } from '@serve.zone/dcrouter
|
|
215
|
+
import { DcRouterApiClient } from '@serve.zone/dcrouter-apiclient';
|
|
265
216
|
|
|
266
217
|
const client = new DcRouterApiClient({
|
|
267
218
|
baseUrl: 'https://dcrouter.example.com',
|
|
268
219
|
});
|
|
269
220
|
|
|
270
|
-
await client.login('admin', '
|
|
221
|
+
await client.login('admin', 'admin');
|
|
271
222
|
|
|
272
223
|
const { routes } = await client.routes.list();
|
|
273
|
-
const systemRoutes = routes.filter((route) => route.origin !== 'api');
|
|
274
|
-
|
|
275
|
-
if (systemRoutes[0]) {
|
|
276
|
-
await systemRoutes[0].toggle(false);
|
|
277
|
-
}
|
|
278
224
|
|
|
279
225
|
await client.routes.build()
|
|
280
226
|
.setName('api-gateway')
|
|
281
227
|
.setMatch({ ports: 443, domains: ['api.example.com'] })
|
|
282
228
|
.setAction({ type: 'forward', targets: [{ host: '127.0.0.1', port: 8081 }] })
|
|
283
229
|
.save();
|
|
230
|
+
|
|
231
|
+
if (routes[0] && routes[0].origin !== 'api') {
|
|
232
|
+
await routes[0].toggle(false);
|
|
233
|
+
}
|
|
284
234
|
```
|
|
285
235
|
|
|
286
|
-
See `./ts_apiclient/readme.md` for the dedicated
|
|
236
|
+
See `./ts_apiclient/readme.md` for the dedicated client package and `./ts_interfaces/readme.md` for the raw contracts.
|
|
237
|
+
|
|
238
|
+
## OCI / Container Bootstrap
|
|
239
|
+
|
|
240
|
+
The package also includes an environment-driven bootstrap used by `runCli()` when `DCROUTER_MODE=OCI_CONTAINER`.
|
|
241
|
+
|
|
242
|
+
```typescript
|
|
243
|
+
import { runCli } from '@serve.zone/dcrouter';
|
|
244
|
+
|
|
245
|
+
await runCli();
|
|
246
|
+
```
|
|
247
|
+
|
|
248
|
+
Useful environment variables include:
|
|
249
|
+
|
|
250
|
+
- `DCROUTER_CONFIG_PATH`
|
|
251
|
+
- `DCROUTER_BASE_DIR`
|
|
252
|
+
- `DCROUTER_TLS_EMAIL`
|
|
253
|
+
- `DCROUTER_TLS_DOMAIN`
|
|
254
|
+
- `DCROUTER_PUBLIC_IP`
|
|
255
|
+
- `DCROUTER_PROXY_IPS`
|
|
256
|
+
- `DCROUTER_DNS_NS_DOMAINS`
|
|
257
|
+
- `DCROUTER_DNS_SCOPES`
|
|
258
|
+
- `DCROUTER_EMAIL_HOSTNAME`
|
|
259
|
+
- `DCROUTER_EMAIL_PORTS`
|
|
287
260
|
|
|
288
261
|
## Published Modules
|
|
289
262
|
|
|
290
|
-
This repository
|
|
263
|
+
This repository ships several module boundaries from one codebase.
|
|
291
264
|
|
|
292
265
|
| Module | Purpose | Docs |
|
|
293
266
|
| --- | --- | --- |
|
|
294
|
-
| `@serve.zone/dcrouter` | Main
|
|
295
|
-
| `@serve.zone/dcrouter
|
|
296
|
-
| `@serve.zone/dcrouter
|
|
297
|
-
| `@serve.zone/dcrouter-
|
|
298
|
-
| `@serve.zone/dcrouter-apiclient` |
|
|
267
|
+
| `@serve.zone/dcrouter` | Main runtime and orchestrator | `./readme.md` |
|
|
268
|
+
| `@serve.zone/dcrouter/interfaces` | Shared request and data contracts as a subpath export | `./ts_interfaces/readme.md` |
|
|
269
|
+
| `@serve.zone/dcrouter/apiclient` | OO API client as a subpath export | `./ts_apiclient/readme.md` |
|
|
270
|
+
| `@serve.zone/dcrouter-interfaces` | Standalone interfaces package | `./ts_interfaces/readme.md` |
|
|
271
|
+
| `@serve.zone/dcrouter-apiclient` | Standalone OO API client package | `./ts_apiclient/readme.md` |
|
|
272
|
+
| `@serve.zone/dcrouter-migrations` | Standalone migration runner package | `./ts_migrations/readme.md` |
|
|
273
|
+
| `@serve.zone/dcrouter-web` | Standalone web dashboard package boundary | `./ts_web/readme.md` |
|
|
299
274
|
|
|
300
|
-
## Development
|
|
275
|
+
## Development
|
|
301
276
|
|
|
302
277
|
```bash
|
|
303
278
|
pnpm run build
|
|
304
279
|
pnpm test
|
|
305
280
|
```
|
|
306
281
|
|
|
307
|
-
Target a single test
|
|
282
|
+
Target a single test while working on one area:
|
|
308
283
|
|
|
309
284
|
```bash
|
|
310
|
-
tstest test/test.
|
|
285
|
+
tstest test/test.apiclient.ts --verbose
|
|
311
286
|
```
|
|
312
287
|
|
|
313
|
-
## Notes for Operators
|
|
314
|
-
|
|
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.
|
|
319
|
-
|
|
320
288
|
## License and Legal Information
|
|
321
289
|
|
|
322
|
-
This repository contains open-source code licensed under the MIT License. A copy of the license can be found in the [
|
|
290
|
+
This repository contains open-source code licensed under the MIT License. A copy of the license can be found in the [LICENSE](./license) file.
|
|
323
291
|
|
|
324
292
|
**Please note:** The MIT License does not grant permission to use the trade names, trademarks, service marks, or product names of the project, except as required for reasonable and customary use in describing the origin of the work and reproducing the content of the NOTICE file.
|
|
325
293
|
|
package/ts/00_commitinfo_data.ts
CHANGED
package/ts/classes.dcrouter.ts
CHANGED
|
@@ -26,6 +26,7 @@ import { RadiusServer, type IRadiusServerConfig } from './radius/index.js';
|
|
|
26
26
|
import { RemoteIngressManager, TunnelManager } from './remoteingress/index.js';
|
|
27
27
|
import { VpnManager, type IVpnManagerConfig } from './vpn/index.js';
|
|
28
28
|
import { RouteConfigManager, ApiTokenManager, ReferenceResolver, DbSeeder, TargetProfileManager } from './config/index.js';
|
|
29
|
+
import type { TIpAllowEntry } from './config/classes.route-config-manager.js';
|
|
29
30
|
import { SecurityLogger, ContentScanner, IPReputationChecker } from './security/index.js';
|
|
30
31
|
import { type IHttp3Config, augmentRoutesWithHttp3 } from './http3/index.js';
|
|
31
32
|
import { DnsManager } from './dns/manager.dns.js';
|
|
@@ -565,20 +566,7 @@ export class DcRouter {
|
|
|
565
566
|
this.routeConfigManager = new RouteConfigManager(
|
|
566
567
|
() => this.smartProxy,
|
|
567
568
|
() => this.options.http3,
|
|
568
|
-
this.
|
|
569
|
-
? (route: import('../ts_interfaces/data/remoteingress.js').IDcRouterRouteConfig, routeId?: string) => {
|
|
570
|
-
if (!this.vpnManager || !this.targetProfileManager) {
|
|
571
|
-
// VPN not ready yet — deny all until re-apply after VPN starts
|
|
572
|
-
return [];
|
|
573
|
-
}
|
|
574
|
-
return this.targetProfileManager.getMatchingClientIps(
|
|
575
|
-
route,
|
|
576
|
-
routeId,
|
|
577
|
-
this.vpnManager.listClients(),
|
|
578
|
-
this.routeConfigManager?.getRoutes() || new Map(),
|
|
579
|
-
);
|
|
580
|
-
}
|
|
581
|
-
: undefined,
|
|
569
|
+
this.createVpnRouteAllowListResolver(),
|
|
582
570
|
this.referenceResolver,
|
|
583
571
|
// Sync routes to RemoteIngressManager whenever routes change,
|
|
584
572
|
// then push updated derived ports to the Rust hub binary
|
|
@@ -2292,6 +2280,32 @@ export class DcRouter {
|
|
|
2292
2280
|
/**
|
|
2293
2281
|
* Set up VPN server for VPN-based route access control.
|
|
2294
2282
|
*/
|
|
2283
|
+
private createVpnRouteAllowListResolver(): ((
|
|
2284
|
+
route: import('../ts_interfaces/data/remoteingress.js').IDcRouterRouteConfig,
|
|
2285
|
+
routeId?: string,
|
|
2286
|
+
) => TIpAllowEntry[]) | undefined {
|
|
2287
|
+
if (!this.options.vpnConfig?.enabled) {
|
|
2288
|
+
return undefined;
|
|
2289
|
+
}
|
|
2290
|
+
|
|
2291
|
+
return (
|
|
2292
|
+
route: import('../ts_interfaces/data/remoteingress.js').IDcRouterRouteConfig,
|
|
2293
|
+
routeId?: string,
|
|
2294
|
+
) => {
|
|
2295
|
+
if (!this.vpnManager || !this.targetProfileManager) {
|
|
2296
|
+
// VPN not ready yet — deny all until re-apply after VPN starts.
|
|
2297
|
+
return [];
|
|
2298
|
+
}
|
|
2299
|
+
|
|
2300
|
+
return this.targetProfileManager.getMatchingClientIps(
|
|
2301
|
+
route,
|
|
2302
|
+
routeId,
|
|
2303
|
+
this.vpnManager.listClients(),
|
|
2304
|
+
this.routeConfigManager?.getRoutes() || new Map(),
|
|
2305
|
+
);
|
|
2306
|
+
};
|
|
2307
|
+
}
|
|
2308
|
+
|
|
2295
2309
|
private async setupVpnServer(): Promise<void> {
|
|
2296
2310
|
if (!this.options.vpnConfig?.enabled) {
|
|
2297
2311
|
return;
|
|
@@ -2441,6 +2455,29 @@ export class DcRouter {
|
|
|
2441
2455
|
|
|
2442
2456
|
logger.log('info', 'RADIUS configuration updated');
|
|
2443
2457
|
}
|
|
2458
|
+
|
|
2459
|
+
/**
|
|
2460
|
+
* Update VPN configuration at runtime.
|
|
2461
|
+
*/
|
|
2462
|
+
public async updateVpnConfig(config: IDcRouterOptions['vpnConfig']): Promise<void> {
|
|
2463
|
+
if (this.vpnManager) {
|
|
2464
|
+
await this.vpnManager.stop();
|
|
2465
|
+
this.vpnManager = undefined;
|
|
2466
|
+
}
|
|
2467
|
+
|
|
2468
|
+
this.options.vpnConfig = config;
|
|
2469
|
+
this.vpnDomainIpCache.clear();
|
|
2470
|
+
this.warnedWildcardVpnDomains.clear();
|
|
2471
|
+
this.routeConfigManager?.setVpnClientIpsResolver(this.createVpnRouteAllowListResolver());
|
|
2472
|
+
|
|
2473
|
+
if (this.options.vpnConfig?.enabled) {
|
|
2474
|
+
await this.setupVpnServer();
|
|
2475
|
+
} else {
|
|
2476
|
+
await this.routeConfigManager?.applyRoutes();
|
|
2477
|
+
}
|
|
2478
|
+
|
|
2479
|
+
logger.log('info', 'VPN configuration updated');
|
|
2480
|
+
}
|
|
2444
2481
|
}
|
|
2445
2482
|
|
|
2446
2483
|
// Re-export email server types for convenience
|
|
@@ -73,6 +73,12 @@ export class RouteConfigManager {
|
|
|
73
73
|
return this.routes.get(id);
|
|
74
74
|
}
|
|
75
75
|
|
|
76
|
+
public setVpnClientIpsResolver(
|
|
77
|
+
resolver?: (route: IDcRouterRouteConfig, routeId?: string) => TIpAllowEntry[],
|
|
78
|
+
): void {
|
|
79
|
+
this.getVpnClientIpsForRoute = resolver;
|
|
80
|
+
}
|
|
81
|
+
|
|
76
82
|
/**
|
|
77
83
|
* Load persisted routes, seed serializable config/email/dns routes,
|
|
78
84
|
* compute warnings, and apply the combined DB-backed + runtime route set to SmartProxy.
|
|
@@ -192,7 +198,16 @@ export class RouteConfigManager {
|
|
|
192
198
|
}
|
|
193
199
|
}
|
|
194
200
|
}
|
|
195
|
-
|
|
201
|
+
const mergedRoute = { ...stored.route, ...patch.route, action: mergedAction } as IDcRouterRouteConfig;
|
|
202
|
+
|
|
203
|
+
// Handle explicit null to remove optional top-level route properties (e.g., remoteIngress: null)
|
|
204
|
+
for (const [key, val] of Object.entries(patch.route)) {
|
|
205
|
+
if (val === null && key !== 'action' && key !== 'match') {
|
|
206
|
+
delete (mergedRoute as any)[key];
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
stored.route = mergedRoute;
|
|
196
211
|
}
|
|
197
212
|
if (patch.enabled !== undefined) {
|
|
198
213
|
stored.enabled = patch.enabled;
|