@serve.zone/remoteingress 1.0.4 → 3.0.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.
- package/dist_rust/remoteingress-bin_linux_amd64 +0 -0
- package/dist_rust/remoteingress-bin_linux_arm64 +0 -0
- package/dist_ts/00_commitinfo_data.d.ts +1 -1
- package/dist_ts/00_commitinfo_data.js +4 -4
- package/dist_ts/classes.remoteingressedge.d.ts +36 -0
- package/dist_ts/classes.remoteingressedge.js +77 -0
- package/dist_ts/classes.remoteingresshub.d.ts +41 -0
- package/dist_ts/classes.remoteingresshub.js +82 -0
- package/dist_ts/index.d.ts +2 -4
- package/dist_ts/index.js +3 -9
- package/dist_ts/plugins.d.ts +4 -7
- package/dist_ts/plugins.js +5 -6
- package/npmextra.json +18 -6
- package/package.json +22 -23
- package/ts/00_commitinfo_data.ts +3 -3
- package/ts/classes.remoteingressedge.ts +132 -0
- package/ts/classes.remoteingresshub.ts +138 -0
- package/ts/index.ts +2 -14
- package/ts/plugins.ts +4 -12
- package/dist_ts/connector.private.d.ts +0 -6
- package/dist_ts/connector.private.js +0 -31
- package/dist_ts/connector.public.d.ts +0 -6
- package/dist_ts/connector.public.js +0 -40
- package/ts/connector.private.ts +0 -38
- package/ts/connector.public.ts +0 -45
|
Binary file
|
|
Binary file
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* autocreated commitinfo by @
|
|
2
|
+
* autocreated commitinfo by @push.rocks/commitinfo
|
|
3
3
|
*/
|
|
4
4
|
export const commitinfo = {
|
|
5
5
|
name: '@serve.zone/remoteingress',
|
|
6
|
-
version: '
|
|
7
|
-
description: '
|
|
6
|
+
version: '3.0.0',
|
|
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
|
-
//# sourceMappingURL=data:application/json;base64,
|
|
9
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiMDBfY29tbWl0aW5mb19kYXRhLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vdHMvMDBfY29tbWl0aW5mb19kYXRhLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBOztHQUVHO0FBQ0gsTUFBTSxDQUFDLE1BQU0sVUFBVSxHQUFHO0lBQ3hCLElBQUksRUFBRSwyQkFBMkI7SUFDakMsT0FBTyxFQUFFLE9BQU87SUFDaEIsV0FBVyxFQUFFLHlLQUF5SztDQUN2TCxDQUFBIn0=
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { EventEmitter } from 'events';
|
|
2
|
+
export interface IEdgeConfig {
|
|
3
|
+
hubHost: string;
|
|
4
|
+
hubPort?: number;
|
|
5
|
+
edgeId: string;
|
|
6
|
+
secret: string;
|
|
7
|
+
listenPorts: number[];
|
|
8
|
+
stunIntervalSecs?: number;
|
|
9
|
+
}
|
|
10
|
+
export declare class RemoteIngressEdge extends EventEmitter {
|
|
11
|
+
private bridge;
|
|
12
|
+
private started;
|
|
13
|
+
constructor();
|
|
14
|
+
/**
|
|
15
|
+
* Start the edge — spawns the Rust binary and connects to the hub.
|
|
16
|
+
*/
|
|
17
|
+
start(config: IEdgeConfig): Promise<void>;
|
|
18
|
+
/**
|
|
19
|
+
* Stop the edge and kill the Rust process.
|
|
20
|
+
*/
|
|
21
|
+
stop(): Promise<void>;
|
|
22
|
+
/**
|
|
23
|
+
* Get the current edge status.
|
|
24
|
+
*/
|
|
25
|
+
getStatus(): Promise<{
|
|
26
|
+
running: boolean;
|
|
27
|
+
connected: boolean;
|
|
28
|
+
publicIp: string | null;
|
|
29
|
+
activeStreams: number;
|
|
30
|
+
listenPorts: number[];
|
|
31
|
+
}>;
|
|
32
|
+
/**
|
|
33
|
+
* Check if the bridge is running.
|
|
34
|
+
*/
|
|
35
|
+
get running(): boolean;
|
|
36
|
+
}
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import * as plugins from './plugins.js';
|
|
2
|
+
import { EventEmitter } from 'events';
|
|
3
|
+
export class RemoteIngressEdge extends EventEmitter {
|
|
4
|
+
constructor() {
|
|
5
|
+
super();
|
|
6
|
+
this.started = false;
|
|
7
|
+
const packageDir = plugins.path.resolve(plugins.path.dirname(new URL(import.meta.url).pathname), '..');
|
|
8
|
+
this.bridge = new plugins.smartrust.RustBridge({
|
|
9
|
+
binaryName: 'remoteingress-bin',
|
|
10
|
+
cliArgs: ['--management'],
|
|
11
|
+
requestTimeoutMs: 30_000,
|
|
12
|
+
readyTimeoutMs: 10_000,
|
|
13
|
+
localPaths: [
|
|
14
|
+
plugins.path.join(packageDir, 'dist_rust'),
|
|
15
|
+
plugins.path.join(packageDir, 'rust', 'target', 'release'),
|
|
16
|
+
plugins.path.join(packageDir, 'rust', 'target', 'debug'),
|
|
17
|
+
],
|
|
18
|
+
searchSystemPath: false,
|
|
19
|
+
});
|
|
20
|
+
// Forward events from Rust binary
|
|
21
|
+
this.bridge.on('management:tunnelConnected', () => {
|
|
22
|
+
this.emit('tunnelConnected');
|
|
23
|
+
});
|
|
24
|
+
this.bridge.on('management:tunnelDisconnected', () => {
|
|
25
|
+
this.emit('tunnelDisconnected');
|
|
26
|
+
});
|
|
27
|
+
this.bridge.on('management:publicIpDiscovered', (data) => {
|
|
28
|
+
this.emit('publicIpDiscovered', data);
|
|
29
|
+
});
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Start the edge — spawns the Rust binary and connects to the hub.
|
|
33
|
+
*/
|
|
34
|
+
async start(config) {
|
|
35
|
+
const spawned = await this.bridge.spawn();
|
|
36
|
+
if (!spawned) {
|
|
37
|
+
throw new Error('Failed to spawn remoteingress-bin');
|
|
38
|
+
}
|
|
39
|
+
await this.bridge.sendCommand('startEdge', {
|
|
40
|
+
hubHost: config.hubHost,
|
|
41
|
+
hubPort: config.hubPort ?? 8443,
|
|
42
|
+
edgeId: config.edgeId,
|
|
43
|
+
secret: config.secret,
|
|
44
|
+
listenPorts: config.listenPorts,
|
|
45
|
+
stunIntervalSecs: config.stunIntervalSecs,
|
|
46
|
+
});
|
|
47
|
+
this.started = true;
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Stop the edge and kill the Rust process.
|
|
51
|
+
*/
|
|
52
|
+
async stop() {
|
|
53
|
+
if (this.started) {
|
|
54
|
+
try {
|
|
55
|
+
await this.bridge.sendCommand('stopEdge', {});
|
|
56
|
+
}
|
|
57
|
+
catch {
|
|
58
|
+
// Process may already be dead
|
|
59
|
+
}
|
|
60
|
+
this.bridge.kill();
|
|
61
|
+
this.started = false;
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Get the current edge status.
|
|
66
|
+
*/
|
|
67
|
+
async getStatus() {
|
|
68
|
+
return this.bridge.sendCommand('getEdgeStatus', {});
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* Check if the bridge is running.
|
|
72
|
+
*/
|
|
73
|
+
get running() {
|
|
74
|
+
return this.bridge.running;
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2xhc3Nlcy5yZW1vdGVpbmdyZXNzZWRnZS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uL3RzL2NsYXNzZXMucmVtb3RlaW5ncmVzc2VkZ2UudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxLQUFLLE9BQU8sTUFBTSxjQUFjLENBQUM7QUFDeEMsT0FBTyxFQUFFLFlBQVksRUFBRSxNQUFNLFFBQVEsQ0FBQztBQTRDdEMsTUFBTSxPQUFPLGlCQUFrQixTQUFRLFlBQVk7SUFJakQ7UUFDRSxLQUFLLEVBQUUsQ0FBQztRQUhGLFlBQU8sR0FBRyxLQUFLLENBQUM7UUFLdEIsTUFBTSxVQUFVLEdBQUcsT0FBTyxDQUFDLElBQUksQ0FBQyxPQUFPLENBQ3JDLE9BQU8sQ0FBQyxJQUFJLENBQUMsT0FBTyxDQUFDLElBQUksR0FBRyxDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUMsR0FBRyxDQUFDLENBQUMsUUFBUSxDQUFDLEVBQ3ZELElBQUksQ0FDTCxDQUFDO1FBRUYsSUFBSSxDQUFDLE1BQU0sR0FBRyxJQUFJLE9BQU8sQ0FBQyxTQUFTLENBQUMsVUFBVSxDQUFnQjtZQUM1RCxVQUFVLEVBQUUsbUJBQW1CO1lBQy9CLE9BQU8sRUFBRSxDQUFDLGNBQWMsQ0FBQztZQUN6QixnQkFBZ0IsRUFBRSxNQUFNO1lBQ3hCLGNBQWMsRUFBRSxNQUFNO1lBQ3RCLFVBQVUsRUFBRTtnQkFDVixPQUFPLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxVQUFVLEVBQUUsV0FBVyxDQUFDO2dCQUMxQyxPQUFPLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxVQUFVLEVBQUUsTUFBTSxFQUFFLFFBQVEsRUFBRSxTQUFTLENBQUM7Z0JBQzFELE9BQU8sQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLFVBQVUsRUFBRSxNQUFNLEVBQUUsUUFBUSxFQUFFLE9BQU8sQ0FBQzthQUN6RDtZQUNELGdCQUFnQixFQUFFLEtBQUs7U0FDeEIsQ0FBQyxDQUFDO1FBRUgsa0NBQWtDO1FBQ2xDLElBQUksQ0FBQyxNQUFNLENBQUMsRUFBRSxDQUFDLDRCQUE0QixFQUFFLEdBQUcsRUFBRTtZQUNoRCxJQUFJLENBQUMsSUFBSSxDQUFDLGlCQUFpQixDQUFDLENBQUM7UUFDL0IsQ0FBQyxDQUFDLENBQUM7UUFDSCxJQUFJLENBQUMsTUFBTSxDQUFDLEVBQUUsQ0FBQywrQkFBK0IsRUFBRSxHQUFHLEVBQUU7WUFDbkQsSUFBSSxDQUFDLElBQUksQ0FBQyxvQkFBb0IsQ0FBQyxDQUFDO1FBQ2xDLENBQUMsQ0FBQyxDQUFDO1FBQ0gsSUFBSSxDQUFDLE1BQU0sQ0FBQyxFQUFFLENBQUMsK0JBQStCLEVBQUUsQ0FBQyxJQUFvQixFQUFFLEVBQUU7WUFDdkUsSUFBSSxDQUFDLElBQUksQ0FBQyxvQkFBb0IsRUFBRSxJQUFJLENBQUMsQ0FBQztRQUN4QyxDQUFDLENBQUMsQ0FBQztJQUNMLENBQUM7SUFFRDs7T0FFRztJQUNJLEtBQUssQ0FBQyxLQUFLLENBQUMsTUFBbUI7UUFDcEMsTUFBTSxPQUFPLEdBQUcsTUFBTSxJQUFJLENBQUMsTUFBTSxDQUFDLEtBQUssRUFBRSxDQUFDO1FBQzFDLElBQUksQ0FBQyxPQUFPLEVBQUUsQ0FBQztZQUNiLE1BQU0sSUFBSSxLQUFLLENBQUMsbUNBQW1DLENBQUMsQ0FBQztRQUN2RCxDQUFDO1FBRUQsTUFBTSxJQUFJLENBQUMsTUFBTSxDQUFDLFdBQVcsQ0FBQyxXQUFXLEVBQUU7WUFDekMsT0FBTyxFQUFFLE1BQU0sQ0FBQyxPQUFPO1lBQ3ZCLE9BQU8sRUFBRSxNQUFNLENBQUMsT0FBTyxJQUFJLElBQUk7WUFDL0IsTUFBTSxFQUFFLE1BQU0sQ0FBQyxNQUFNO1lBQ3JCLE1BQU0sRUFBRSxNQUFNLENBQUMsTUFBTTtZQUNyQixXQUFXLEVBQUUsTUFBTSxDQUFDLFdBQVc7WUFDL0IsZ0JBQWdCLEVBQUUsTUFBTSxDQUFDLGdCQUFnQjtTQUMxQyxDQUFDLENBQUM7UUFFSCxJQUFJLENBQUMsT0FBTyxHQUFHLElBQUksQ0FBQztJQUN0QixDQUFDO0lBRUQ7O09BRUc7SUFDSSxLQUFLLENBQUMsSUFBSTtRQUNmLElBQUksSUFBSSxDQUFDLE9BQU8sRUFBRSxDQUFDO1lBQ2pCLElBQUksQ0FBQztnQkFDSCxNQUFNLElBQUksQ0FBQyxNQUFNLENBQUMsV0FBVyxDQUFDLFVBQVUsRUFBRSxFQUEyQixDQUFDLENBQUM7WUFDekUsQ0FBQztZQUFDLE1BQU0sQ0FBQztnQkFDUCw4QkFBOEI7WUFDaEMsQ0FBQztZQUNELElBQUksQ0FBQyxNQUFNLENBQUMsSUFBSSxFQUFFLENBQUM7WUFDbkIsSUFBSSxDQUFDLE9BQU8sR0FBRyxLQUFLLENBQUM7UUFDdkIsQ0FBQztJQUNILENBQUM7SUFFRDs7T0FFRztJQUNJLEtBQUssQ0FBQyxTQUFTO1FBQ3BCLE9BQU8sSUFBSSxDQUFDLE1BQU0sQ0FBQyxXQUFXLENBQUMsZUFBZSxFQUFFLEVBQTJCLENBQUMsQ0FBQztJQUMvRSxDQUFDO0lBRUQ7O09BRUc7SUFDSCxJQUFXLE9BQU87UUFDaEIsT0FBTyxJQUFJLENBQUMsTUFBTSxDQUFDLE9BQU8sQ0FBQztJQUM3QixDQUFDO0NBQ0YifQ==
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { EventEmitter } from 'events';
|
|
2
|
+
export interface IHubConfig {
|
|
3
|
+
tunnelPort?: number;
|
|
4
|
+
targetHost?: string;
|
|
5
|
+
}
|
|
6
|
+
export declare class RemoteIngressHub extends EventEmitter {
|
|
7
|
+
private bridge;
|
|
8
|
+
private started;
|
|
9
|
+
constructor();
|
|
10
|
+
/**
|
|
11
|
+
* Start the hub — spawns the Rust binary and starts the tunnel server.
|
|
12
|
+
*/
|
|
13
|
+
start(config?: IHubConfig): Promise<void>;
|
|
14
|
+
/**
|
|
15
|
+
* Stop the hub and kill the Rust process.
|
|
16
|
+
*/
|
|
17
|
+
stop(): Promise<void>;
|
|
18
|
+
/**
|
|
19
|
+
* Update the list of allowed edges that can connect to this hub.
|
|
20
|
+
*/
|
|
21
|
+
updateAllowedEdges(edges: Array<{
|
|
22
|
+
id: string;
|
|
23
|
+
secret: string;
|
|
24
|
+
}>): Promise<void>;
|
|
25
|
+
/**
|
|
26
|
+
* Get the current hub status.
|
|
27
|
+
*/
|
|
28
|
+
getStatus(): Promise<{
|
|
29
|
+
running: boolean;
|
|
30
|
+
tunnelPort: number;
|
|
31
|
+
connectedEdges: Array<{
|
|
32
|
+
edgeId: string;
|
|
33
|
+
connectedAt: number;
|
|
34
|
+
activeStreams: number;
|
|
35
|
+
}>;
|
|
36
|
+
}>;
|
|
37
|
+
/**
|
|
38
|
+
* Check if the bridge is running.
|
|
39
|
+
*/
|
|
40
|
+
get running(): boolean;
|
|
41
|
+
}
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
import * as plugins from './plugins.js';
|
|
2
|
+
import { EventEmitter } from 'events';
|
|
3
|
+
export class RemoteIngressHub extends EventEmitter {
|
|
4
|
+
constructor() {
|
|
5
|
+
super();
|
|
6
|
+
this.started = false;
|
|
7
|
+
const packageDir = plugins.path.resolve(plugins.path.dirname(new URL(import.meta.url).pathname), '..');
|
|
8
|
+
this.bridge = new plugins.smartrust.RustBridge({
|
|
9
|
+
binaryName: 'remoteingress-bin',
|
|
10
|
+
cliArgs: ['--management'],
|
|
11
|
+
requestTimeoutMs: 30_000,
|
|
12
|
+
readyTimeoutMs: 10_000,
|
|
13
|
+
localPaths: [
|
|
14
|
+
plugins.path.join(packageDir, 'dist_rust'),
|
|
15
|
+
plugins.path.join(packageDir, 'rust', 'target', 'release'),
|
|
16
|
+
plugins.path.join(packageDir, 'rust', 'target', 'debug'),
|
|
17
|
+
],
|
|
18
|
+
searchSystemPath: false,
|
|
19
|
+
});
|
|
20
|
+
// Forward events from Rust binary
|
|
21
|
+
this.bridge.on('management:edgeConnected', (data) => {
|
|
22
|
+
this.emit('edgeConnected', data);
|
|
23
|
+
});
|
|
24
|
+
this.bridge.on('management:edgeDisconnected', (data) => {
|
|
25
|
+
this.emit('edgeDisconnected', data);
|
|
26
|
+
});
|
|
27
|
+
this.bridge.on('management:streamOpened', (data) => {
|
|
28
|
+
this.emit('streamOpened', data);
|
|
29
|
+
});
|
|
30
|
+
this.bridge.on('management:streamClosed', (data) => {
|
|
31
|
+
this.emit('streamClosed', data);
|
|
32
|
+
});
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Start the hub — spawns the Rust binary and starts the tunnel server.
|
|
36
|
+
*/
|
|
37
|
+
async start(config = {}) {
|
|
38
|
+
const spawned = await this.bridge.spawn();
|
|
39
|
+
if (!spawned) {
|
|
40
|
+
throw new Error('Failed to spawn remoteingress-bin');
|
|
41
|
+
}
|
|
42
|
+
await this.bridge.sendCommand('startHub', {
|
|
43
|
+
tunnelPort: config.tunnelPort ?? 8443,
|
|
44
|
+
targetHost: config.targetHost ?? '127.0.0.1',
|
|
45
|
+
});
|
|
46
|
+
this.started = true;
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Stop the hub and kill the Rust process.
|
|
50
|
+
*/
|
|
51
|
+
async stop() {
|
|
52
|
+
if (this.started) {
|
|
53
|
+
try {
|
|
54
|
+
await this.bridge.sendCommand('stopHub', {});
|
|
55
|
+
}
|
|
56
|
+
catch {
|
|
57
|
+
// Process may already be dead
|
|
58
|
+
}
|
|
59
|
+
this.bridge.kill();
|
|
60
|
+
this.started = false;
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* Update the list of allowed edges that can connect to this hub.
|
|
65
|
+
*/
|
|
66
|
+
async updateAllowedEdges(edges) {
|
|
67
|
+
await this.bridge.sendCommand('updateAllowedEdges', { edges });
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Get the current hub status.
|
|
71
|
+
*/
|
|
72
|
+
async getStatus() {
|
|
73
|
+
return this.bridge.sendCommand('getHubStatus', {});
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* Check if the bridge is running.
|
|
77
|
+
*/
|
|
78
|
+
get running() {
|
|
79
|
+
return this.bridge.running;
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2xhc3Nlcy5yZW1vdGVpbmdyZXNzaHViLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vdHMvY2xhc3Nlcy5yZW1vdGVpbmdyZXNzaHViLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sS0FBSyxPQUFPLE1BQU0sY0FBYyxDQUFDO0FBQ3hDLE9BQU8sRUFBRSxZQUFZLEVBQUUsTUFBTSxRQUFRLENBQUM7QUE0Q3RDLE1BQU0sT0FBTyxnQkFBaUIsU0FBUSxZQUFZO0lBSWhEO1FBQ0UsS0FBSyxFQUFFLENBQUM7UUFIRixZQUFPLEdBQUcsS0FBSyxDQUFDO1FBS3RCLE1BQU0sVUFBVSxHQUFHLE9BQU8sQ0FBQyxJQUFJLENBQUMsT0FBTyxDQUNyQyxPQUFPLENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxJQUFJLEdBQUcsQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDLEdBQUcsQ0FBQyxDQUFDLFFBQVEsQ0FBQyxFQUN2RCxJQUFJLENBQ0wsQ0FBQztRQUVGLElBQUksQ0FBQyxNQUFNLEdBQUcsSUFBSSxPQUFPLENBQUMsU0FBUyxDQUFDLFVBQVUsQ0FBZTtZQUMzRCxVQUFVLEVBQUUsbUJBQW1CO1lBQy9CLE9BQU8sRUFBRSxDQUFDLGNBQWMsQ0FBQztZQUN6QixnQkFBZ0IsRUFBRSxNQUFNO1lBQ3hCLGNBQWMsRUFBRSxNQUFNO1lBQ3RCLFVBQVUsRUFBRTtnQkFDVixPQUFPLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxVQUFVLEVBQUUsV0FBVyxDQUFDO2dCQUMxQyxPQUFPLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxVQUFVLEVBQUUsTUFBTSxFQUFFLFFBQVEsRUFBRSxTQUFTLENBQUM7Z0JBQzFELE9BQU8sQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLFVBQVUsRUFBRSxNQUFNLEVBQUUsUUFBUSxFQUFFLE9BQU8sQ0FBQzthQUN6RDtZQUNELGdCQUFnQixFQUFFLEtBQUs7U0FDeEIsQ0FBQyxDQUFDO1FBRUgsa0NBQWtD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
|
package/dist_ts/index.d.ts
CHANGED
|
@@ -1,4 +1,2 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
export { ConnectorPublic, ConnectorPrivate };
|
|
4
|
-
export declare const runCli: () => Promise<void>;
|
|
1
|
+
export * from './classes.remoteingresshub.js';
|
|
2
|
+
export * from './classes.remoteingressedge.js';
|
package/dist_ts/index.js
CHANGED
|
@@ -1,9 +1,3 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
export { ConnectorPublic, ConnectorPrivate };
|
|
5
|
-
export const runCli = async () => {
|
|
6
|
-
const qenv = new plugins.qenv.Qenv();
|
|
7
|
-
const mode = await qenv.getEnvVarOnDemand('MODE');
|
|
8
|
-
};
|
|
9
|
-
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi90cy9pbmRleC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEtBQUssT0FBTyxNQUFNLGNBQWMsQ0FBQztBQUV4QyxPQUFPLEVBQUUsZUFBZSxFQUFFLE1BQU0sdUJBQXVCLENBQUM7QUFDeEQsT0FBTyxFQUFFLGdCQUFnQixFQUFFLE1BQU0sd0JBQXdCLENBQUM7QUFFMUQsT0FBTyxFQUNMLGVBQWUsRUFDZixnQkFBZ0IsRUFDakIsQ0FBQTtBQUVELE1BQU0sQ0FBQyxNQUFNLE1BQU0sR0FBRyxLQUFLLElBQUksRUFBRTtJQUMvQixNQUFNLElBQUksR0FBRyxJQUFJLE9BQU8sQ0FBQyxJQUFJLENBQUMsSUFBSSxFQUFFLENBQUM7SUFDckMsTUFBTSxJQUFJLEdBQUcsTUFBTSxJQUFJLENBQUMsaUJBQWlCLENBQUMsTUFBTSxDQUFDLENBQUM7QUFDcEQsQ0FBQyxDQUFBIn0=
|
|
1
|
+
export * from './classes.remoteingresshub.js';
|
|
2
|
+
export * from './classes.remoteingressedge.js';
|
|
3
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi90cy9pbmRleC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxjQUFjLCtCQUErQixDQUFDO0FBQzlDLGNBQWMsZ0NBQWdDLENBQUMifQ==
|
package/dist_ts/plugins.d.ts
CHANGED
|
@@ -1,7 +1,4 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
import * as
|
|
4
|
-
|
|
5
|
-
export { tls, fs, };
|
|
6
|
-
import * as qenv from '@push.rocks/qenv';
|
|
7
|
-
export { qenv, };
|
|
1
|
+
import * as path from 'path';
|
|
2
|
+
export { path };
|
|
3
|
+
import * as smartrust from '@push.rocks/smartrust';
|
|
4
|
+
export { smartrust };
|
package/dist_ts/plugins.js
CHANGED
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
// node native scope
|
|
2
|
-
import * as
|
|
3
|
-
|
|
4
|
-
export { tls, fs, };
|
|
2
|
+
import * as path from 'path';
|
|
3
|
+
export { path };
|
|
5
4
|
// @push.rocks scope
|
|
6
|
-
import * as
|
|
7
|
-
export {
|
|
8
|
-
//# sourceMappingURL=data:application/json;base64,
|
|
5
|
+
import * as smartrust from '@push.rocks/smartrust';
|
|
6
|
+
export { smartrust };
|
|
7
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicGx1Z2lucy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uL3RzL3BsdWdpbnMudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsb0JBQW9CO0FBQ3BCLE9BQU8sS0FBSyxJQUFJLE1BQU0sTUFBTSxDQUFDO0FBQzdCLE9BQU8sRUFBRSxJQUFJLEVBQUUsQ0FBQztBQUVoQixvQkFBb0I7QUFDcEIsT0FBTyxLQUFLLFNBQVMsTUFBTSx1QkFBdUIsQ0FBQztBQUNuRCxPQUFPLEVBQUUsU0FBUyxFQUFFLENBQUMifQ==
|
package/npmextra.json
CHANGED
|
@@ -1,5 +1,11 @@
|
|
|
1
1
|
{
|
|
2
|
-
"
|
|
2
|
+
"@git.zone/tsrust": {
|
|
3
|
+
"targets": [
|
|
4
|
+
"linux_amd64",
|
|
5
|
+
"linux_arm64"
|
|
6
|
+
]
|
|
7
|
+
},
|
|
8
|
+
"@git.zone/cli": {
|
|
3
9
|
"projectType": "npm",
|
|
4
10
|
"module": {
|
|
5
11
|
"githost": "code.foss.global",
|
|
@@ -26,13 +32,19 @@
|
|
|
26
32
|
"software development",
|
|
27
33
|
"private network integration"
|
|
28
34
|
]
|
|
35
|
+
},
|
|
36
|
+
"release": {
|
|
37
|
+
"registries": [
|
|
38
|
+
"https://verdaccio.lossless.digital",
|
|
39
|
+
"https://registry.npmjs.org"
|
|
40
|
+
],
|
|
41
|
+
"accessLevel": "public"
|
|
29
42
|
}
|
|
30
43
|
},
|
|
31
|
-
"
|
|
32
|
-
"npmGlobalTools": [],
|
|
33
|
-
"npmAccessLevel": "public"
|
|
34
|
-
},
|
|
35
|
-
"tsdoc": {
|
|
44
|
+
"@git.zone/tsdoc": {
|
|
36
45
|
"legal": "\n## License and Legal Information\n\nThis repository contains open-source code that is licensed under the MIT License. A copy of the MIT License can be found in the [license](license) file within this repository. \n\n**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.\n\n### Trademarks\n\nThis project is owned and maintained by Task Venture Capital GmbH. The names and logos associated with Task Venture Capital GmbH and any related products or services are trademarks of Task Venture Capital GmbH and are not included within the scope of the MIT license granted herein. Use of these trademarks must comply with Task Venture Capital GmbH's Trademark Guidelines, and any usage must be approved in writing by Task Venture Capital GmbH.\n\n### Company Information\n\nTask Venture Capital GmbH \nRegistered at District court Bremen HRB 35230 HB, Germany\n\nFor any legal inquiries or if you require further information, please contact us via email at hello@task.vc.\n\nBy using this repository, you acknowledge that you have read this section, agree to comply with its terms, and understand that the licensing of the code does not imply endorsement by Task Venture Capital GmbH of any derivative works.\n"
|
|
46
|
+
},
|
|
47
|
+
"@ship.zone/szci": {
|
|
48
|
+
"npmGlobalTools": []
|
|
37
49
|
}
|
|
38
50
|
}
|
package/package.json
CHANGED
|
@@ -1,23 +1,30 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@serve.zone/remoteingress",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "3.0.0",
|
|
4
4
|
"private": false,
|
|
5
|
-
"description": "
|
|
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",
|
|
7
7
|
"typings": "dist_ts/index.d.ts",
|
|
8
8
|
"type": "module",
|
|
9
9
|
"author": "Task Venture Capital GmbH",
|
|
10
10
|
"license": "MIT",
|
|
11
|
+
"scripts": {
|
|
12
|
+
"test": "(tstest test/ --web)",
|
|
13
|
+
"build": "(tsbuild --web --allowimplicitany && tsrust)",
|
|
14
|
+
"buildDocs": "(tsdoc)"
|
|
15
|
+
},
|
|
11
16
|
"devDependencies": {
|
|
12
17
|
"@git.zone/tsbuild": "^2.1.25",
|
|
13
18
|
"@git.zone/tsbundle": "^2.0.5",
|
|
14
19
|
"@git.zone/tsrun": "^1.2.46",
|
|
20
|
+
"@git.zone/tsrust": "^1.3.0",
|
|
15
21
|
"@git.zone/tstest": "^1.0.44",
|
|
16
22
|
"@push.rocks/tapbundle": "^5.0.15",
|
|
17
23
|
"@types/node": "^20.8.7"
|
|
18
24
|
},
|
|
19
25
|
"dependencies": {
|
|
20
|
-
"@push.rocks/qenv": "^6.0.5"
|
|
26
|
+
"@push.rocks/qenv": "^6.0.5",
|
|
27
|
+
"@push.rocks/smartrust": "^1.2.1"
|
|
21
28
|
},
|
|
22
29
|
"repository": {
|
|
23
30
|
"type": "git",
|
|
@@ -37,6 +44,7 @@
|
|
|
37
44
|
"dist_*/**/*",
|
|
38
45
|
"dist_ts/**/*",
|
|
39
46
|
"dist_ts_web/**/*",
|
|
47
|
+
"dist_rust/**/*",
|
|
40
48
|
"assets/**/*",
|
|
41
49
|
"cli.js",
|
|
42
50
|
"npmextra.json",
|
|
@@ -44,24 +52,15 @@
|
|
|
44
52
|
],
|
|
45
53
|
"keywords": [
|
|
46
54
|
"remote access",
|
|
47
|
-
"
|
|
48
|
-
"network
|
|
49
|
-
"
|
|
50
|
-
"
|
|
55
|
+
"ingress tunnel",
|
|
56
|
+
"network edge",
|
|
57
|
+
"PROXY protocol",
|
|
58
|
+
"multiplexed tunnel",
|
|
59
|
+
"TCP proxy",
|
|
60
|
+
"TLS tunnel",
|
|
51
61
|
"serve.zone stack",
|
|
52
|
-
"
|
|
53
|
-
"
|
|
54
|
-
"
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
"TLS/SSL certificates",
|
|
58
|
-
"development tools",
|
|
59
|
-
"software development",
|
|
60
|
-
"private network integration"
|
|
61
|
-
],
|
|
62
|
-
"scripts": {
|
|
63
|
-
"test": "(tstest test/ --web)",
|
|
64
|
-
"build": "(tsbuild --web --allowimplicitany)",
|
|
65
|
-
"buildDocs": "(tsdoc)"
|
|
66
|
-
}
|
|
67
|
-
}
|
|
62
|
+
"TypeScript",
|
|
63
|
+
"Rust",
|
|
64
|
+
"SmartProxy"
|
|
65
|
+
]
|
|
66
|
+
}
|
package/ts/00_commitinfo_data.ts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* autocreated commitinfo by @
|
|
2
|
+
* autocreated commitinfo by @push.rocks/commitinfo
|
|
3
3
|
*/
|
|
4
4
|
export const commitinfo = {
|
|
5
5
|
name: '@serve.zone/remoteingress',
|
|
6
|
-
version: '
|
|
7
|
-
description: '
|
|
6
|
+
version: '3.0.0',
|
|
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
|
}
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
import * as plugins from './plugins.js';
|
|
2
|
+
import { EventEmitter } from 'events';
|
|
3
|
+
|
|
4
|
+
// Command map for the edge side of remoteingress-bin
|
|
5
|
+
type TEdgeCommands = {
|
|
6
|
+
ping: {
|
|
7
|
+
params: Record<string, never>;
|
|
8
|
+
result: { pong: boolean };
|
|
9
|
+
};
|
|
10
|
+
startEdge: {
|
|
11
|
+
params: {
|
|
12
|
+
hubHost: string;
|
|
13
|
+
hubPort: number;
|
|
14
|
+
edgeId: string;
|
|
15
|
+
secret: string;
|
|
16
|
+
listenPorts: number[];
|
|
17
|
+
stunIntervalSecs?: number;
|
|
18
|
+
};
|
|
19
|
+
result: { started: boolean };
|
|
20
|
+
};
|
|
21
|
+
stopEdge: {
|
|
22
|
+
params: Record<string, never>;
|
|
23
|
+
result: { stopped: boolean; wasRunning?: boolean };
|
|
24
|
+
};
|
|
25
|
+
getEdgeStatus: {
|
|
26
|
+
params: Record<string, never>;
|
|
27
|
+
result: {
|
|
28
|
+
running: boolean;
|
|
29
|
+
connected: boolean;
|
|
30
|
+
publicIp: string | null;
|
|
31
|
+
activeStreams: number;
|
|
32
|
+
listenPorts: number[];
|
|
33
|
+
};
|
|
34
|
+
};
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
export interface IEdgeConfig {
|
|
38
|
+
hubHost: string;
|
|
39
|
+
hubPort?: number;
|
|
40
|
+
edgeId: string;
|
|
41
|
+
secret: string;
|
|
42
|
+
listenPorts: number[];
|
|
43
|
+
stunIntervalSecs?: number;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
export class RemoteIngressEdge extends EventEmitter {
|
|
47
|
+
private bridge: InstanceType<typeof plugins.smartrust.RustBridge<TEdgeCommands>>;
|
|
48
|
+
private started = false;
|
|
49
|
+
|
|
50
|
+
constructor() {
|
|
51
|
+
super();
|
|
52
|
+
|
|
53
|
+
const packageDir = plugins.path.resolve(
|
|
54
|
+
plugins.path.dirname(new URL(import.meta.url).pathname),
|
|
55
|
+
'..',
|
|
56
|
+
);
|
|
57
|
+
|
|
58
|
+
this.bridge = new plugins.smartrust.RustBridge<TEdgeCommands>({
|
|
59
|
+
binaryName: 'remoteingress-bin',
|
|
60
|
+
cliArgs: ['--management'],
|
|
61
|
+
requestTimeoutMs: 30_000,
|
|
62
|
+
readyTimeoutMs: 10_000,
|
|
63
|
+
localPaths: [
|
|
64
|
+
plugins.path.join(packageDir, 'dist_rust'),
|
|
65
|
+
plugins.path.join(packageDir, 'rust', 'target', 'release'),
|
|
66
|
+
plugins.path.join(packageDir, 'rust', 'target', 'debug'),
|
|
67
|
+
],
|
|
68
|
+
searchSystemPath: false,
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
// Forward events from Rust binary
|
|
72
|
+
this.bridge.on('management:tunnelConnected', () => {
|
|
73
|
+
this.emit('tunnelConnected');
|
|
74
|
+
});
|
|
75
|
+
this.bridge.on('management:tunnelDisconnected', () => {
|
|
76
|
+
this.emit('tunnelDisconnected');
|
|
77
|
+
});
|
|
78
|
+
this.bridge.on('management:publicIpDiscovered', (data: { ip: string }) => {
|
|
79
|
+
this.emit('publicIpDiscovered', data);
|
|
80
|
+
});
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
/**
|
|
84
|
+
* Start the edge — spawns the Rust binary and connects to the hub.
|
|
85
|
+
*/
|
|
86
|
+
public async start(config: IEdgeConfig): Promise<void> {
|
|
87
|
+
const spawned = await this.bridge.spawn();
|
|
88
|
+
if (!spawned) {
|
|
89
|
+
throw new Error('Failed to spawn remoteingress-bin');
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
await this.bridge.sendCommand('startEdge', {
|
|
93
|
+
hubHost: config.hubHost,
|
|
94
|
+
hubPort: config.hubPort ?? 8443,
|
|
95
|
+
edgeId: config.edgeId,
|
|
96
|
+
secret: config.secret,
|
|
97
|
+
listenPorts: config.listenPorts,
|
|
98
|
+
stunIntervalSecs: config.stunIntervalSecs,
|
|
99
|
+
});
|
|
100
|
+
|
|
101
|
+
this.started = true;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
/**
|
|
105
|
+
* Stop the edge and kill the Rust process.
|
|
106
|
+
*/
|
|
107
|
+
public async stop(): Promise<void> {
|
|
108
|
+
if (this.started) {
|
|
109
|
+
try {
|
|
110
|
+
await this.bridge.sendCommand('stopEdge', {} as Record<string, never>);
|
|
111
|
+
} catch {
|
|
112
|
+
// Process may already be dead
|
|
113
|
+
}
|
|
114
|
+
this.bridge.kill();
|
|
115
|
+
this.started = false;
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
/**
|
|
120
|
+
* Get the current edge status.
|
|
121
|
+
*/
|
|
122
|
+
public async getStatus() {
|
|
123
|
+
return this.bridge.sendCommand('getEdgeStatus', {} as Record<string, never>);
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
/**
|
|
127
|
+
* Check if the bridge is running.
|
|
128
|
+
*/
|
|
129
|
+
public get running(): boolean {
|
|
130
|
+
return this.bridge.running;
|
|
131
|
+
}
|
|
132
|
+
}
|
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
import * as plugins from './plugins.js';
|
|
2
|
+
import { EventEmitter } from 'events';
|
|
3
|
+
|
|
4
|
+
// Command map for the hub side of remoteingress-bin
|
|
5
|
+
type THubCommands = {
|
|
6
|
+
ping: {
|
|
7
|
+
params: Record<string, never>;
|
|
8
|
+
result: { pong: boolean };
|
|
9
|
+
};
|
|
10
|
+
startHub: {
|
|
11
|
+
params: {
|
|
12
|
+
tunnelPort: number;
|
|
13
|
+
targetHost?: string;
|
|
14
|
+
};
|
|
15
|
+
result: { started: boolean };
|
|
16
|
+
};
|
|
17
|
+
stopHub: {
|
|
18
|
+
params: Record<string, never>;
|
|
19
|
+
result: { stopped: boolean; wasRunning?: boolean };
|
|
20
|
+
};
|
|
21
|
+
updateAllowedEdges: {
|
|
22
|
+
params: {
|
|
23
|
+
edges: Array<{ id: string; secret: string }>;
|
|
24
|
+
};
|
|
25
|
+
result: { updated: boolean };
|
|
26
|
+
};
|
|
27
|
+
getHubStatus: {
|
|
28
|
+
params: Record<string, never>;
|
|
29
|
+
result: {
|
|
30
|
+
running: boolean;
|
|
31
|
+
tunnelPort: number;
|
|
32
|
+
connectedEdges: Array<{
|
|
33
|
+
edgeId: string;
|
|
34
|
+
connectedAt: number;
|
|
35
|
+
activeStreams: number;
|
|
36
|
+
}>;
|
|
37
|
+
};
|
|
38
|
+
};
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
export interface IHubConfig {
|
|
42
|
+
tunnelPort?: number;
|
|
43
|
+
targetHost?: string;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
export class RemoteIngressHub extends EventEmitter {
|
|
47
|
+
private bridge: InstanceType<typeof plugins.smartrust.RustBridge<THubCommands>>;
|
|
48
|
+
private started = false;
|
|
49
|
+
|
|
50
|
+
constructor() {
|
|
51
|
+
super();
|
|
52
|
+
|
|
53
|
+
const packageDir = plugins.path.resolve(
|
|
54
|
+
plugins.path.dirname(new URL(import.meta.url).pathname),
|
|
55
|
+
'..',
|
|
56
|
+
);
|
|
57
|
+
|
|
58
|
+
this.bridge = new plugins.smartrust.RustBridge<THubCommands>({
|
|
59
|
+
binaryName: 'remoteingress-bin',
|
|
60
|
+
cliArgs: ['--management'],
|
|
61
|
+
requestTimeoutMs: 30_000,
|
|
62
|
+
readyTimeoutMs: 10_000,
|
|
63
|
+
localPaths: [
|
|
64
|
+
plugins.path.join(packageDir, 'dist_rust'),
|
|
65
|
+
plugins.path.join(packageDir, 'rust', 'target', 'release'),
|
|
66
|
+
plugins.path.join(packageDir, 'rust', 'target', 'debug'),
|
|
67
|
+
],
|
|
68
|
+
searchSystemPath: false,
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
// Forward events from Rust binary
|
|
72
|
+
this.bridge.on('management:edgeConnected', (data: { edgeId: string }) => {
|
|
73
|
+
this.emit('edgeConnected', data);
|
|
74
|
+
});
|
|
75
|
+
this.bridge.on('management:edgeDisconnected', (data: { edgeId: string }) => {
|
|
76
|
+
this.emit('edgeDisconnected', data);
|
|
77
|
+
});
|
|
78
|
+
this.bridge.on('management:streamOpened', (data: { edgeId: string; streamId: number }) => {
|
|
79
|
+
this.emit('streamOpened', data);
|
|
80
|
+
});
|
|
81
|
+
this.bridge.on('management:streamClosed', (data: { edgeId: string; streamId: number }) => {
|
|
82
|
+
this.emit('streamClosed', data);
|
|
83
|
+
});
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
/**
|
|
87
|
+
* Start the hub — spawns the Rust binary and starts the tunnel server.
|
|
88
|
+
*/
|
|
89
|
+
public async start(config: IHubConfig = {}): Promise<void> {
|
|
90
|
+
const spawned = await this.bridge.spawn();
|
|
91
|
+
if (!spawned) {
|
|
92
|
+
throw new Error('Failed to spawn remoteingress-bin');
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
await this.bridge.sendCommand('startHub', {
|
|
96
|
+
tunnelPort: config.tunnelPort ?? 8443,
|
|
97
|
+
targetHost: config.targetHost ?? '127.0.0.1',
|
|
98
|
+
});
|
|
99
|
+
|
|
100
|
+
this.started = true;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
/**
|
|
104
|
+
* Stop the hub and kill the Rust process.
|
|
105
|
+
*/
|
|
106
|
+
public async stop(): Promise<void> {
|
|
107
|
+
if (this.started) {
|
|
108
|
+
try {
|
|
109
|
+
await this.bridge.sendCommand('stopHub', {} as Record<string, never>);
|
|
110
|
+
} catch {
|
|
111
|
+
// Process may already be dead
|
|
112
|
+
}
|
|
113
|
+
this.bridge.kill();
|
|
114
|
+
this.started = false;
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
/**
|
|
119
|
+
* Update the list of allowed edges that can connect to this hub.
|
|
120
|
+
*/
|
|
121
|
+
public async updateAllowedEdges(edges: Array<{ id: string; secret: string }>): Promise<void> {
|
|
122
|
+
await this.bridge.sendCommand('updateAllowedEdges', { edges });
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
/**
|
|
126
|
+
* Get the current hub status.
|
|
127
|
+
*/
|
|
128
|
+
public async getStatus() {
|
|
129
|
+
return this.bridge.sendCommand('getHubStatus', {} as Record<string, never>);
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
/**
|
|
133
|
+
* Check if the bridge is running.
|
|
134
|
+
*/
|
|
135
|
+
public get running(): boolean {
|
|
136
|
+
return this.bridge.running;
|
|
137
|
+
}
|
|
138
|
+
}
|
package/ts/index.ts
CHANGED
|
@@ -1,14 +1,2 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
import { ConnectorPublic } from './connector.public.js';
|
|
4
|
-
import { ConnectorPrivate } from './connector.private.js';
|
|
5
|
-
|
|
6
|
-
export {
|
|
7
|
-
ConnectorPublic,
|
|
8
|
-
ConnectorPrivate
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
export const runCli = async () => {
|
|
12
|
-
const qenv = new plugins.qenv.Qenv();
|
|
13
|
-
const mode = await qenv.getEnvVarOnDemand('MODE');
|
|
14
|
-
}
|
|
1
|
+
export * from './classes.remoteingresshub.js';
|
|
2
|
+
export * from './classes.remoteingressedge.js';
|
package/ts/plugins.ts
CHANGED
|
@@ -1,15 +1,7 @@
|
|
|
1
1
|
// node native scope
|
|
2
|
-
import * as
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
export {
|
|
6
|
-
tls,
|
|
7
|
-
fs,
|
|
8
|
-
}
|
|
2
|
+
import * as path from 'path';
|
|
3
|
+
export { path };
|
|
9
4
|
|
|
10
5
|
// @push.rocks scope
|
|
11
|
-
import * as
|
|
12
|
-
|
|
13
|
-
export {
|
|
14
|
-
qenv,
|
|
15
|
-
}
|
|
6
|
+
import * as smartrust from '@push.rocks/smartrust';
|
|
7
|
+
export { smartrust };
|
|
@@ -1,31 +0,0 @@
|
|
|
1
|
-
import * as plugins from './plugins.js';
|
|
2
|
-
export class ConnectorPrivate {
|
|
3
|
-
constructor(targetHost, targetPort = 4000) {
|
|
4
|
-
this.targetHost = targetHost;
|
|
5
|
-
this.targetPort = targetPort;
|
|
6
|
-
this.connectToPublicRemoteConnector();
|
|
7
|
-
}
|
|
8
|
-
connectToPublicRemoteConnector() {
|
|
9
|
-
const options = {
|
|
10
|
-
// Include CA certificate if necessary, for example:
|
|
11
|
-
// ca: fs.readFileSync('path/to/ca.pem'),
|
|
12
|
-
rejectUnauthorized: true // Only set this to true if you are sure about the server's certificate
|
|
13
|
-
};
|
|
14
|
-
const tunnel = plugins.tls.connect(this.targetPort, options, () => {
|
|
15
|
-
console.log('Connected to PublicRemoteConnector on port 4000');
|
|
16
|
-
});
|
|
17
|
-
tunnel.on('data', (data) => {
|
|
18
|
-
const targetConnection = plugins.tls.connect({
|
|
19
|
-
host: this.targetHost,
|
|
20
|
-
port: this.targetPort,
|
|
21
|
-
// Include necessary options for the target connection
|
|
22
|
-
}, () => {
|
|
23
|
-
targetConnection.write(data);
|
|
24
|
-
});
|
|
25
|
-
targetConnection.on('data', (backData) => {
|
|
26
|
-
tunnel.write(backData); // Send data back through the tunnel
|
|
27
|
-
});
|
|
28
|
-
});
|
|
29
|
-
}
|
|
30
|
-
}
|
|
31
|
-
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY29ubmVjdG9yLnByaXZhdGUuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi90cy9jb25uZWN0b3IucHJpdmF0ZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEtBQUssT0FBTyxNQUFNLGNBQWMsQ0FBQztBQUV4QyxNQUFNLE9BQU8sZ0JBQWdCO0lBSTNCLFlBQVksVUFBa0IsRUFBRSxhQUFxQixJQUFJO1FBQ3ZELElBQUksQ0FBQyxVQUFVLEdBQUcsVUFBVSxDQUFDO1FBQzdCLElBQUksQ0FBQyxVQUFVLEdBQUcsVUFBVSxDQUFDO1FBQzdCLElBQUksQ0FBQyw4QkFBOEIsRUFBRSxDQUFDO0lBQ3hDLENBQUM7SUFFTyw4QkFBOEI7UUFDcEMsTUFBTSxPQUFPLEdBQUc7WUFDZCxvREFBb0Q7WUFDcEQseUNBQXlDO1lBQ3pDLGtCQUFrQixFQUFFLElBQUksQ0FBQyx1RUFBdUU7U0FDakcsQ0FBQztRQUVGLE1BQU0sTUFBTSxHQUFHLE9BQU8sQ0FBQyxHQUFHLENBQUMsT0FBTyxDQUFDLElBQUksQ0FBQyxVQUFVLEVBQUUsT0FBTyxFQUFFLEdBQUcsRUFBRTtZQUNoRSxPQUFPLENBQUMsR0FBRyxDQUFDLGlEQUFpRCxDQUFDLENBQUM7UUFDakUsQ0FBQyxDQUFDLENBQUM7UUFFSCxNQUFNLENBQUMsRUFBRSxDQUFDLE1BQU0sRUFBRSxDQUFDLElBQVksRUFBRSxFQUFFO1lBQ2pDLE1BQU0sZ0JBQWdCLEdBQUcsT0FBTyxDQUFDLEdBQUcsQ0FBQyxPQUFPLENBQUM7Z0JBQzNDLElBQUksRUFBRSxJQUFJLENBQUMsVUFBVTtnQkFDckIsSUFBSSxFQUFFLElBQUksQ0FBQyxVQUFVO2dCQUNyQixzREFBc0Q7YUFDdkQsRUFBRSxHQUFHLEVBQUU7Z0JBQ04sZ0JBQWdCLENBQUMsS0FBSyxDQUFDLElBQUksQ0FBQyxDQUFDO1lBQy9CLENBQUMsQ0FBQyxDQUFDO1lBRUgsZ0JBQWdCLENBQUMsRUFBRSxDQUFDLE1BQU0sRUFBRSxDQUFDLFFBQWdCLEVBQUUsRUFBRTtnQkFDL0MsTUFBTSxDQUFDLEtBQUssQ0FBQyxRQUFRLENBQUMsQ0FBQyxDQUFDLG9DQUFvQztZQUM5RCxDQUFDLENBQUMsQ0FBQztRQUNMLENBQUMsQ0FBQyxDQUFDO0lBQ0wsQ0FBQztDQUNGIn0=
|
|
@@ -1,40 +0,0 @@
|
|
|
1
|
-
import * as plugins from './plugins.js';
|
|
2
|
-
export class ConnectorPublic {
|
|
3
|
-
constructor() {
|
|
4
|
-
this.tunnel = null;
|
|
5
|
-
this.createTunnel();
|
|
6
|
-
this.listenOnPorts();
|
|
7
|
-
}
|
|
8
|
-
createTunnel() {
|
|
9
|
-
const options = {
|
|
10
|
-
key: plugins.fs.readFileSync('path/to/key.pem'),
|
|
11
|
-
cert: plugins.fs.readFileSync('path/to/cert.pem'),
|
|
12
|
-
};
|
|
13
|
-
const server = plugins.tls.createServer(options, (socket) => {
|
|
14
|
-
this.tunnel = socket;
|
|
15
|
-
console.log('Tunnel established with LocalConnector');
|
|
16
|
-
});
|
|
17
|
-
server.listen(4000, () => {
|
|
18
|
-
console.log('PublicRemoteConnector listening for tunnel on port 4000');
|
|
19
|
-
});
|
|
20
|
-
}
|
|
21
|
-
listenOnPorts() {
|
|
22
|
-
// Example for port 80, adapt for port 443 similarly
|
|
23
|
-
// Note: TLS for the initial connection might not apply directly for HTTP/HTTPS traffic without additional setup
|
|
24
|
-
const options = {
|
|
25
|
-
key: plugins.fs.readFileSync('path/to/key.pem'),
|
|
26
|
-
cert: plugins.fs.readFileSync('path/to/cert.pem'),
|
|
27
|
-
};
|
|
28
|
-
plugins.tls.createServer(options, (socket) => {
|
|
29
|
-
console.log('Received connection, tunneling to LocalConnector');
|
|
30
|
-
if (this.tunnel) {
|
|
31
|
-
socket.pipe(this.tunnel).pipe(socket);
|
|
32
|
-
}
|
|
33
|
-
else {
|
|
34
|
-
console.log('Tunnel to LocalConnector not established');
|
|
35
|
-
socket.end();
|
|
36
|
-
}
|
|
37
|
-
}).listen(80); // Repeat this block for any other ports you wish to listen on
|
|
38
|
-
}
|
|
39
|
-
}
|
|
40
|
-
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY29ubmVjdG9yLnB1YmxpYy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uL3RzL2Nvbm5lY3Rvci5wdWJsaWMudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxLQUFLLE9BQU8sTUFBTSxjQUFjLENBQUM7QUFFeEMsTUFBTSxPQUFPLGVBQWU7SUFHMUI7UUFGUSxXQUFNLEdBQWlDLElBQUksQ0FBQztRQUdsRCxJQUFJLENBQUMsWUFBWSxFQUFFLENBQUM7UUFDcEIsSUFBSSxDQUFDLGFBQWEsRUFBRSxDQUFDO0lBQ3ZCLENBQUM7SUFFTyxZQUFZO1FBQ2xCLE1BQU0sT0FBTyxHQUFHO1lBQ2QsR0FBRyxFQUFFLE9BQU8sQ0FBQyxFQUFFLENBQUMsWUFBWSxDQUFDLGlCQUFpQixDQUFDO1lBQy9DLElBQUksRUFBRSxPQUFPLENBQUMsRUFBRSxDQUFDLFlBQVksQ0FBQyxrQkFBa0IsQ0FBQztTQUNsRCxDQUFDO1FBRUYsTUFBTSxNQUFNLEdBQUcsT0FBTyxDQUFDLEdBQUcsQ0FBQyxZQUFZLENBQUMsT0FBTyxFQUFFLENBQUMsTUFBNkIsRUFBRSxFQUFFO1lBQ2pGLElBQUksQ0FBQyxNQUFNLEdBQUcsTUFBTSxDQUFDO1lBQ3JCLE9BQU8sQ0FBQyxHQUFHLENBQUMsd0NBQXdDLENBQUMsQ0FBQztRQUN4RCxDQUFDLENBQUMsQ0FBQztRQUVILE1BQU0sQ0FBQyxNQUFNLENBQUMsSUFBSSxFQUFFLEdBQUcsRUFBRTtZQUN2QixPQUFPLENBQUMsR0FBRyxDQUFDLHlEQUF5RCxDQUFDLENBQUM7UUFDekUsQ0FBQyxDQUFDLENBQUM7SUFDTCxDQUFDO0lBRU8sYUFBYTtRQUNuQixvREFBb0Q7UUFDcEQsZ0hBQWdIO1FBQ2hILE1BQU0sT0FBTyxHQUFHO1lBQ2QsR0FBRyxFQUFFLE9BQU8sQ0FBQyxFQUFFLENBQUMsWUFBWSxDQUFDLGlCQUFpQixDQUFDO1lBQy9DLElBQUksRUFBRSxPQUFPLENBQUMsRUFBRSxDQUFDLFlBQVksQ0FBQyxrQkFBa0IsQ0FBQztTQUNsRCxDQUFDO1FBRUYsT0FBTyxDQUFDLEdBQUcsQ0FBQyxZQUFZLENBQUMsT0FBTyxFQUFFLENBQUMsTUFBNkIsRUFBRSxFQUFFO1lBQ2xFLE9BQU8sQ0FBQyxHQUFHLENBQUMsa0RBQWtELENBQUMsQ0FBQztZQUNoRSxJQUFJLElBQUksQ0FBQyxNQUFNLEVBQUUsQ0FBQztnQkFDaEIsTUFBTSxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsTUFBTSxDQUFDLENBQUMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxDQUFDO1lBQ3hDLENBQUM7aUJBQU0sQ0FBQztnQkFDTixPQUFPLENBQUMsR0FBRyxDQUFDLDBDQUEwQyxDQUFDLENBQUM7Z0JBQ3hELE1BQU0sQ0FBQyxHQUFHLEVBQUUsQ0FBQztZQUNmLENBQUM7UUFDSCxDQUFDLENBQUMsQ0FBQyxNQUFNLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyw4REFBOEQ7SUFDL0UsQ0FBQztDQUNGIn0=
|
package/ts/connector.private.ts
DELETED
|
@@ -1,38 +0,0 @@
|
|
|
1
|
-
import * as plugins from './plugins.js';
|
|
2
|
-
|
|
3
|
-
export class ConnectorPrivate {
|
|
4
|
-
private targetHost: string;
|
|
5
|
-
private targetPort: number;
|
|
6
|
-
|
|
7
|
-
constructor(targetHost: string, targetPort: number = 4000) {
|
|
8
|
-
this.targetHost = targetHost;
|
|
9
|
-
this.targetPort = targetPort;
|
|
10
|
-
this.connectToPublicRemoteConnector();
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
private connectToPublicRemoteConnector(): void {
|
|
14
|
-
const options = {
|
|
15
|
-
// Include CA certificate if necessary, for example:
|
|
16
|
-
// ca: fs.readFileSync('path/to/ca.pem'),
|
|
17
|
-
rejectUnauthorized: true // Only set this to true if you are sure about the server's certificate
|
|
18
|
-
};
|
|
19
|
-
|
|
20
|
-
const tunnel = plugins.tls.connect(this.targetPort, options, () => {
|
|
21
|
-
console.log('Connected to PublicRemoteConnector on port 4000');
|
|
22
|
-
});
|
|
23
|
-
|
|
24
|
-
tunnel.on('data', (data: Buffer) => {
|
|
25
|
-
const targetConnection = plugins.tls.connect({
|
|
26
|
-
host: this.targetHost,
|
|
27
|
-
port: this.targetPort,
|
|
28
|
-
// Include necessary options for the target connection
|
|
29
|
-
}, () => {
|
|
30
|
-
targetConnection.write(data);
|
|
31
|
-
});
|
|
32
|
-
|
|
33
|
-
targetConnection.on('data', (backData: Buffer) => {
|
|
34
|
-
tunnel.write(backData); // Send data back through the tunnel
|
|
35
|
-
});
|
|
36
|
-
});
|
|
37
|
-
}
|
|
38
|
-
}
|
package/ts/connector.public.ts
DELETED
|
@@ -1,45 +0,0 @@
|
|
|
1
|
-
import * as plugins from './plugins.js';
|
|
2
|
-
|
|
3
|
-
export class ConnectorPublic {
|
|
4
|
-
private tunnel: plugins.tls.TLSSocket | null = null;
|
|
5
|
-
|
|
6
|
-
constructor() {
|
|
7
|
-
this.createTunnel();
|
|
8
|
-
this.listenOnPorts();
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
private createTunnel(): void {
|
|
12
|
-
const options = {
|
|
13
|
-
key: plugins.fs.readFileSync('path/to/key.pem'),
|
|
14
|
-
cert: plugins.fs.readFileSync('path/to/cert.pem'),
|
|
15
|
-
};
|
|
16
|
-
|
|
17
|
-
const server = plugins.tls.createServer(options, (socket: plugins.tls.TLSSocket) => {
|
|
18
|
-
this.tunnel = socket;
|
|
19
|
-
console.log('Tunnel established with LocalConnector');
|
|
20
|
-
});
|
|
21
|
-
|
|
22
|
-
server.listen(4000, () => {
|
|
23
|
-
console.log('PublicRemoteConnector listening for tunnel on port 4000');
|
|
24
|
-
});
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
private listenOnPorts(): void {
|
|
28
|
-
// Example for port 80, adapt for port 443 similarly
|
|
29
|
-
// Note: TLS for the initial connection might not apply directly for HTTP/HTTPS traffic without additional setup
|
|
30
|
-
const options = {
|
|
31
|
-
key: plugins.fs.readFileSync('path/to/key.pem'),
|
|
32
|
-
cert: plugins.fs.readFileSync('path/to/cert.pem'),
|
|
33
|
-
};
|
|
34
|
-
|
|
35
|
-
plugins.tls.createServer(options, (socket: plugins.tls.TLSSocket) => {
|
|
36
|
-
console.log('Received connection, tunneling to LocalConnector');
|
|
37
|
-
if (this.tunnel) {
|
|
38
|
-
socket.pipe(this.tunnel).pipe(socket);
|
|
39
|
-
} else {
|
|
40
|
-
console.log('Tunnel to LocalConnector not established');
|
|
41
|
-
socket.end();
|
|
42
|
-
}
|
|
43
|
-
}).listen(80); // Repeat this block for any other ports you wish to listen on
|
|
44
|
-
}
|
|
45
|
-
}
|