@push.rocks/smartvpn 1.0.3
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/smartvpn_daemon_linux_amd64 +0 -0
- package/dist_rust/smartvpn_daemon_linux_arm64 +0 -0
- package/dist_ts/00_commitinfo_data.d.ts +8 -0
- package/dist_ts/00_commitinfo_data.js +9 -0
- package/dist_ts/index.d.ts +6 -0
- package/dist_ts/index.js +7 -0
- package/dist_ts/smartvpn.classes.vpnbridge.d.ts +34 -0
- package/dist_ts/smartvpn.classes.vpnbridge.js +123 -0
- package/dist_ts/smartvpn.classes.vpnclient.d.ts +40 -0
- package/dist_ts/smartvpn.classes.vpnclient.js +69 -0
- package/dist_ts/smartvpn.classes.vpnconfig.d.ts +30 -0
- package/dist_ts/smartvpn.classes.vpnconfig.js +98 -0
- package/dist_ts/smartvpn.classes.vpninstaller.d.ts +37 -0
- package/dist_ts/smartvpn.classes.vpninstaller.js +105 -0
- package/dist_ts/smartvpn.classes.vpnserver.d.ts +46 -0
- package/dist_ts/smartvpn.classes.vpnserver.js +85 -0
- package/dist_ts/smartvpn.interfaces.d.ts +167 -0
- package/dist_ts/smartvpn.interfaces.js +5 -0
- package/dist_ts/smartvpn.paths.d.ts +1 -0
- package/dist_ts/smartvpn.paths.js +3 -0
- package/dist_ts/smartvpn.plugins.d.ts +9 -0
- package/dist_ts/smartvpn.plugins.js +12 -0
- package/license.md +21 -0
- package/package.json +52 -0
- package/readme.md +410 -0
- package/ts/00_commitinfo_data.ts +8 -0
- package/ts/index.ts +6 -0
- package/ts/smartvpn.classes.vpnbridge.ts +152 -0
- package/ts/smartvpn.classes.vpnclient.ts +87 -0
- package/ts/smartvpn.classes.vpnconfig.ts +104 -0
- package/ts/smartvpn.classes.vpninstaller.ts +126 -0
- package/ts/smartvpn.classes.vpnserver.ts +107 -0
- package/ts/smartvpn.interfaces.ts +166 -0
- package/ts/smartvpn.paths.ts +6 -0
- package/ts/smartvpn.plugins.ts +14 -0
|
Binary file
|
|
Binary file
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* autocreated commitinfo by @push.rocks/commitinfo
|
|
3
|
+
*/
|
|
4
|
+
export const commitinfo = {
|
|
5
|
+
name: '@push.rocks/smartvpn',
|
|
6
|
+
version: '1.0.3',
|
|
7
|
+
description: 'A VPN solution with TypeScript control plane and Rust data plane daemon'
|
|
8
|
+
};
|
|
9
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiMDBfY29tbWl0aW5mb19kYXRhLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vdHMvMDBfY29tbWl0aW5mb19kYXRhLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBOztHQUVHO0FBQ0gsTUFBTSxDQUFDLE1BQU0sVUFBVSxHQUFHO0lBQ3hCLElBQUksRUFBRSxzQkFBc0I7SUFDNUIsT0FBTyxFQUFFLE9BQU87SUFDaEIsV0FBVyxFQUFFLHlFQUF5RTtDQUN2RixDQUFBIn0=
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
export * from './smartvpn.interfaces.js';
|
|
2
|
+
export { VpnBridge } from './smartvpn.classes.vpnbridge.js';
|
|
3
|
+
export { VpnClient } from './smartvpn.classes.vpnclient.js';
|
|
4
|
+
export { VpnServer } from './smartvpn.classes.vpnserver.js';
|
|
5
|
+
export { VpnConfig } from './smartvpn.classes.vpnconfig.js';
|
|
6
|
+
export { VpnInstaller } from './smartvpn.classes.vpninstaller.js';
|
package/dist_ts/index.js
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export * from './smartvpn.interfaces.js';
|
|
2
|
+
export { VpnBridge } from './smartvpn.classes.vpnbridge.js';
|
|
3
|
+
export { VpnClient } from './smartvpn.classes.vpnclient.js';
|
|
4
|
+
export { VpnServer } from './smartvpn.classes.vpnserver.js';
|
|
5
|
+
export { VpnConfig } from './smartvpn.classes.vpnconfig.js';
|
|
6
|
+
export { VpnInstaller } from './smartvpn.classes.vpninstaller.js';
|
|
7
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi90cy9pbmRleC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxjQUFjLDBCQUEwQixDQUFDO0FBQ3pDLE9BQU8sRUFBRSxTQUFTLEVBQUUsTUFBTSxpQ0FBaUMsQ0FBQztBQUM1RCxPQUFPLEVBQUUsU0FBUyxFQUFFLE1BQU0saUNBQWlDLENBQUM7QUFDNUQsT0FBTyxFQUFFLFNBQVMsRUFBRSxNQUFNLGlDQUFpQyxDQUFDO0FBQzVELE9BQU8sRUFBRSxTQUFTLEVBQUUsTUFBTSxpQ0FBaUMsQ0FBQztBQUM1RCxPQUFPLEVBQUUsWUFBWSxFQUFFLE1BQU0sb0NBQW9DLENBQUMifQ==
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import * as plugins from './smartvpn.plugins.js';
|
|
2
|
+
import type { TVpnTransportOptions } from './smartvpn.interfaces.js';
|
|
3
|
+
import type { TCommandMap } from '@push.rocks/smartrust';
|
|
4
|
+
/**
|
|
5
|
+
* Shared bridge wrapper around smartrust RustBridge.
|
|
6
|
+
* Supports stdio mode (dev: spawn child process) and socket mode (production: connect to running daemon).
|
|
7
|
+
*/
|
|
8
|
+
export declare class VpnBridge<TCommands extends TCommandMap> extends plugins.events.EventEmitter {
|
|
9
|
+
private bridge;
|
|
10
|
+
private transportOptions;
|
|
11
|
+
private mode;
|
|
12
|
+
constructor(options: {
|
|
13
|
+
transport: TVpnTransportOptions;
|
|
14
|
+
mode: 'client' | 'server';
|
|
15
|
+
binaryName?: string;
|
|
16
|
+
});
|
|
17
|
+
/**
|
|
18
|
+
* Start the bridge: spawn in stdio mode or connect in socket mode.
|
|
19
|
+
*/
|
|
20
|
+
start(): Promise<boolean>;
|
|
21
|
+
/**
|
|
22
|
+
* Stop the bridge. In socket mode, closes the socket (daemon stays alive).
|
|
23
|
+
* In stdio mode, kills the child process.
|
|
24
|
+
*/
|
|
25
|
+
stop(): void;
|
|
26
|
+
/**
|
|
27
|
+
* Send a typed command to the daemon.
|
|
28
|
+
*/
|
|
29
|
+
sendCommand<K extends string & keyof TCommands>(method: K, params: TCommands[K]['params']): Promise<TCommands[K]['result']>;
|
|
30
|
+
/**
|
|
31
|
+
* Whether the bridge is currently running/connected.
|
|
32
|
+
*/
|
|
33
|
+
get running(): boolean;
|
|
34
|
+
}
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
import * as plugins from './smartvpn.plugins.js';
|
|
2
|
+
import * as paths from './smartvpn.paths.js';
|
|
3
|
+
/**
|
|
4
|
+
* Get the package root directory.
|
|
5
|
+
*/
|
|
6
|
+
function getPackageRoot() {
|
|
7
|
+
const thisDir = plugins.path.dirname(plugins.url.fileURLToPath(import.meta.url));
|
|
8
|
+
return plugins.path.resolve(thisDir, '..');
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* Map Node.js platform/arch to tsrust's platform suffix.
|
|
12
|
+
*/
|
|
13
|
+
function getTsrustPlatformSuffix() {
|
|
14
|
+
const archMap = { x64: 'amd64', arm64: 'arm64' };
|
|
15
|
+
const osMap = { linux: 'linux', darwin: 'macos' };
|
|
16
|
+
const os = osMap[process.platform];
|
|
17
|
+
const arch = archMap[process.arch];
|
|
18
|
+
if (os && arch) {
|
|
19
|
+
return `${os}_${arch}`;
|
|
20
|
+
}
|
|
21
|
+
return null;
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Build local search paths for the smartvpn daemon binary.
|
|
25
|
+
*/
|
|
26
|
+
function buildLocalPaths(binaryName) {
|
|
27
|
+
const packageRoot = getPackageRoot();
|
|
28
|
+
const suffix = getTsrustPlatformSuffix();
|
|
29
|
+
const paths = [];
|
|
30
|
+
// dist_rust/ (tsrust cross-compiled output)
|
|
31
|
+
if (suffix) {
|
|
32
|
+
paths.push(plugins.path.join(packageRoot, 'dist_rust', `${binaryName}_${suffix}`));
|
|
33
|
+
}
|
|
34
|
+
paths.push(plugins.path.join(packageRoot, 'dist_rust', binaryName));
|
|
35
|
+
// Local dev build paths
|
|
36
|
+
paths.push(plugins.path.resolve(process.cwd(), 'rust', 'target', 'release', binaryName));
|
|
37
|
+
paths.push(plugins.path.resolve(process.cwd(), 'rust', 'target', 'debug', binaryName));
|
|
38
|
+
return paths;
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Shared bridge wrapper around smartrust RustBridge.
|
|
42
|
+
* Supports stdio mode (dev: spawn child process) and socket mode (production: connect to running daemon).
|
|
43
|
+
*/
|
|
44
|
+
export class VpnBridge extends plugins.events.EventEmitter {
|
|
45
|
+
constructor(options) {
|
|
46
|
+
super();
|
|
47
|
+
const binaryName = options.binaryName || 'smartvpn_daemon';
|
|
48
|
+
this.transportOptions = options.transport;
|
|
49
|
+
this.mode = options.mode;
|
|
50
|
+
this.bridge = new plugins.smartrust.RustBridge({
|
|
51
|
+
binaryName,
|
|
52
|
+
envVarName: 'SMARTVPN_RUST_BINARY',
|
|
53
|
+
platformPackagePrefix: '@push.rocks/smartvpn',
|
|
54
|
+
localPaths: buildLocalPaths(binaryName),
|
|
55
|
+
cliArgs: ['--management', '--mode', this.mode],
|
|
56
|
+
maxPayloadSize: 10 * 1024 * 1024, // 10 MB
|
|
57
|
+
});
|
|
58
|
+
// Forward events from inner bridge
|
|
59
|
+
this.bridge.on('exit', (code, signal) => {
|
|
60
|
+
this.emit('exit', code, signal);
|
|
61
|
+
});
|
|
62
|
+
this.bridge.on('reconnected', () => {
|
|
63
|
+
this.emit('reconnected');
|
|
64
|
+
});
|
|
65
|
+
// Forward management events from the daemon
|
|
66
|
+
// smartrust emits 'management:<eventName>' for unsolicited events
|
|
67
|
+
this.bridge.on('management:status', (data) => {
|
|
68
|
+
this.emit('status', data);
|
|
69
|
+
});
|
|
70
|
+
this.bridge.on('management:error', (data) => {
|
|
71
|
+
this.emit('error', data);
|
|
72
|
+
});
|
|
73
|
+
this.bridge.on('management:client-connected', (data) => {
|
|
74
|
+
this.emit('client-connected', data);
|
|
75
|
+
});
|
|
76
|
+
this.bridge.on('management:client-disconnected', (data) => {
|
|
77
|
+
this.emit('client-disconnected', data);
|
|
78
|
+
});
|
|
79
|
+
this.bridge.on('management:started', (data) => {
|
|
80
|
+
this.emit('started', data);
|
|
81
|
+
});
|
|
82
|
+
this.bridge.on('management:stopped', (data) => {
|
|
83
|
+
this.emit('stopped', data);
|
|
84
|
+
});
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* Start the bridge: spawn in stdio mode or connect in socket mode.
|
|
88
|
+
*/
|
|
89
|
+
async start() {
|
|
90
|
+
if (this.transportOptions.transport === 'socket') {
|
|
91
|
+
const socketOpts = this.transportOptions;
|
|
92
|
+
return this.bridge.connect(socketOpts.socketPath, {
|
|
93
|
+
autoReconnect: socketOpts.autoReconnect,
|
|
94
|
+
reconnectBaseDelayMs: socketOpts.reconnectBaseDelayMs,
|
|
95
|
+
reconnectMaxDelayMs: socketOpts.reconnectMaxDelayMs,
|
|
96
|
+
maxReconnectAttempts: socketOpts.maxReconnectAttempts,
|
|
97
|
+
});
|
|
98
|
+
}
|
|
99
|
+
else {
|
|
100
|
+
return this.bridge.spawn();
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
/**
|
|
104
|
+
* Stop the bridge. In socket mode, closes the socket (daemon stays alive).
|
|
105
|
+
* In stdio mode, kills the child process.
|
|
106
|
+
*/
|
|
107
|
+
stop() {
|
|
108
|
+
this.bridge.kill();
|
|
109
|
+
}
|
|
110
|
+
/**
|
|
111
|
+
* Send a typed command to the daemon.
|
|
112
|
+
*/
|
|
113
|
+
async sendCommand(method, params) {
|
|
114
|
+
return this.bridge.sendCommand(method, params);
|
|
115
|
+
}
|
|
116
|
+
/**
|
|
117
|
+
* Whether the bridge is currently running/connected.
|
|
118
|
+
*/
|
|
119
|
+
get running() {
|
|
120
|
+
return this.bridge.running;
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic21hcnR2cG4uY2xhc3Nlcy52cG5icmlkZ2UuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi90cy9zbWFydHZwbi5jbGFzc2VzLnZwbmJyaWRnZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEtBQUssT0FBTyxNQUFNLHVCQUF1QixDQUFDO0FBQ2pELE9BQU8sS0FBSyxLQUFLLE1BQU0scUJBQXFCLENBQUM7QUFPN0M7O0dBRUc7QUFDSCxTQUFTLGNBQWM7SUFDckIsTUFBTSxPQUFPLEdBQUcsT0FBTyxDQUFDLElBQUksQ0FBQyxPQUFPLENBQUMsT0FBTyxDQUFDLEdBQUcsQ0FBQyxhQUFhLENBQUMsTUFBTSxDQUFDLElBQUksQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDO0lBQ2pGLE9BQU8sT0FBTyxDQUFDLElBQUksQ0FBQyxPQUFPLENBQUMsT0FBTyxFQUFFLElBQUksQ0FBQyxDQUFDO0FBQzdDLENBQUM7QUFFRDs7R0FFRztBQUNILFNBQVMsdUJBQXVCO0lBQzlCLE1BQU0sT0FBTyxHQUEyQixFQUFFLEdBQUcsRUFBRSxPQUFPLEVBQUUsS0FBSyxFQUFFLE9BQU8sRUFBRSxDQUFDO0lBQ3pFLE1BQU0sS0FBSyxHQUEyQixFQUFFLEtBQUssRUFBRSxPQUFPLEVBQUUsTUFBTSxFQUFFLE9BQU8sRUFBRSxDQUFDO0lBQzFFLE1BQU0sRUFBRSxHQUFHLEtBQUssQ0FBQyxPQUFPLENBQUMsUUFBUSxDQUFDLENBQUM7SUFDbkMsTUFBTSxJQUFJLEdBQUcsT0FBTyxDQUFDLE9BQU8sQ0FBQyxJQUFJLENBQUMsQ0FBQztJQUNuQyxJQUFJLEVBQUUsSUFBSSxJQUFJLEVBQUUsQ0FBQztRQUNmLE9BQU8sR0FBRyxFQUFFLElBQUksSUFBSSxFQUFFLENBQUM7SUFDekIsQ0FBQztJQUNELE9BQU8sSUFBSSxDQUFDO0FBQ2QsQ0FBQztBQUVEOztHQUVHO0FBQ0gsU0FBUyxlQUFlLENBQUMsVUFBa0I7SUFDekMsTUFBTSxXQUFXLEdBQUcs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
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import * as plugins from './smartvpn.plugins.js';
|
|
2
|
+
import type { IVpnClientOptions, IVpnClientConfig, IVpnStatus, IVpnStatistics } from './smartvpn.interfaces.js';
|
|
3
|
+
/**
|
|
4
|
+
* VPN Client — manages a smartvpn daemon in client mode.
|
|
5
|
+
*/
|
|
6
|
+
export declare class VpnClient extends plugins.events.EventEmitter {
|
|
7
|
+
private bridge;
|
|
8
|
+
private options;
|
|
9
|
+
constructor(options: IVpnClientOptions);
|
|
10
|
+
/**
|
|
11
|
+
* Start the daemon bridge (spawn or connect).
|
|
12
|
+
*/
|
|
13
|
+
start(): Promise<boolean>;
|
|
14
|
+
/**
|
|
15
|
+
* Connect to the VPN server using the provided config.
|
|
16
|
+
*/
|
|
17
|
+
connect(config?: IVpnClientConfig): Promise<{
|
|
18
|
+
assignedIp: string;
|
|
19
|
+
}>;
|
|
20
|
+
/**
|
|
21
|
+
* Disconnect from the VPN server.
|
|
22
|
+
*/
|
|
23
|
+
disconnect(): Promise<void>;
|
|
24
|
+
/**
|
|
25
|
+
* Get current connection status.
|
|
26
|
+
*/
|
|
27
|
+
getStatus(): Promise<IVpnStatus>;
|
|
28
|
+
/**
|
|
29
|
+
* Get traffic statistics.
|
|
30
|
+
*/
|
|
31
|
+
getStatistics(): Promise<IVpnStatistics>;
|
|
32
|
+
/**
|
|
33
|
+
* Stop the daemon bridge.
|
|
34
|
+
*/
|
|
35
|
+
stop(): void;
|
|
36
|
+
/**
|
|
37
|
+
* Whether the bridge is running.
|
|
38
|
+
*/
|
|
39
|
+
get running(): boolean;
|
|
40
|
+
}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import * as plugins from './smartvpn.plugins.js';
|
|
2
|
+
import { VpnBridge } from './smartvpn.classes.vpnbridge.js';
|
|
3
|
+
/**
|
|
4
|
+
* VPN Client — manages a smartvpn daemon in client mode.
|
|
5
|
+
*/
|
|
6
|
+
export class VpnClient extends plugins.events.EventEmitter {
|
|
7
|
+
constructor(options) {
|
|
8
|
+
super();
|
|
9
|
+
this.options = options;
|
|
10
|
+
this.bridge = new VpnBridge({
|
|
11
|
+
transport: options.transport,
|
|
12
|
+
mode: 'client',
|
|
13
|
+
});
|
|
14
|
+
// Forward bridge events
|
|
15
|
+
this.bridge.on('exit', (code, signal) => {
|
|
16
|
+
this.emit('exit', { code, signal });
|
|
17
|
+
});
|
|
18
|
+
this.bridge.on('reconnected', () => {
|
|
19
|
+
this.emit('reconnected');
|
|
20
|
+
});
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Start the daemon bridge (spawn or connect).
|
|
24
|
+
*/
|
|
25
|
+
async start() {
|
|
26
|
+
return this.bridge.start();
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Connect to the VPN server using the provided config.
|
|
30
|
+
*/
|
|
31
|
+
async connect(config) {
|
|
32
|
+
const cfg = config || this.options.config;
|
|
33
|
+
if (!cfg) {
|
|
34
|
+
throw new Error('VpnClient.connect: no config provided');
|
|
35
|
+
}
|
|
36
|
+
return this.bridge.sendCommand('connect', { config: cfg });
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Disconnect from the VPN server.
|
|
40
|
+
*/
|
|
41
|
+
async disconnect() {
|
|
42
|
+
await this.bridge.sendCommand('disconnect', {});
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Get current connection status.
|
|
46
|
+
*/
|
|
47
|
+
async getStatus() {
|
|
48
|
+
return this.bridge.sendCommand('getStatus', {});
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Get traffic statistics.
|
|
52
|
+
*/
|
|
53
|
+
async getStatistics() {
|
|
54
|
+
return this.bridge.sendCommand('getStatistics', {});
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Stop the daemon bridge.
|
|
58
|
+
*/
|
|
59
|
+
stop() {
|
|
60
|
+
this.bridge.stop();
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Whether the bridge is running.
|
|
64
|
+
*/
|
|
65
|
+
get running() {
|
|
66
|
+
return this.bridge.running;
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic21hcnR2cG4uY2xhc3Nlcy52cG5jbGllbnQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi90cy9zbWFydHZwbi5jbGFzc2VzLnZwbmNsaWVudC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEtBQUssT0FBTyxNQUFNLHVCQUF1QixDQUFDO0FBQ2pELE9BQU8sRUFBRSxTQUFTLEVBQUUsTUFBTSxpQ0FBaUMsQ0FBQztBQVM1RDs7R0FFRztBQUNILE1BQU0sT0FBTyxTQUFVLFNBQVEsT0FBTyxDQUFDLE1BQU0sQ0FBQyxZQUFZO0lBSXhELFlBQVksT0FBMEI7UUFDcEMsS0FBSyxFQUFFLENBQUM7UUFDUixJQUFJLENBQUMsT0FBTyxHQUFHLE9BQU8sQ0FBQztRQUN2QixJQUFJLENBQUMsTUFBTSxHQUFHLElBQUksU0FBUyxDQUFxQjtZQUM5QyxTQUFTLEVBQUUsT0FBTyxDQUFDLFNBQVM7WUFDNUIsSUFBSSxFQUFFLFFBQVE7U0FDZixDQUFDLENBQUM7UUFFSCx3QkFBd0I7UUFDeEIsSUFBSSxDQUFDLE1BQU0sQ0FBQyxFQUFFLENBQUMsTUFBTSxFQUFFLENBQUMsSUFBbUIsRUFBRSxNQUFxQixFQUFFLEVBQUU7WUFDcEUsSUFBSSxDQUFDLElBQUksQ0FBQyxNQUFNLEVBQUUsRUFBRSxJQUFJLEVBQUUsTUFBTSxFQUFFLENBQUMsQ0FBQztRQUN0QyxDQUFDLENBQUMsQ0FBQztRQUNILElBQUksQ0FBQyxNQUFNLENBQUMsRUFBRSxDQUFDLGFBQWEsRUFBRSxHQUFHLEVBQUU7WUFDakMsSUFBSSxDQUFDLElBQUksQ0FBQyxhQUFhLENBQUMsQ0FBQztRQUMzQixDQUFDLENBQUMsQ0FBQztJQUNMLENBQUM7SUFFRDs7T0FFRztJQUNJLEtBQUssQ0FBQyxLQUFLO1FBQ2hCLE9BQU8sSUFBSSxDQUFDLE1BQU0sQ0FBQyxLQUFLLEVBQUUsQ0FBQztJQUM3QixDQUFDO0lBRUQ7O09BRUc7SUFDSSxLQUFLLENBQUMsT0FBTyxDQUFDLE1BQXlCO1FBQzVDLE1BQU0sR0FBRyxHQUFHLE1BQU0sSUFBSSxJQUFJLENBQUMsT0FBTyxDQUFDLE1BQU0sQ0FBQztRQUMxQyxJQUFJLENBQUMsR0FBRyxFQUFFLENBQUM7WUFDVCxNQUFNLElBQUksS0FBSyxDQUFDLHVDQUF1QyxDQUFDLENBQUM7UUFDM0QsQ0FBQztRQUNELE9BQU8sSUFBSSxDQUFDLE1BQU0sQ0FBQyxXQUFXLENBQUMsU0FBUyxFQUFFLEVBQUUsTUFBTSxFQUFFLEdBQUcsRUFBRSxDQUFDLENBQUM7SUFDN0QsQ0FBQztJQUVEOztPQUVHO0lBQ0ksS0FBSyxDQUFDLFVBQVU7UUFDckIsTUFBTSxJQUFJLENBQUMsTUFBTSxDQUFDLFdBQVcsQ0FBQyxZQUFZLEVBQUUsRUFBMkIsQ0FBQyxDQUFDO0lBQzNFLENBQUM7SUFFRDs7T0FFRztJQUNJLEtBQUssQ0FBQyxTQUFTO1FBQ3BCLE9BQU8sSUFBSSxDQUFDLE1BQU0sQ0FBQyxXQUFXLENBQUMsV0FBVyxFQUFFLEVBQTJCLENBQUMsQ0FBQztJQUMzRSxDQUFDO0lBRUQ7O09BRUc7SUFDSSxLQUFLLENBQUMsYUFBYTtRQUN4QixPQUFPLElBQUksQ0FBQyxNQUFNLENBQUMsV0FBVyxDQUFDLGVBQWUsRUFBRSxFQUEyQixDQUFDLENBQUM7SUFDL0UsQ0FBQztJQUVEOztPQUVHO0lBQ0ksSUFBSTtRQUNULElBQUksQ0FBQyxNQUFNLENBQUMsSUFBSSxFQUFFLENBQUM7SUFDckIsQ0FBQztJQUVEOztPQUVHO0lBQ0gsSUFBVyxPQUFPO1FBQ2hCLE9BQU8sSUFBSSxDQUFDLE1BQU0sQ0FBQyxPQUFPLENBQUM7SUFDN0IsQ0FBQztDQUNGIn0=
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import type { IVpnClientConfig, IVpnServerConfig } from './smartvpn.interfaces.js';
|
|
2
|
+
/**
|
|
3
|
+
* VPN configuration loader, saver, and validator.
|
|
4
|
+
*/
|
|
5
|
+
export declare class VpnConfig {
|
|
6
|
+
/**
|
|
7
|
+
* Validate a client config object. Throws on invalid config.
|
|
8
|
+
*/
|
|
9
|
+
static validateClientConfig(config: IVpnClientConfig): void;
|
|
10
|
+
/**
|
|
11
|
+
* Validate a server config object. Throws on invalid config.
|
|
12
|
+
*/
|
|
13
|
+
static validateServerConfig(config: IVpnServerConfig): void;
|
|
14
|
+
/**
|
|
15
|
+
* Load a config from a JSON file.
|
|
16
|
+
*/
|
|
17
|
+
static loadFromFile<T>(filePath: string): Promise<T>;
|
|
18
|
+
/**
|
|
19
|
+
* Save a config to a JSON file.
|
|
20
|
+
*/
|
|
21
|
+
static saveToFile<T>(filePath: string, config: T): Promise<void>;
|
|
22
|
+
/**
|
|
23
|
+
* Basic IP address validation.
|
|
24
|
+
*/
|
|
25
|
+
private static isValidIp;
|
|
26
|
+
/**
|
|
27
|
+
* Basic subnet validation (CIDR notation).
|
|
28
|
+
*/
|
|
29
|
+
private static isValidSubnet;
|
|
30
|
+
}
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
import * as plugins from './smartvpn.plugins.js';
|
|
2
|
+
/**
|
|
3
|
+
* VPN configuration loader, saver, and validator.
|
|
4
|
+
*/
|
|
5
|
+
export class VpnConfig {
|
|
6
|
+
/**
|
|
7
|
+
* Validate a client config object. Throws on invalid config.
|
|
8
|
+
*/
|
|
9
|
+
static validateClientConfig(config) {
|
|
10
|
+
if (!config.serverUrl) {
|
|
11
|
+
throw new Error('VpnConfig: serverUrl is required');
|
|
12
|
+
}
|
|
13
|
+
if (!config.serverUrl.startsWith('wss://') && !config.serverUrl.startsWith('ws://')) {
|
|
14
|
+
throw new Error('VpnConfig: serverUrl must start with wss:// or ws://');
|
|
15
|
+
}
|
|
16
|
+
if (!config.serverPublicKey) {
|
|
17
|
+
throw new Error('VpnConfig: serverPublicKey is required');
|
|
18
|
+
}
|
|
19
|
+
if (config.mtu !== undefined && (config.mtu < 576 || config.mtu > 65535)) {
|
|
20
|
+
throw new Error('VpnConfig: mtu must be between 576 and 65535');
|
|
21
|
+
}
|
|
22
|
+
if (config.keepaliveIntervalSecs !== undefined && config.keepaliveIntervalSecs < 1) {
|
|
23
|
+
throw new Error('VpnConfig: keepaliveIntervalSecs must be >= 1');
|
|
24
|
+
}
|
|
25
|
+
if (config.dns) {
|
|
26
|
+
for (const dns of config.dns) {
|
|
27
|
+
if (!VpnConfig.isValidIp(dns)) {
|
|
28
|
+
throw new Error(`VpnConfig: invalid DNS address: ${dns}`);
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Validate a server config object. Throws on invalid config.
|
|
35
|
+
*/
|
|
36
|
+
static validateServerConfig(config) {
|
|
37
|
+
if (!config.listenAddr) {
|
|
38
|
+
throw new Error('VpnConfig: listenAddr is required');
|
|
39
|
+
}
|
|
40
|
+
if (!config.privateKey) {
|
|
41
|
+
throw new Error('VpnConfig: privateKey is required');
|
|
42
|
+
}
|
|
43
|
+
if (!config.publicKey) {
|
|
44
|
+
throw new Error('VpnConfig: publicKey is required');
|
|
45
|
+
}
|
|
46
|
+
if (!config.subnet) {
|
|
47
|
+
throw new Error('VpnConfig: subnet is required');
|
|
48
|
+
}
|
|
49
|
+
if (!VpnConfig.isValidSubnet(config.subnet)) {
|
|
50
|
+
throw new Error(`VpnConfig: invalid subnet: ${config.subnet}`);
|
|
51
|
+
}
|
|
52
|
+
if (config.mtu !== undefined && (config.mtu < 576 || config.mtu > 65535)) {
|
|
53
|
+
throw new Error('VpnConfig: mtu must be between 576 and 65535');
|
|
54
|
+
}
|
|
55
|
+
if (config.keepaliveIntervalSecs !== undefined && config.keepaliveIntervalSecs < 1) {
|
|
56
|
+
throw new Error('VpnConfig: keepaliveIntervalSecs must be >= 1');
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Load a config from a JSON file.
|
|
61
|
+
*/
|
|
62
|
+
static async loadFromFile(filePath) {
|
|
63
|
+
const content = await plugins.fs.promises.readFile(filePath, 'utf-8');
|
|
64
|
+
return JSON.parse(content);
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* Save a config to a JSON file.
|
|
68
|
+
*/
|
|
69
|
+
static async saveToFile(filePath, config) {
|
|
70
|
+
const content = JSON.stringify(config, null, 2);
|
|
71
|
+
await plugins.fs.promises.writeFile(filePath, content, 'utf-8');
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* Basic IP address validation.
|
|
75
|
+
*/
|
|
76
|
+
static isValidIp(ip) {
|
|
77
|
+
const parts = ip.split('.');
|
|
78
|
+
if (parts.length !== 4)
|
|
79
|
+
return false;
|
|
80
|
+
return parts.every((part) => {
|
|
81
|
+
const num = parseInt(part, 10);
|
|
82
|
+
return !isNaN(num) && num >= 0 && num <= 255 && String(num) === part;
|
|
83
|
+
});
|
|
84
|
+
}
|
|
85
|
+
/**
|
|
86
|
+
* Basic subnet validation (CIDR notation).
|
|
87
|
+
*/
|
|
88
|
+
static isValidSubnet(subnet) {
|
|
89
|
+
const [ip, prefix] = subnet.split('/');
|
|
90
|
+
if (!ip || !prefix)
|
|
91
|
+
return false;
|
|
92
|
+
if (!VpnConfig.isValidIp(ip))
|
|
93
|
+
return false;
|
|
94
|
+
const prefixNum = parseInt(prefix, 10);
|
|
95
|
+
return !isNaN(prefixNum) && prefixNum >= 0 && prefixNum <= 32;
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic21hcnR2cG4uY2xhc3Nlcy52cG5jb25maWcuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi90cy9zbWFydHZwbi5jbGFzc2VzLnZwbmNvbmZpZy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEtBQUssT0FBTyxNQUFNLHVCQUF1QixDQUFDO0FBTWpEOztHQUVHO0FBQ0gsTUFBTSxPQUFPLFNBQVM7SUFDcEI7O09BRUc7SUFDSSxNQUFNLENBQUMsb0JBQW9CLENBQUMsTUFBd0I7UUFDekQsSUFBSSxDQUFDLE1BQU0sQ0FBQyxTQUFTLEVBQUUsQ0FBQztZQUN0QixNQUFNLElBQUksS0FBSyxDQUFDLGtDQUFrQyxDQUFDLENBQUM7UUFDdEQsQ0FBQztRQUNELElBQUksQ0FBQyxNQUFNLENBQUMsU0FBUyxDQUFDLFVBQVUsQ0FBQyxRQUFRLENBQUMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxTQUFTLENBQUMsVUFBVSxDQUFDLE9BQU8sQ0FBQyxFQUFFLENBQUM7WUFDcEYsTUFBTSxJQUFJLEtBQUssQ0FBQyxzREFBc0QsQ0FBQyxDQUFDO1FBQzFFLENBQUM7UUFDRCxJQUFJLENBQUMsTUFBTSxDQUFDLGVBQWUsRUFBRSxDQUFDO1lBQzVCLE1BQU0sSUFBSSxLQUFLLENBQUMsd0NBQXdDLENBQUMsQ0FBQztRQUM1RCxDQUFDO1FBQ0QsSUFBSSxNQUFNLENBQUMsR0FBRyxLQUFLLFNBQVMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxHQUFHLEdBQUcsR0FBRyxJQUFJLE1BQU0sQ0FBQyxHQUFHLEdBQUcsS0FBSyxDQUFDLEVBQUUsQ0FBQztZQUN6RSxNQUFNLElBQUksS0FBSyxDQUFDLDhDQUE4QyxDQUFDLENBQUM7UUFDbEUsQ0FBQztRQUNELElBQUksTUFBTSxDQUFDLHFCQUFxQixLQUFLLFNBQVMsSUFBSSxNQUFNLENBQUMscUJBQXFCLEdBQUcsQ0FBQyxFQUFFLENBQUM7WUFDbkYsTUFBTSxJQUFJLEtBQUssQ0FBQywrQ0FBK0MsQ0FBQyxD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
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import type { TVpnPlatform, IVpnServiceUnit } from './smartvpn.interfaces.js';
|
|
2
|
+
/**
|
|
3
|
+
* Install the smartvpn daemon as a system service.
|
|
4
|
+
*/
|
|
5
|
+
export declare class VpnInstaller {
|
|
6
|
+
/**
|
|
7
|
+
* Detect the current platform.
|
|
8
|
+
*/
|
|
9
|
+
static detectPlatform(): TVpnPlatform;
|
|
10
|
+
/**
|
|
11
|
+
* Generate a systemd unit file for Linux.
|
|
12
|
+
*/
|
|
13
|
+
static generateSystemdUnit(options: {
|
|
14
|
+
binaryPath: string;
|
|
15
|
+
socketPath: string;
|
|
16
|
+
mode: 'client' | 'server';
|
|
17
|
+
configPath?: string;
|
|
18
|
+
description?: string;
|
|
19
|
+
}): IVpnServiceUnit;
|
|
20
|
+
/**
|
|
21
|
+
* Generate a launchd plist for macOS.
|
|
22
|
+
*/
|
|
23
|
+
static generateLaunchdPlist(options: {
|
|
24
|
+
binaryPath: string;
|
|
25
|
+
socketPath: string;
|
|
26
|
+
mode: 'client' | 'server';
|
|
27
|
+
description?: string;
|
|
28
|
+
}): IVpnServiceUnit;
|
|
29
|
+
/**
|
|
30
|
+
* Generate the appropriate service unit for the current platform.
|
|
31
|
+
*/
|
|
32
|
+
static generateServiceUnit(options: {
|
|
33
|
+
binaryPath: string;
|
|
34
|
+
socketPath: string;
|
|
35
|
+
mode: 'client' | 'server';
|
|
36
|
+
}): IVpnServiceUnit;
|
|
37
|
+
}
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
import * as plugins from './smartvpn.plugins.js';
|
|
2
|
+
/**
|
|
3
|
+
* Install the smartvpn daemon as a system service.
|
|
4
|
+
*/
|
|
5
|
+
export class VpnInstaller {
|
|
6
|
+
/**
|
|
7
|
+
* Detect the current platform.
|
|
8
|
+
*/
|
|
9
|
+
static detectPlatform() {
|
|
10
|
+
switch (process.platform) {
|
|
11
|
+
case 'linux':
|
|
12
|
+
return 'linux';
|
|
13
|
+
case 'darwin':
|
|
14
|
+
return 'macos';
|
|
15
|
+
case 'win32':
|
|
16
|
+
return 'windows';
|
|
17
|
+
default:
|
|
18
|
+
return 'unknown';
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Generate a systemd unit file for Linux.
|
|
23
|
+
*/
|
|
24
|
+
static generateSystemdUnit(options) {
|
|
25
|
+
const desc = options.description || `SmartVPN ${options.mode} daemon`;
|
|
26
|
+
const content = `[Unit]
|
|
27
|
+
Description=${desc}
|
|
28
|
+
After=network-online.target
|
|
29
|
+
Wants=network-online.target
|
|
30
|
+
|
|
31
|
+
[Service]
|
|
32
|
+
Type=simple
|
|
33
|
+
ExecStart=${options.binaryPath} --management-socket ${options.socketPath} --mode ${options.mode}
|
|
34
|
+
Restart=always
|
|
35
|
+
RestartSec=5
|
|
36
|
+
LimitNOFILE=65535
|
|
37
|
+
|
|
38
|
+
# Security hardening
|
|
39
|
+
NoNewPrivileges=no
|
|
40
|
+
ProtectSystem=strict
|
|
41
|
+
ProtectHome=yes
|
|
42
|
+
ReadWritePaths=/var/run /dev/net/tun
|
|
43
|
+
PrivateTmp=yes
|
|
44
|
+
|
|
45
|
+
[Install]
|
|
46
|
+
WantedBy=multi-user.target
|
|
47
|
+
`;
|
|
48
|
+
return {
|
|
49
|
+
platform: 'linux',
|
|
50
|
+
content,
|
|
51
|
+
installPath: `/etc/systemd/system/smartvpn-${options.mode}.service`,
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Generate a launchd plist for macOS.
|
|
56
|
+
*/
|
|
57
|
+
static generateLaunchdPlist(options) {
|
|
58
|
+
const label = `rocks.push.smartvpn.${options.mode}`;
|
|
59
|
+
const content = `<?xml version="1.0" encoding="UTF-8"?>
|
|
60
|
+
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
|
61
|
+
<plist version="1.0">
|
|
62
|
+
<dict>
|
|
63
|
+
<key>Label</key>
|
|
64
|
+
<string>${label}</string>
|
|
65
|
+
<key>ProgramArguments</key>
|
|
66
|
+
<array>
|
|
67
|
+
<string>${options.binaryPath}</string>
|
|
68
|
+
<string>--management-socket</string>
|
|
69
|
+
<string>${options.socketPath}</string>
|
|
70
|
+
<string>--mode</string>
|
|
71
|
+
<string>${options.mode}</string>
|
|
72
|
+
</array>
|
|
73
|
+
<key>RunAtLoad</key>
|
|
74
|
+
<true/>
|
|
75
|
+
<key>KeepAlive</key>
|
|
76
|
+
<true/>
|
|
77
|
+
<key>StandardErrorPath</key>
|
|
78
|
+
<string>/var/log/smartvpn-${options.mode}.err.log</string>
|
|
79
|
+
<key>StandardOutPath</key>
|
|
80
|
+
<string>/var/log/smartvpn-${options.mode}.out.log</string>
|
|
81
|
+
</dict>
|
|
82
|
+
</plist>
|
|
83
|
+
`;
|
|
84
|
+
return {
|
|
85
|
+
platform: 'macos',
|
|
86
|
+
content,
|
|
87
|
+
installPath: `/Library/LaunchDaemons/${label}.plist`,
|
|
88
|
+
};
|
|
89
|
+
}
|
|
90
|
+
/**
|
|
91
|
+
* Generate the appropriate service unit for the current platform.
|
|
92
|
+
*/
|
|
93
|
+
static generateServiceUnit(options) {
|
|
94
|
+
const platform = VpnInstaller.detectPlatform();
|
|
95
|
+
switch (platform) {
|
|
96
|
+
case 'linux':
|
|
97
|
+
return VpnInstaller.generateSystemdUnit(options);
|
|
98
|
+
case 'macos':
|
|
99
|
+
return VpnInstaller.generateLaunchdPlist(options);
|
|
100
|
+
default:
|
|
101
|
+
throw new Error(`VpnInstaller: unsupported platform: ${platform}`);
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic21hcnR2cG4uY2xhc3Nlcy52cG5pbnN0YWxsZXIuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi90cy9zbWFydHZwbi5jbGFzc2VzLnZwbmluc3RhbGxlci50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEtBQUssT0FBTyxNQUFNLHVCQUF1QixDQUFDO0FBR2pEOztHQUVHO0FBQ0gsTUFBTSxPQUFPLFlBQVk7SUFDdkI7O09BRUc7SUFDSSxNQUFNLENBQUMsY0FBYztRQUMxQixRQUFRLE9BQU8sQ0FBQyxRQUFRLEVBQUUsQ0FBQztZQUN6QixLQUFLLE9BQU87Z0JBQ1YsT0FBTyxPQUFPLENBQUM7WUFDakIsS0FBSyxRQUFRO2dCQUNYLE9BQU8sT0FBTyxDQUFDO1lBQ2pCLEtBQUssT0FBTztnQkFDVixPQUFPLFNBQVMsQ0FBQztZQUNuQjtnQkFDRSxPQUFPLFNBQVMsQ0FBQztRQUNyQixDQUFDO0lBQ0gsQ0FBQztJQUVEOztPQUVHO0lBQ0ksTUFBTSxDQUFDLG1CQUFtQixDQUFDLE9BTWpDO1FBQ0MsTUFBTSxJQUFJLEdBQUcsT0FBTyxDQUFDLFdBQVcsSUFBSSxZQUFZLE9BQU8sQ0FBQyxJQUFJLFNBQVMsQ0FBQztRQUN0RSxNQUFNLE9BQU8sR0FBRztjQUNOLElBQUk7Ozs7OztZQU1OLE9BQU8sQ0FBQyxVQUFVLHdCQUF3QixPQUFPLENBQUMsVUFBVSxXQUFXLE9BQU8sQ0FBQyxJQUFJOzs7Ozs7Ozs7Ozs7OztDQWM5RixDQUFDO1FBRUUsT0FBTztZQUNMLFFBQVEsRUFBRSxPQUFPO1lBQ2pCLE9BQU87WUFDUCxXQUFXLEVBQUUsZ0NBQWdDLE9BQU8sQ0FBQyxJQUFJLFVBQVU7U0FDcEUsQ0FBQztJQUNKLENBQUM7SUFFRDs7T0FFRztJQUNJLE1BQU0sQ0FBQyxvQkFBb0IsQ0FBQyxPQUtsQztRQUNDLE1BQU0sS0FBSyxHQUFHLHVCQUF1QixPQUFPLENBQUMsSUFBSSxFQUFFLENBQUM7UUFDcEQsTUFBTSxPQUFPLEdBQUc7Ozs7O1lBS1IsS0FBSzs7O2NBR0gsT0FBTyxDQUFDLFVBQVU7O2NBRWxCLE9BQU8sQ0FBQyxVQUFVOztjQUVsQixPQUFPLENBQUMsSUFBSTs7Ozs7Ozs4QkFPSSxPQUFPLENBQUMsSUFBSTs7OEJBRVosT0FBTyxDQUFDLElBQUk7OztDQUd6QyxDQUFDO1FBRUUsT0FBTztZQUNMLFFBQVEsRUFBRSxPQUFPO1lBQ2pCLE9BQU87WUFDUCxXQUFXLEVBQUUsMEJBQTBCLEtBQUssUUFBUTtTQUNyRCxDQUFDO0lBQ0osQ0FBQztJQUVEOztPQUVHO0lBQ0ksTUFBTSxDQUFDLG1CQUFtQixDQUFDLE9BSWpDO1FBQ0MsTUFBTSxRQUFRLEdBQUcsWUFBWSxDQUFDLGNBQWMsRUFBRSxDQUFDO1FBQy9DLFFBQVEsUUFBUSxFQUFFLENBQUM7WUFDakIsS0FBSyxPQUFPO2dCQUNWLE9BQU8sWUFBWSxDQUFDLG1CQUFtQixDQUFDLE9BQU8sQ0FBQyxDQUFDO1lBQ25ELEtBQUssT0FBTztnQkFDVixPQUFPLFlBQVksQ0FBQyxvQkFBb0IsQ0FBQyxPQUFPLENBQUMsQ0FBQztZQUNwRDtnQkFDRSxNQUFNLElBQUksS0FBSyxDQUFDLHVDQUF1QyxRQUFRLEVBQUUsQ0FBQyxDQUFDO1FBQ3ZFLENBQUM7SUFDSCxDQUFDO0NBQ0YifQ==
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import * as plugins from './smartvpn.plugins.js';
|
|
2
|
+
import type { IVpnServerOptions, IVpnServerConfig, IVpnStatus, IVpnServerStatistics, IVpnClientInfo, IVpnKeypair } from './smartvpn.interfaces.js';
|
|
3
|
+
/**
|
|
4
|
+
* VPN Server — manages a smartvpn daemon in server mode.
|
|
5
|
+
*/
|
|
6
|
+
export declare class VpnServer extends plugins.events.EventEmitter {
|
|
7
|
+
private bridge;
|
|
8
|
+
private options;
|
|
9
|
+
constructor(options: IVpnServerOptions);
|
|
10
|
+
/**
|
|
11
|
+
* Start the daemon bridge (spawn or connect).
|
|
12
|
+
*/
|
|
13
|
+
start(config?: IVpnServerConfig): Promise<void>;
|
|
14
|
+
/**
|
|
15
|
+
* Stop the VPN server.
|
|
16
|
+
*/
|
|
17
|
+
stopServer(): Promise<void>;
|
|
18
|
+
/**
|
|
19
|
+
* Get server status.
|
|
20
|
+
*/
|
|
21
|
+
getStatus(): Promise<IVpnStatus>;
|
|
22
|
+
/**
|
|
23
|
+
* Get server statistics.
|
|
24
|
+
*/
|
|
25
|
+
getStatistics(): Promise<IVpnServerStatistics>;
|
|
26
|
+
/**
|
|
27
|
+
* List connected clients.
|
|
28
|
+
*/
|
|
29
|
+
listClients(): Promise<IVpnClientInfo[]>;
|
|
30
|
+
/**
|
|
31
|
+
* Disconnect a specific client.
|
|
32
|
+
*/
|
|
33
|
+
disconnectClient(clientId: string): Promise<void>;
|
|
34
|
+
/**
|
|
35
|
+
* Generate a new Noise keypair.
|
|
36
|
+
*/
|
|
37
|
+
generateKeypair(): Promise<IVpnKeypair>;
|
|
38
|
+
/**
|
|
39
|
+
* Stop the daemon bridge.
|
|
40
|
+
*/
|
|
41
|
+
stop(): void;
|
|
42
|
+
/**
|
|
43
|
+
* Whether the bridge is running.
|
|
44
|
+
*/
|
|
45
|
+
get running(): boolean;
|
|
46
|
+
}
|