@serve.zone/remoteingress 3.2.0 → 3.3.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.
|
Binary file
|
|
Binary file
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
*/
|
|
4
4
|
export const commitinfo = {
|
|
5
5
|
name: '@serve.zone/remoteingress',
|
|
6
|
-
version: '3.
|
|
6
|
+
version: '3.3.0',
|
|
7
7
|
description: 'Edge ingress tunnel for DcRouter - accepts incoming TCP connections at network edge and tunnels them to DcRouter SmartProxy preserving client IP via PROXY protocol v1.'
|
|
8
8
|
};
|
|
9
9
|
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiMDBfY29tbWl0aW5mb19kYXRhLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vdHMvMDBfY29tbWl0aW5mb19kYXRhLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBOztHQUVHO0FBQ0gsTUFBTSxDQUFDLE1BQU0sVUFBVSxHQUFHO0lBQ3hCLElBQUksRUFBRSwyQkFBMkI7SUFDakMsT0FBTyxFQUFFLE9BQU87SUFDaEIsV0FBVyxFQUFFLHlLQUF5SztDQUN2TCxDQUFBIn0=
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@serve.zone/remoteingress",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.3.0",
|
|
4
4
|
"private": false,
|
|
5
5
|
"description": "Edge ingress tunnel for DcRouter - accepts incoming TCP connections at network edge and tunnels them to DcRouter SmartProxy preserving client IP via PROXY protocol v1.",
|
|
6
6
|
"main": "dist_ts/index.js",
|
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
"author": "Task Venture Capital GmbH",
|
|
10
10
|
"license": "MIT",
|
|
11
11
|
"scripts": {
|
|
12
|
-
"test": "(tstest test/ --
|
|
12
|
+
"test": "(tstest test/ --verbose --logfile --timeout 60)",
|
|
13
13
|
"build": "(tsbuild tsfolders --allowimplicitany && tsrust)",
|
|
14
14
|
"buildDocs": "(tsdoc)"
|
|
15
15
|
},
|
package/readme.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# @serve.zone/remoteingress
|
|
2
2
|
|
|
3
|
-
Edge ingress tunnel for DcRouter — accepts incoming TCP connections at the network edge and tunnels them to a DcRouter SmartProxy instance, preserving the original client IP via PROXY protocol v1.
|
|
3
|
+
Edge ingress tunnel for DcRouter — accepts incoming TCP connections at the network edge and tunnels them over a single encrypted TLS connection to a DcRouter SmartProxy instance, preserving the original client IP via PROXY protocol v1.
|
|
4
4
|
|
|
5
5
|
## Issue Reporting and Security
|
|
6
6
|
|
|
@@ -22,8 +22,8 @@ pnpm install @serve.zone/remoteingress
|
|
|
22
22
|
│ │ (multiplexed frames + │ │
|
|
23
23
|
│ RemoteIngressEdge │ shared-secret auth) │ RemoteIngressHub │
|
|
24
24
|
│ Accepts client TCP │ │ Forwards to │
|
|
25
|
-
│ connections
|
|
26
|
-
│
|
|
25
|
+
│ connections on │ │ SmartProxy on │
|
|
26
|
+
│ hub-assigned ports │ │ local ports │
|
|
27
27
|
└─────────────────────┘ └─────────────────────┘
|
|
28
28
|
▲ │
|
|
29
29
|
│ TCP from end users ▼
|
|
@@ -32,8 +32,8 @@ pnpm install @serve.zone/remoteingress
|
|
|
32
32
|
|
|
33
33
|
| Component | Role |
|
|
34
34
|
|-----------|------|
|
|
35
|
-
| **RemoteIngressEdge** | Deployed at the network edge (e.g. a VPS or cloud instance).
|
|
36
|
-
| **RemoteIngressHub** | Deployed alongside DcRouter/SmartProxy in a private cluster. Accepts edge connections, demuxes streams, and forwards each to SmartProxy with a PROXY protocol v1 header so the real client IP is preserved. |
|
|
35
|
+
| **RemoteIngressEdge** | Deployed at the network edge (e.g. a VPS or cloud instance). Listens on ports assigned by the hub, accepts raw TCP connections, and multiplexes them over a single TLS tunnel to the hub. Ports are hot-reloadable — the hub can change them at runtime. |
|
|
36
|
+
| **RemoteIngressHub** | Deployed alongside DcRouter/SmartProxy in a private cluster. Accepts edge connections, demuxes streams, and forwards each to SmartProxy with a PROXY protocol v1 header so the real client IP is preserved. Controls which ports each edge listens on. |
|
|
37
37
|
| **Rust Binary** (`remoteingress-bin`) | The performance-critical networking core. Managed via `@push.rocks/smartrust` RustBridge IPC — you never interact with it directly. Cross-compiled for `linux/amd64` and `linux/arm64`. |
|
|
38
38
|
|
|
39
39
|
### ✨ Key Features
|
|
@@ -45,6 +45,7 @@ pnpm install @serve.zone/remoteingress
|
|
|
45
45
|
- 🎫 **Connection tokens** — encode all connection details into a single opaque string
|
|
46
46
|
- 📡 **STUN-based public IP discovery** — the edge automatically discovers its public IP via Cloudflare STUN
|
|
47
47
|
- 🔄 **Auto-reconnect** with exponential backoff if the tunnel drops
|
|
48
|
+
- 🎛️ **Dynamic port configuration** — the hub assigns listen ports per edge and can hot-reload them at runtime via `FRAME_CONFIG` frames
|
|
48
49
|
- 📣 **Event-driven** — both Hub and Edge extend `EventEmitter` for real-time monitoring
|
|
49
50
|
- ⚡ **Rust core** — all frame encoding, TLS, and TCP proxying happen in native code for maximum throughput
|
|
50
51
|
|
|
@@ -79,10 +80,28 @@ await hub.start({
|
|
|
79
80
|
targetHost: '127.0.0.1', // SmartProxy host to forward streams to (default: 127.0.0.1)
|
|
80
81
|
});
|
|
81
82
|
|
|
82
|
-
// Register which edges are allowed to connect
|
|
83
|
+
// Register which edges are allowed to connect, including their listen ports
|
|
83
84
|
await hub.updateAllowedEdges([
|
|
84
|
-
{
|
|
85
|
-
|
|
85
|
+
{
|
|
86
|
+
id: 'edge-nyc-01',
|
|
87
|
+
secret: 'supersecrettoken1',
|
|
88
|
+
listenPorts: [80, 443], // ports the edge should listen on
|
|
89
|
+
stunIntervalSecs: 300, // STUN discovery interval (default: 300)
|
|
90
|
+
},
|
|
91
|
+
{
|
|
92
|
+
id: 'edge-fra-02',
|
|
93
|
+
secret: 'supersecrettoken2',
|
|
94
|
+
listenPorts: [443, 8080],
|
|
95
|
+
},
|
|
96
|
+
]);
|
|
97
|
+
|
|
98
|
+
// Dynamically update ports for a connected edge — changes are pushed instantly
|
|
99
|
+
await hub.updateAllowedEdges([
|
|
100
|
+
{
|
|
101
|
+
id: 'edge-nyc-01',
|
|
102
|
+
secret: 'supersecrettoken1',
|
|
103
|
+
listenPorts: [80, 443, 8443], // added port 8443 — edge picks it up in real time
|
|
104
|
+
},
|
|
86
105
|
]);
|
|
87
106
|
|
|
88
107
|
// Check status at any time
|
|
@@ -116,6 +135,8 @@ const edge = new RemoteIngressEdge();
|
|
|
116
135
|
edge.on('tunnelConnected', () => console.log('Tunnel established'));
|
|
117
136
|
edge.on('tunnelDisconnected', () => console.log('Tunnel lost — will auto-reconnect'));
|
|
118
137
|
edge.on('publicIpDiscovered', ({ ip }) => console.log(`Public IP: ${ip}`));
|
|
138
|
+
edge.on('portsAssigned', ({ listenPorts }) => console.log(`Listening on ports: ${listenPorts}`));
|
|
139
|
+
edge.on('portsUpdated', ({ listenPorts }) => console.log(`Ports updated: ${listenPorts}`));
|
|
119
140
|
|
|
120
141
|
// Single token contains hubHost, hubPort, edgeId, and secret
|
|
121
142
|
await edge.start({
|
|
@@ -133,6 +154,8 @@ const edge = new RemoteIngressEdge();
|
|
|
133
154
|
edge.on('tunnelConnected', () => console.log('Tunnel established'));
|
|
134
155
|
edge.on('tunnelDisconnected', () => console.log('Tunnel lost — will auto-reconnect'));
|
|
135
156
|
edge.on('publicIpDiscovered', ({ ip }) => console.log(`Public IP: ${ip}`));
|
|
157
|
+
edge.on('portsAssigned', ({ listenPorts }) => console.log(`Listening on ports: ${listenPorts}`));
|
|
158
|
+
edge.on('portsUpdated', ({ listenPorts }) => console.log(`Ports updated: ${listenPorts}`));
|
|
136
159
|
|
|
137
160
|
await edge.start({
|
|
138
161
|
hubHost: 'hub.example.com', // hostname or IP of the hub
|
|
@@ -194,7 +217,7 @@ Tokens are base64url-encoded (URL-safe, no padding) — safe to pass as environm
|
|
|
194
217
|
|-------------------|-------------|
|
|
195
218
|
| `start(config?)` | Spawns the Rust binary and starts the tunnel listener. Config: `{ tunnelPort?: number, targetHost?: string }` |
|
|
196
219
|
| `stop()` | Gracefully shuts down the hub and kills the Rust process. |
|
|
197
|
-
| `updateAllowedEdges(edges)` | Dynamically update which edges are authorized. Each edge: `{ id: string, secret: string }` |
|
|
220
|
+
| `updateAllowedEdges(edges)` | Dynamically update which edges are authorized and what ports they listen on. Each edge: `{ id: string, secret: string, listenPorts?: number[], stunIntervalSecs?: number }`. If ports change for a connected edge, the update is pushed immediately via a `FRAME_CONFIG` frame. |
|
|
198
221
|
| `getStatus()` | Returns current hub status including connected edges and active stream counts. |
|
|
199
222
|
| `running` | `boolean` — whether the Rust binary is alive. |
|
|
200
223
|
|
|
@@ -204,12 +227,12 @@ Tokens are base64url-encoded (URL-safe, no padding) — safe to pass as environm
|
|
|
204
227
|
|
|
205
228
|
| Method / Property | Description |
|
|
206
229
|
|-------------------|-------------|
|
|
207
|
-
| `start(config)` | Spawns the Rust binary and connects to the hub. Accepts `{ token: string }` or `IEdgeConfig`. |
|
|
230
|
+
| `start(config)` | Spawns the Rust binary and connects to the hub. Accepts `{ token: string }` or `IEdgeConfig`. Listen ports are received from the hub during handshake. |
|
|
208
231
|
| `stop()` | Gracefully shuts down the edge and kills the Rust process. |
|
|
209
|
-
| `getStatus()` | Returns current edge status including connection state, public IP, and active streams. |
|
|
232
|
+
| `getStatus()` | Returns current edge status including connection state, public IP, listen ports, and active streams. |
|
|
210
233
|
| `running` | `boolean` — whether the Rust binary is alive. |
|
|
211
234
|
|
|
212
|
-
**Events:** `tunnelConnected`, `tunnelDisconnected`, `publicIpDiscovered`
|
|
235
|
+
**Events:** `tunnelConnected`, `tunnelDisconnected`, `publicIpDiscovered`, `portsAssigned`, `portsUpdated`
|
|
213
236
|
|
|
214
237
|
### Token Utilities
|
|
215
238
|
|
|
@@ -246,7 +269,7 @@ interface IConnectionTokenData {
|
|
|
246
269
|
The tunnel uses a custom binary frame protocol over TLS:
|
|
247
270
|
|
|
248
271
|
```
|
|
249
|
-
[stream_id: 4 bytes][type: 1 byte][length: 4 bytes][payload: N bytes]
|
|
272
|
+
[stream_id: 4 bytes BE][type: 1 byte][length: 4 bytes BE][payload: N bytes]
|
|
250
273
|
```
|
|
251
274
|
|
|
252
275
|
| Frame Type | Value | Direction | Purpose |
|
|
@@ -256,8 +279,18 @@ The tunnel uses a custom binary frame protocol over TLS:
|
|
|
256
279
|
| `CLOSE` | `0x03` | Edge → Hub | Client closed the connection |
|
|
257
280
|
| `DATA_BACK` | `0x04` | Hub → Edge | Response data flowing downstream |
|
|
258
281
|
| `CLOSE_BACK` | `0x05` | Hub → Edge | Upstream (SmartProxy) closed the connection |
|
|
282
|
+
| `CONFIG` | `0x06` | Hub → Edge | Runtime configuration update (e.g. port changes); payload is JSON |
|
|
283
|
+
|
|
284
|
+
Max payload size per frame: **16 MB**. Stream IDs are 32-bit unsigned integers.
|
|
259
285
|
|
|
260
|
-
|
|
286
|
+
### Handshake Sequence
|
|
287
|
+
|
|
288
|
+
1. Edge opens a TLS connection to the hub
|
|
289
|
+
2. Edge sends: `EDGE <edgeId> <secret>\n`
|
|
290
|
+
3. Hub verifies credentials (constant-time comparison) and responds with JSON: `{"listenPorts":[...],"stunIntervalSecs":300}\n`
|
|
291
|
+
4. Edge starts TCP listeners on the assigned ports
|
|
292
|
+
5. Frame protocol begins — `OPEN`/`DATA`/`CLOSE` frames flow in both directions
|
|
293
|
+
6. Hub can push `CONFIG` frames at any time to update the edge's listen ports
|
|
261
294
|
|
|
262
295
|
## 💡 Example Scenarios
|
|
263
296
|
|
|
@@ -292,6 +325,22 @@ const edge = new RemoteIngressEdge();
|
|
|
292
325
|
await edge.start({ token });
|
|
293
326
|
```
|
|
294
327
|
|
|
328
|
+
### 5. Dynamic Port Management
|
|
329
|
+
|
|
330
|
+
The hub controls which ports each edge listens on. Ports can be changed at runtime without restarting the edge — the hub pushes a `CONFIG` frame and the edge hot-reloads its TCP listeners.
|
|
331
|
+
|
|
332
|
+
```typescript
|
|
333
|
+
// Initially assign ports 80 and 443
|
|
334
|
+
await hub.updateAllowedEdges([
|
|
335
|
+
{ id: 'edge-nyc-01', secret: 'secret', listenPorts: [80, 443] },
|
|
336
|
+
]);
|
|
337
|
+
|
|
338
|
+
// Later, add port 8080 — the connected edge picks it up instantly
|
|
339
|
+
await hub.updateAllowedEdges([
|
|
340
|
+
{ id: 'edge-nyc-01', secret: 'secret', listenPorts: [80, 443, 8080] },
|
|
341
|
+
]);
|
|
342
|
+
```
|
|
343
|
+
|
|
295
344
|
## License and Legal Information
|
|
296
345
|
|
|
297
346
|
This repository contains open-source code licensed under the MIT License. A copy of the license can be found in the [LICENSE](./LICENSE) file.
|
package/ts/00_commitinfo_data.ts
CHANGED
|
@@ -3,6 +3,6 @@
|
|
|
3
3
|
*/
|
|
4
4
|
export const commitinfo = {
|
|
5
5
|
name: '@serve.zone/remoteingress',
|
|
6
|
-
version: '3.
|
|
6
|
+
version: '3.3.0',
|
|
7
7
|
description: 'Edge ingress tunnel for DcRouter - accepts incoming TCP connections at network edge and tunnels them to DcRouter SmartProxy preserving client IP via PROXY protocol v1.'
|
|
8
8
|
}
|