Compare commits
24 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 0804544564 | |||
| 671e72452a | |||
| 647c705b81 | |||
| 40c3202082 | |||
| 3b91ed3d5a | |||
| 133b17f136 | |||
| efa45dfdc9 | |||
| 79b4ea6bd9 | |||
| b483412a2e | |||
| d964515ff9 | |||
| e2c453423e | |||
| c44b7d513a | |||
| 2487f77b8a | |||
| ea80ef005c | |||
| dd45b7fbe7 | |||
| ca73da7b9b | |||
| f6e1951aa2 | |||
| 76fd563e21 | |||
| ee831ea057 | |||
| a65c2ec096 | |||
| 65822278d5 | |||
| aa3955fc67 | |||
| d4605062bb | |||
| cd3f08d55f |
66
changelog.md
66
changelog.md
@@ -1,5 +1,71 @@
|
|||||||
# Changelog
|
# Changelog
|
||||||
|
|
||||||
|
## 2026-03-20 - 11.8.9 - fix(deps)
|
||||||
|
bump @push.rocks/smartproxy to ^25.17.8
|
||||||
|
|
||||||
|
- Updates the @push.rocks/smartproxy dependency from ^25.17.7 to ^25.17.8.
|
||||||
|
|
||||||
|
## 2026-03-20 - 11.8.8 - fix(deps)
|
||||||
|
bump @push.rocks/smartproxy to ^25.17.7
|
||||||
|
|
||||||
|
- Updates the @push.rocks/smartproxy dependency from ^25.17.4 to ^25.17.7 in package.json.
|
||||||
|
|
||||||
|
## 2026-03-20 - 11.8.7 - fix(deps)
|
||||||
|
bump @push.rocks/smartproxy to ^25.17.4
|
||||||
|
|
||||||
|
- updates @push.rocks/smartproxy from ^25.17.3 to ^25.17.4 in package.json
|
||||||
|
|
||||||
|
## 2026-03-20 - 11.8.6 - fix(deps)
|
||||||
|
bump @push.rocks/smartproxy to ^25.17.3
|
||||||
|
|
||||||
|
- updates @push.rocks/smartproxy from ^25.17.1 to ^25.17.3 in package.json
|
||||||
|
|
||||||
|
## 2026-03-20 - 11.8.5 - fix(deps)
|
||||||
|
bump @push.rocks/smartproxy to ^25.17.1
|
||||||
|
|
||||||
|
- Updates the @push.rocks/smartproxy dependency from ^25.17.0 to ^25.17.1.
|
||||||
|
|
||||||
|
## 2026-03-20 - 11.8.4 - fix(deps)
|
||||||
|
bump @serve.zone/remoteingress to ^4.14.0
|
||||||
|
|
||||||
|
- Updates the @serve.zone/remoteingress dependency from ^4.13.2 to ^4.14.0 in package.json.
|
||||||
|
|
||||||
|
## 2026-03-20 - 11.8.3 - fix(deps)
|
||||||
|
bump @serve.zone/remoteingress to ^4.13.2
|
||||||
|
|
||||||
|
- Updates the @serve.zone/remoteingress dependency from ^4.13.1 to ^4.13.2.
|
||||||
|
|
||||||
|
## 2026-03-19 - 11.8.2 - fix(deps)
|
||||||
|
bump smartproxy and remoteingress dependencies
|
||||||
|
|
||||||
|
- updates @push.rocks/smartproxy from ^25.16.3 to ^25.17.0
|
||||||
|
- updates @serve.zone/remoteingress from ^4.13.0 to ^4.13.1
|
||||||
|
|
||||||
|
## 2026-03-19 - 11.8.1 - fix(dcrouter)
|
||||||
|
use constructor routes for remote ingress setup and bump smartproxy dependency
|
||||||
|
|
||||||
|
- Switch remote ingress initialization to use constructorRoutes instead of smartProxyConfig routes so derived edge ports are based on the active route set.
|
||||||
|
- Update @push.rocks/smartproxy from ^25.16.2 to ^25.16.3.
|
||||||
|
|
||||||
|
## 2026-03-19 - 11.8.0 - feat(remoteingress)
|
||||||
|
add UDP listen port derivation and edge configuration support
|
||||||
|
|
||||||
|
- derive UDP ports from remote ingress routes using transport 'udp' or 'all'
|
||||||
|
- expose effective UDP listen ports in allowed edge payloads and remote ingress interfaces
|
||||||
|
- update @push.rocks/smartproxy to ^25.16.2
|
||||||
|
|
||||||
|
## 2026-03-19 - 11.7.1 - fix(deps)
|
||||||
|
bump @push.rocks/smartproxy to ^25.16.0
|
||||||
|
|
||||||
|
- updates the smartproxy dependency from ^25.15.0 to ^25.16.0
|
||||||
|
|
||||||
|
## 2026-03-19 - 11.7.0 - feat(readme)
|
||||||
|
document HTTP/3 QUIC support and configuration options
|
||||||
|
|
||||||
|
- Add a dedicated README section explaining default HTTP/3 route augmentation, qualification rules, and opt-out behavior.
|
||||||
|
- Document the new global `http3` configuration shape and re-exported `IHttp3Config` type.
|
||||||
|
- Update TypeScript module documentation to include the built-in HTTP/3 augmentation module and exports.
|
||||||
|
|
||||||
## 2026-03-19 - 11.6.0 - feat(http3)
|
## 2026-03-19 - 11.6.0 - feat(http3)
|
||||||
add automatic HTTP/3 route augmentation for qualifying HTTPS routes
|
add automatic HTTP/3 route augmentation for qualifying HTTPS routes
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"name": "@serve.zone/dcrouter",
|
"name": "@serve.zone/dcrouter",
|
||||||
"private": false,
|
"private": false,
|
||||||
"version": "11.6.0",
|
"version": "11.8.9",
|
||||||
"description": "A multifaceted routing service handling mail and SMS delivery functions.",
|
"description": "A multifaceted routing service handling mail and SMS delivery functions.",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"exports": {
|
"exports": {
|
||||||
@@ -53,7 +53,7 @@
|
|||||||
"@push.rocks/smartnetwork": "^4.4.0",
|
"@push.rocks/smartnetwork": "^4.4.0",
|
||||||
"@push.rocks/smartpath": "^6.0.0",
|
"@push.rocks/smartpath": "^6.0.0",
|
||||||
"@push.rocks/smartpromise": "^4.2.3",
|
"@push.rocks/smartpromise": "^4.2.3",
|
||||||
"@push.rocks/smartproxy": "^25.15.0",
|
"@push.rocks/smartproxy": "^25.17.8",
|
||||||
"@push.rocks/smartradius": "^1.1.1",
|
"@push.rocks/smartradius": "^1.1.1",
|
||||||
"@push.rocks/smartrequest": "^5.0.1",
|
"@push.rocks/smartrequest": "^5.0.1",
|
||||||
"@push.rocks/smartrx": "^3.0.10",
|
"@push.rocks/smartrx": "^3.0.10",
|
||||||
@@ -61,7 +61,7 @@
|
|||||||
"@push.rocks/smartunique": "^3.0.9",
|
"@push.rocks/smartunique": "^3.0.9",
|
||||||
"@serve.zone/catalog": "^2.9.0",
|
"@serve.zone/catalog": "^2.9.0",
|
||||||
"@serve.zone/interfaces": "^5.3.0",
|
"@serve.zone/interfaces": "^5.3.0",
|
||||||
"@serve.zone/remoteingress": "^4.13.0",
|
"@serve.zone/remoteingress": "^4.14.0",
|
||||||
"@tsclass/tsclass": "^9.4.0",
|
"@tsclass/tsclass": "^9.4.0",
|
||||||
"lru-cache": "^11.2.7",
|
"lru-cache": "^11.2.7",
|
||||||
"uuid": "^13.0.0"
|
"uuid": "^13.0.0"
|
||||||
|
|||||||
20
pnpm-lock.yaml
generated
20
pnpm-lock.yaml
generated
@@ -78,8 +78,8 @@ importers:
|
|||||||
specifier: ^4.2.3
|
specifier: ^4.2.3
|
||||||
version: 4.2.3
|
version: 4.2.3
|
||||||
'@push.rocks/smartproxy':
|
'@push.rocks/smartproxy':
|
||||||
specifier: ^25.15.0
|
specifier: ^25.17.8
|
||||||
version: 25.15.0
|
version: 25.17.8
|
||||||
'@push.rocks/smartradius':
|
'@push.rocks/smartradius':
|
||||||
specifier: ^1.1.1
|
specifier: ^1.1.1
|
||||||
version: 1.1.1
|
version: 1.1.1
|
||||||
@@ -102,8 +102,8 @@ importers:
|
|||||||
specifier: ^5.3.0
|
specifier: ^5.3.0
|
||||||
version: 5.3.0
|
version: 5.3.0
|
||||||
'@serve.zone/remoteingress':
|
'@serve.zone/remoteingress':
|
||||||
specifier: ^4.13.0
|
specifier: ^4.14.0
|
||||||
version: 4.13.0
|
version: 4.14.0
|
||||||
'@tsclass/tsclass':
|
'@tsclass/tsclass':
|
||||||
specifier: ^9.4.0
|
specifier: ^9.4.0
|
||||||
version: 9.5.0
|
version: 9.5.0
|
||||||
@@ -1256,8 +1256,8 @@ packages:
|
|||||||
'@push.rocks/smartpromise@4.2.3':
|
'@push.rocks/smartpromise@4.2.3':
|
||||||
resolution: {integrity: sha512-Ycg/TJR+tMt+S3wSFurOpEoW6nXv12QBtKXgBcjMZ4RsdO28geN46U09osPn9N9WuwQy1PkmTV5J/V4F9U8qEw==}
|
resolution: {integrity: sha512-Ycg/TJR+tMt+S3wSFurOpEoW6nXv12QBtKXgBcjMZ4RsdO28geN46U09osPn9N9WuwQy1PkmTV5J/V4F9U8qEw==}
|
||||||
|
|
||||||
'@push.rocks/smartproxy@25.15.0':
|
'@push.rocks/smartproxy@25.17.8':
|
||||||
resolution: {integrity: sha512-quw4MH6Snr6X2vy27iykXbBwN1oDKU7AntbUAPOgsWERTTDZGZU79fk9VZTvk5hGNemb2wEgnkgsUxAnj0y4dQ==}
|
resolution: {integrity: sha512-lcSCv6dV+0HayjhlyfmsfTm3X0XYvgQe+mP/rGi0uPH0aPQ028lCG3AYgTZXuEs8fmDypBX6hhl53tpGFeV1tg==}
|
||||||
|
|
||||||
'@push.rocks/smartpuppeteer@2.0.5':
|
'@push.rocks/smartpuppeteer@2.0.5':
|
||||||
resolution: {integrity: sha512-yK/qSeWVHIGWRp3c8S5tfdGP6WCKllZC4DR8d8CQlEjszOSBmHtlTdyyqOMBZ/BA4kd+eU5f3A1r4K2tGYty1g==}
|
resolution: {integrity: sha512-yK/qSeWVHIGWRp3c8S5tfdGP6WCKllZC4DR8d8CQlEjszOSBmHtlTdyyqOMBZ/BA4kd+eU5f3A1r4K2tGYty1g==}
|
||||||
@@ -1550,8 +1550,8 @@ packages:
|
|||||||
'@serve.zone/interfaces@5.3.0':
|
'@serve.zone/interfaces@5.3.0':
|
||||||
resolution: {integrity: sha512-venO7wtDR9ixzD9NhdERBGjNKbFA5LL0yHw4eqGh0UpmvtXVc3SFG0uuHDilOKMZqZ8bttV88qVsFy1aSTJrtA==}
|
resolution: {integrity: sha512-venO7wtDR9ixzD9NhdERBGjNKbFA5LL0yHw4eqGh0UpmvtXVc3SFG0uuHDilOKMZqZ8bttV88qVsFy1aSTJrtA==}
|
||||||
|
|
||||||
'@serve.zone/remoteingress@4.13.0':
|
'@serve.zone/remoteingress@4.14.0':
|
||||||
resolution: {integrity: sha512-Gw/yIgCukh3kImIco3u9B+b2cQP4l88RgCdP7NhYpwTDrI9jrsKmrzq0cRXo/Lnja35RZ1D7fBmNvaaAqEToVQ==}
|
resolution: {integrity: sha512-oDbKHhhvN2LxCcvmSgYhRLF+0FknEcPN+zg5kO4I0pfNpW/zgUYiaZns4TcYStZMS5/4i9j1uVR7QEO0a571/w==}
|
||||||
|
|
||||||
'@sindresorhus/is@5.6.0':
|
'@sindresorhus/is@5.6.0':
|
||||||
resolution: {integrity: sha512-TV7t8GKYaJWsn00tFDqBw8+Uqmr8A0fRU1tvTQhyZzGv0sJCGRQL3JGMI3ucuKo3XIZdUP+Lx7/gh2t3lewy7g==}
|
resolution: {integrity: sha512-TV7t8GKYaJWsn00tFDqBw8+Uqmr8A0fRU1tvTQhyZzGv0sJCGRQL3JGMI3ucuKo3XIZdUP+Lx7/gh2t3lewy7g==}
|
||||||
@@ -6539,7 +6539,7 @@ snapshots:
|
|||||||
|
|
||||||
'@push.rocks/smartpromise@4.2.3': {}
|
'@push.rocks/smartpromise@4.2.3': {}
|
||||||
|
|
||||||
'@push.rocks/smartproxy@25.15.0':
|
'@push.rocks/smartproxy@25.17.8':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@push.rocks/smartcrypto': 2.0.4
|
'@push.rocks/smartcrypto': 2.0.4
|
||||||
'@push.rocks/smartlog': 3.2.1
|
'@push.rocks/smartlog': 3.2.1
|
||||||
@@ -6956,7 +6956,7 @@ snapshots:
|
|||||||
'@push.rocks/smartlog-interfaces': 3.0.2
|
'@push.rocks/smartlog-interfaces': 3.0.2
|
||||||
'@tsclass/tsclass': 9.5.0
|
'@tsclass/tsclass': 9.5.0
|
||||||
|
|
||||||
'@serve.zone/remoteingress@4.13.0':
|
'@serve.zone/remoteingress@4.14.0':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@push.rocks/qenv': 6.1.3
|
'@push.rocks/qenv': 6.1.3
|
||||||
'@push.rocks/smartrust': 1.3.2
|
'@push.rocks/smartrust': 1.3.2
|
||||||
|
|||||||
125
readme.md
125
readme.md
@@ -18,6 +18,7 @@ For reporting bugs, issues, or security vulnerabilities, please visit [community
|
|||||||
- [Architecture](#architecture)
|
- [Architecture](#architecture)
|
||||||
- [Configuration Reference](#configuration-reference)
|
- [Configuration Reference](#configuration-reference)
|
||||||
- [HTTP/HTTPS & TCP/SNI Routing](#httphttps--tcpsni-routing)
|
- [HTTP/HTTPS & TCP/SNI Routing](#httphttps--tcpsni-routing)
|
||||||
|
- [HTTP/3 (QUIC) Support](#http3-quic-support)
|
||||||
- [Email System](#email-system)
|
- [Email System](#email-system)
|
||||||
- [DNS Server](#dns-server)
|
- [DNS Server](#dns-server)
|
||||||
- [RADIUS Server](#radius-server)
|
- [RADIUS Server](#radius-server)
|
||||||
@@ -37,6 +38,7 @@ For reporting bugs, issues, or security vulnerabilities, please visit [community
|
|||||||
|
|
||||||
### 🌐 Universal Traffic Router
|
### 🌐 Universal Traffic Router
|
||||||
- **HTTP/HTTPS routing** with domain matching, path-based forwarding, and automatic TLS
|
- **HTTP/HTTPS routing** with domain matching, path-based forwarding, and automatic TLS
|
||||||
|
- **HTTP/3 (QUIC) enabled by default** — qualifying HTTPS routes automatically get QUIC/H3 support with zero configuration
|
||||||
- **TCP/SNI proxy** for any protocol with TLS termination or passthrough
|
- **TCP/SNI proxy** for any protocol with TLS termination or passthrough
|
||||||
- **DNS server** (Rust-powered via [SmartDNS](https://code.foss.global/push.rocks/smartdns)) with authoritative zones, dynamic record management, and DNS-over-HTTPS
|
- **DNS server** (Rust-powered via [SmartDNS](https://code.foss.global/push.rocks/smartdns)) with authoritative zones, dynamic record management, and DNS-over-HTTPS
|
||||||
- **Multi-protocol support** on the same infrastructure via [SmartProxy](https://code.foss.global/push.rocks/smartproxy)
|
- **Multi-protocol support** on the same infrastructure via [SmartProxy](https://code.foss.global/push.rocks/smartproxy)
|
||||||
@@ -425,6 +427,27 @@ interface IDcRouterOptions {
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// ── HTTP/3 (QUIC) ────────────────────────────────────────────
|
||||||
|
/** HTTP/3 config — enabled by default on qualifying HTTPS routes */
|
||||||
|
http3?: {
|
||||||
|
enabled?: boolean; // default: true
|
||||||
|
quicSettings?: {
|
||||||
|
maxIdleTimeout?: number; // default: 30000ms
|
||||||
|
maxConcurrentBidiStreams?: number; // default: 100
|
||||||
|
maxConcurrentUniStreams?: number; // default: 100
|
||||||
|
initialCongestionWindow?: number;
|
||||||
|
};
|
||||||
|
altSvc?: {
|
||||||
|
port?: number; // default: listening port
|
||||||
|
maxAge?: number; // default: 86400s
|
||||||
|
};
|
||||||
|
udpSettings?: {
|
||||||
|
sessionTimeout?: number; // default: 60000ms
|
||||||
|
maxSessionsPerIP?: number; // default: 1000
|
||||||
|
maxDatagramSize?: number; // default: 65535
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
// ── OpsServer ────────────────────────────────────────────────
|
// ── OpsServer ────────────────────────────────────────────────
|
||||||
/** Port for the OpsServer web dashboard (default: 3000) */
|
/** Port for the OpsServer web dashboard (default: 3000) */
|
||||||
opsServerPort?: number;
|
opsServerPort?: number;
|
||||||
@@ -516,6 +539,102 @@ DcRouter uses [SmartProxy](https://code.foss.global/push.rocks/smartproxy) for a
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## HTTP/3 (QUIC) Support
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
||||||
|
### How It Works
|
||||||
|
|
||||||
|
When DcRouter assembles routes in `setupSmartProxy()`, it automatically augments qualifying routes with:
|
||||||
|
- `match.transport: 'all'` — listen on both TCP (HTTP/1.1 + HTTP/2) and UDP (QUIC/HTTP/3) on the same port
|
||||||
|
- `action.udp.quic` — QUIC configuration with `enableHttp3: true` and `altSvcMaxAge: 86400`
|
||||||
|
|
||||||
|
Browsers that support HTTP/3 will discover it via the `Alt-Svc` header on initial TCP responses, then upgrade to QUIC for subsequent requests.
|
||||||
|
|
||||||
|
### What Gets Augmented
|
||||||
|
|
||||||
|
A route qualifies for HTTP/3 augmentation when **all** of these are true:
|
||||||
|
- Port includes **443** (single number, array, or range)
|
||||||
|
- Action type is **`forward`** (not `socket-handler`)
|
||||||
|
- **TLS is enabled** (passthrough, terminate, or terminate-and-reencrypt)
|
||||||
|
- Route is **not** an email route (ports 25/587/465)
|
||||||
|
- Route doesn't already have `transport: 'all'` or existing `udp.quic` config
|
||||||
|
|
||||||
|
### Zero-Config (Default Behavior)
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
// HTTP/3 is ON by default — this route automatically gets QUIC/H3:
|
||||||
|
const router = new DcRouter({
|
||||||
|
smartProxyConfig: {
|
||||||
|
routes: [{
|
||||||
|
name: 'web-app',
|
||||||
|
match: { domains: ['example.com'], ports: [443] },
|
||||||
|
action: {
|
||||||
|
type: 'forward',
|
||||||
|
targets: [{ host: '192.168.1.10', port: 8080 }],
|
||||||
|
tls: { mode: 'terminate', certificate: 'auto' }
|
||||||
|
}
|
||||||
|
}]
|
||||||
|
}
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
### Per-Route Opt-Out
|
||||||
|
|
||||||
|
Disable HTTP/3 on a specific route using `action.options.http3`:
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
{
|
||||||
|
name: 'legacy-app',
|
||||||
|
match: { domains: ['legacy.example.com'], ports: [443] },
|
||||||
|
action: {
|
||||||
|
type: 'forward',
|
||||||
|
targets: [{ host: '192.168.1.50', port: 8080 }],
|
||||||
|
tls: { mode: 'terminate', certificate: 'auto' },
|
||||||
|
options: { http3: false } // ← This route stays TCP-only
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Global Opt-Out
|
||||||
|
|
||||||
|
Disable HTTP/3 across all routes:
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
const router = new DcRouter({
|
||||||
|
http3: { enabled: false },
|
||||||
|
smartProxyConfig: { routes: [/* ... */] }
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
### Custom QUIC Settings
|
||||||
|
|
||||||
|
Fine-tune QUIC parameters globally:
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
const router = new DcRouter({
|
||||||
|
http3: {
|
||||||
|
quicSettings: {
|
||||||
|
maxIdleTimeout: 60000, // 60s idle timeout
|
||||||
|
maxConcurrentBidiStreams: 200, // More parallel streams
|
||||||
|
maxConcurrentUniStreams: 50,
|
||||||
|
},
|
||||||
|
altSvc: {
|
||||||
|
maxAge: 3600, // 1 hour Alt-Svc cache
|
||||||
|
},
|
||||||
|
udpSettings: {
|
||||||
|
sessionTimeout: 120000, // 2 min UDP session timeout
|
||||||
|
maxSessionsPerIP: 500,
|
||||||
|
}
|
||||||
|
},
|
||||||
|
smartProxyConfig: { routes: [/* ... */] }
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
### Programmatic Routes
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
||||||
## Email System
|
## Email System
|
||||||
|
|
||||||
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.
|
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.
|
||||||
@@ -1221,7 +1340,7 @@ const router = new DcRouter(options: IDcRouterOptions);
|
|||||||
|
|
||||||
### Re-exported Types
|
### Re-exported Types
|
||||||
|
|
||||||
DcRouter re-exports key types from smartmta for convenience:
|
DcRouter re-exports key types for convenience:
|
||||||
|
|
||||||
```typescript
|
```typescript
|
||||||
import {
|
import {
|
||||||
@@ -1231,6 +1350,7 @@ import {
|
|||||||
type IUnifiedEmailServerOptions,
|
type IUnifiedEmailServerOptions,
|
||||||
type IEmailRoute,
|
type IEmailRoute,
|
||||||
type IEmailDomainConfig,
|
type IEmailDomainConfig,
|
||||||
|
type IHttp3Config,
|
||||||
} from '@serve.zone/dcrouter';
|
} from '@serve.zone/dcrouter';
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -1277,9 +1397,10 @@ tstest test/test.opsserver-api.ts --verbose --timeout 60
|
|||||||
| `test.dns-server-config.ts` | DNS record parsing, grouping, extraction | 5 |
|
| `test.dns-server-config.ts` | DNS record parsing, grouping, extraction | 5 |
|
||||||
| `test.dns-socket-handler.ts` | DNS socket handler and route generation | 6 |
|
| `test.dns-socket-handler.ts` | DNS socket handler and route generation | 6 |
|
||||||
| `test.errors.ts` | Error classes, handler, retry utilities | 5 |
|
| `test.errors.ts` | Error classes, handler, retry utilities | 5 |
|
||||||
|
| `test.http3-augmentation.ts` | HTTP/3 route augmentation, qualification, opt-in/out, QUIC settings | 20 |
|
||||||
| `test.ipreputationchecker.ts` | IP reputation, DNSBL, caching, risk classification | 10 |
|
| `test.ipreputationchecker.ts` | IP reputation, DNSBL, caching, risk classification | 10 |
|
||||||
| `test.jwt-auth.ts` | JWT login, verification, logout, invalid credentials | 8 |
|
| `test.jwt-auth.ts` | JWT login, verification, logout, invalid credentials | 8 |
|
||||||
| `test.opsserver-api.ts` | Health, statistics, configuration, log APIs | 6 |
|
| `test.opsserver-api.ts` | Health, statistics, configuration, log APIs | 8 |
|
||||||
| `test.protected-endpoint.ts` | Admin auth, identity verification, public endpoints | 8 |
|
| `test.protected-endpoint.ts` | Admin auth, identity verification, public endpoints | 8 |
|
||||||
| `test.storagemanager.ts` | Memory, filesystem, custom backends, concurrency | 8 |
|
| `test.storagemanager.ts` | Memory, filesystem, custom backends, concurrency | 8 |
|
||||||
|
|
||||||
|
|||||||
@@ -3,6 +3,6 @@
|
|||||||
*/
|
*/
|
||||||
export const commitinfo = {
|
export const commitinfo = {
|
||||||
name: '@serve.zone/dcrouter',
|
name: '@serve.zone/dcrouter',
|
||||||
version: '11.6.0',
|
version: '11.8.9',
|
||||||
description: 'A multifaceted routing service handling mail and SMS delivery functions.'
|
description: 'A multifaceted routing service handling mail and SMS delivery functions.'
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1753,7 +1753,7 @@ export class DcRouter {
|
|||||||
await this.remoteIngressManager.initialize();
|
await this.remoteIngressManager.initialize();
|
||||||
|
|
||||||
// Pass current routes so the manager can derive edge ports from remoteIngress-tagged routes
|
// Pass current routes so the manager can derive edge ports from remoteIngress-tagged routes
|
||||||
const currentRoutes = this.options.smartProxyConfig?.routes || [];
|
const currentRoutes = this.constructorRoutes;
|
||||||
this.remoteIngressManager.setRoutes(currentRoutes as any[]);
|
this.remoteIngressManager.setRoutes(currentRoutes as any[]);
|
||||||
|
|
||||||
// Resolve TLS certs for tunnel: explicit paths > ACME for hubDomain > self-signed (Rust default)
|
// Resolve TLS certs for tunnel: explicit paths > ACME for hubDomain > self-signed (Rust default)
|
||||||
|
|||||||
@@ -60,6 +60,9 @@ ts/
|
|||||||
│ └── documents/ # Cached document models
|
│ └── documents/ # Cached document models
|
||||||
├── config/ # Configuration utilities
|
├── config/ # Configuration utilities
|
||||||
├── errors/ # Error classes and retry logic
|
├── errors/ # Error classes and retry logic
|
||||||
|
├── http3/ # HTTP/3 (QUIC) route augmentation
|
||||||
|
│ ├── index.ts # Barrel export
|
||||||
|
│ └── http3-route-augmentation.ts # Pure utility: augmentRoutesWithHttp3(), IHttp3Config
|
||||||
├── monitoring/ # MetricsManager (SmartMetrics integration)
|
├── monitoring/ # MetricsManager (SmartMetrics integration)
|
||||||
├── opsserver/ # OpsServer dashboard + API handlers
|
├── opsserver/ # OpsServer dashboard + API handlers
|
||||||
│ ├── classes.opsserver.ts # HTTP server + TypedRouter setup
|
│ ├── classes.opsserver.ts # HTTP server + TypedRouter setup
|
||||||
@@ -99,6 +102,9 @@ export { RadiusServer, IRadiusServerConfig } from './radius/index.js';
|
|||||||
|
|
||||||
// Remote Ingress
|
// Remote Ingress
|
||||||
export { RemoteIngressManager, TunnelManager } from './remoteingress/index.js';
|
export { RemoteIngressManager, TunnelManager } from './remoteingress/index.js';
|
||||||
|
|
||||||
|
// HTTP/3
|
||||||
|
export type { IHttp3Config } from './http3/index.js';
|
||||||
```
|
```
|
||||||
|
|
||||||
## Key Classes
|
## Key Classes
|
||||||
@@ -115,6 +121,7 @@ The central orchestrator. Accepts `IDcRouterOptions` and manages the lifecycle o
|
|||||||
| `radiusConfig` | RadiusServer (auth + accounting) | `@push.rocks/smartradius` |
|
| `radiusConfig` | RadiusServer (auth + accounting) | `@push.rocks/smartradius` |
|
||||||
| `remoteIngressConfig` | RemoteIngressManager + TunnelManager | `@serve.zone/remoteingress` |
|
| `remoteIngressConfig` | RemoteIngressManager + TunnelManager | `@serve.zone/remoteingress` |
|
||||||
| `tls` + `dnsChallenge` | SmartAcme (ACME cert provisioning) | `@push.rocks/smartacme` |
|
| `tls` + `dnsChallenge` | SmartAcme (ACME cert provisioning) | `@push.rocks/smartacme` |
|
||||||
|
| `http3` | HTTP/3 route augmentation (enabled by default) | built-in |
|
||||||
| `cacheConfig` | CacheDb (embedded MongoDB) | `@push.rocks/smartdata` |
|
| `cacheConfig` | CacheDb (embedded MongoDB) | `@push.rocks/smartdata` |
|
||||||
| *(always)* | OpsServer (dashboard + API) | `@api.global/typedserver` |
|
| *(always)* | OpsServer (dashboard + API) | `@api.global/typedserver` |
|
||||||
| *(always)* | MetricsManager | `@push.rocks/smartmetrics` |
|
| *(always)* | MetricsManager | `@push.rocks/smartmetrics` |
|
||||||
|
|||||||
@@ -94,6 +94,38 @@ export class RemoteIngressManager {
|
|||||||
return [...ports].sort((a, b) => a - b);
|
return [...ports].sort((a, b) => a - b);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Derive UDP listen ports for an edge from routes with transport 'udp' or 'all'.
|
||||||
|
* These ports need UDP listeners on the edge (e.g. for QUIC/HTTP3).
|
||||||
|
*/
|
||||||
|
public deriveUdpPortsForEdge(edgeId: string, edgeTags?: string[]): number[] {
|
||||||
|
const ports = new Set<number>();
|
||||||
|
|
||||||
|
for (const route of this.routes) {
|
||||||
|
if (!route.remoteIngress?.enabled) continue;
|
||||||
|
|
||||||
|
// Apply edge filter if present
|
||||||
|
const filter = route.remoteIngress.edgeFilter;
|
||||||
|
if (filter && filter.length > 0) {
|
||||||
|
const idMatch = filter.includes(edgeId);
|
||||||
|
const tagMatch = edgeTags?.some((tag) => filter.includes(tag)) ?? false;
|
||||||
|
if (!idMatch && !tagMatch) continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Only include ports from routes that listen on UDP
|
||||||
|
const transport = route.match?.transport;
|
||||||
|
if (transport === 'udp' || transport === 'all') {
|
||||||
|
if (route.match?.ports) {
|
||||||
|
for (const p of extractPorts(route.match.ports)) {
|
||||||
|
ports.add(p);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return [...ports].sort((a, b) => a - b);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the effective listen ports for an edge.
|
* Get the effective listen ports for an edge.
|
||||||
* Manual ports are always included. Auto-derived ports are added (union) when autoDerivePorts is true.
|
* Manual ports are always included. Auto-derived ports are added (union) when autoDerivePorts is true.
|
||||||
@@ -106,6 +138,18 @@ export class RemoteIngressManager {
|
|||||||
return [...new Set([...manualPorts, ...derivedPorts])].sort((a, b) => a - b);
|
return [...new Set([...manualPorts, ...derivedPorts])].sort((a, b) => a - b);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the effective UDP listen ports for an edge.
|
||||||
|
* Manual UDP ports are always included. Auto-derived UDP ports are added when autoDerivePorts is true.
|
||||||
|
*/
|
||||||
|
public getEffectiveListenPortsUdp(edge: IRemoteIngress): number[] {
|
||||||
|
const manualPorts = edge.listenPortsUdp || [];
|
||||||
|
const shouldDerive = edge.autoDerivePorts !== false;
|
||||||
|
if (!shouldDerive) return [...manualPorts].sort((a, b) => a - b);
|
||||||
|
const derivedPorts = this.deriveUdpPortsForEdge(edge.id, edge.tags);
|
||||||
|
return [...new Set([...manualPorts, ...derivedPorts])].sort((a, b) => a - b);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get manual and derived port breakdown for an edge (used in API responses).
|
* Get manual and derived port breakdown for an edge (used in API responses).
|
||||||
* Derived ports exclude any ports already present in the manual list.
|
* Derived ports exclude any ports already present in the manual list.
|
||||||
@@ -241,15 +285,18 @@ export class RemoteIngressManager {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the list of allowed edges (enabled only) for the Rust hub.
|
* Get the list of allowed edges (enabled only) for the Rust hub.
|
||||||
|
* Includes listenPortsUdp when routes with transport 'udp' or 'all' are present.
|
||||||
*/
|
*/
|
||||||
public getAllowedEdges(): Array<{ id: string; secret: string; listenPorts: number[] }> {
|
public getAllowedEdges(): Array<{ id: string; secret: string; listenPorts: number[]; listenPortsUdp?: number[] }> {
|
||||||
const result: Array<{ id: string; secret: string; listenPorts: number[] }> = [];
|
const result: Array<{ id: string; secret: string; listenPorts: number[]; listenPortsUdp?: number[] }> = [];
|
||||||
for (const edge of this.edges.values()) {
|
for (const edge of this.edges.values()) {
|
||||||
if (edge.enabled) {
|
if (edge.enabled) {
|
||||||
|
const listenPortsUdp = this.getEffectiveListenPortsUdp(edge);
|
||||||
result.push({
|
result.push({
|
||||||
id: edge.id,
|
id: edge.id,
|
||||||
secret: edge.secret,
|
secret: edge.secret,
|
||||||
listenPorts: this.getEffectiveListenPorts(edge),
|
listenPorts: this.getEffectiveListenPorts(edge),
|
||||||
|
...(listenPortsUdp.length > 0 ? { listenPortsUdp } : {}),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,6 +8,8 @@ export interface IRemoteIngress {
|
|||||||
name: string;
|
name: string;
|
||||||
secret: string;
|
secret: string;
|
||||||
listenPorts: number[];
|
listenPorts: number[];
|
||||||
|
/** UDP listen ports (e.g. for QUIC/HTTP3). Derived from routes with transport 'udp' or 'all'. */
|
||||||
|
listenPortsUdp?: number[];
|
||||||
enabled: boolean;
|
enabled: boolean;
|
||||||
/** Whether to auto-derive ports from remoteIngress-tagged routes. Defaults to true. */
|
/** Whether to auto-derive ports from remoteIngress-tagged routes. Defaults to true. */
|
||||||
autoDerivePorts: boolean;
|
autoDerivePorts: boolean;
|
||||||
@@ -20,6 +22,8 @@ export interface IRemoteIngress {
|
|||||||
manualPorts?: number[];
|
manualPorts?: number[];
|
||||||
/** Ports auto-derived from route configs — only present in API responses. */
|
/** Ports auto-derived from route configs — only present in API responses. */
|
||||||
derivedPorts?: number[];
|
derivedPorts?: number[];
|
||||||
|
/** Effective UDP ports (union of manual + derived) — only present in API responses. */
|
||||||
|
effectiveListenPortsUdp?: number[];
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -3,6 +3,6 @@
|
|||||||
*/
|
*/
|
||||||
export const commitinfo = {
|
export const commitinfo = {
|
||||||
name: '@serve.zone/dcrouter',
|
name: '@serve.zone/dcrouter',
|
||||||
version: '11.6.0',
|
version: '11.8.9',
|
||||||
description: 'A multifaceted routing service handling mail and SMS delivery functions.'
|
description: 'A multifaceted routing service handling mail and SMS delivery functions.'
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user