@push.rocks/smartvpn 1.18.0 → 1.19.1
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.js +1 -1
- package/dist_ts/smartvpn.interfaces.d.ts +14 -1
- package/package.json +1 -1
- package/readme.md +71 -15
- package/ts/00_commitinfo_data.ts +1 -1
- package/ts/smartvpn.interfaces.ts +17 -1
|
Binary file
|
|
Binary file
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
*/
|
|
4
4
|
export const commitinfo = {
|
|
5
5
|
name: '@push.rocks/smartvpn',
|
|
6
|
-
version: '1.
|
|
6
|
+
version: '1.19.1',
|
|
7
7
|
description: 'A VPN solution with TypeScript control plane and Rust data plane daemon'
|
|
8
8
|
};
|
|
9
9
|
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiMDBfY29tbWl0aW5mb19kYXRhLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vdHMvMDBfY29tbWl0aW5mb19kYXRhLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBOztHQUVHO0FBQ0gsTUFBTSxDQUFDLE1BQU0sVUFBVSxHQUFHO0lBQ3hCLElBQUksRUFBRSxzQkFBc0I7SUFDNUIsT0FBTyxFQUFFLFFBQVE7SUFDakIsV0FBVyxFQUFFLHlFQUF5RTtDQUN2RixDQUFBIn0=
|
|
@@ -75,8 +75,9 @@ export interface IVpnServerConfig {
|
|
|
75
75
|
/** Enable NAT/masquerade for client traffic */
|
|
76
76
|
enableNat?: boolean;
|
|
77
77
|
/** Forwarding mode: 'tun' (kernel TUN, requires root), 'socket' (userspace NAT),
|
|
78
|
+
* 'bridge' (L2 bridge to host LAN), 'hybrid' (per-client socket+bridge),
|
|
78
79
|
* or 'testing' (monitoring only). Default: 'testing'. */
|
|
79
|
-
forwardingMode?: 'tun' | 'socket' | 'bridge' | 'testing';
|
|
80
|
+
forwardingMode?: 'tun' | 'socket' | 'bridge' | 'hybrid' | 'testing';
|
|
80
81
|
/** Default rate limit for new clients (bytes/sec). Omit for unlimited. */
|
|
81
82
|
defaultRateLimitBytesPerSec?: number;
|
|
82
83
|
/** Default burst size for new clients (bytes). Omit for unlimited. */
|
|
@@ -300,6 +301,18 @@ export interface IClientEntry {
|
|
|
300
301
|
expiresAt?: string;
|
|
301
302
|
/** Assigned VPN IP address (set by server) */
|
|
302
303
|
assignedIp?: string;
|
|
304
|
+
/** If true, client gets a host network IP via bridge mode (L2 to LAN).
|
|
305
|
+
* If false (default), client gets a VPN subnet IP via socket/NAT mode. */
|
|
306
|
+
useHostIp?: boolean;
|
|
307
|
+
/** If true and useHostIp is true, obtain IP via DHCP relay.
|
|
308
|
+
* If false or omitted, use staticIp or auto-assign from bridge IP range. */
|
|
309
|
+
useDhcp?: boolean;
|
|
310
|
+
/** Static LAN IP when useHostIp is true and useDhcp is false. */
|
|
311
|
+
staticIp?: string;
|
|
312
|
+
/** If true, assign this client to a specific 802.1Q VLAN on the bridge. */
|
|
313
|
+
forceVlan?: boolean;
|
|
314
|
+
/** 802.1Q VLAN ID (1-4094). Required when forceVlan is true. */
|
|
315
|
+
vlanId?: number;
|
|
303
316
|
}
|
|
304
317
|
/**
|
|
305
318
|
* Complete client config bundle — returned by createClient() and rotateClientKey().
|
package/package.json
CHANGED
package/readme.md
CHANGED
|
@@ -2,17 +2,19 @@
|
|
|
2
2
|
|
|
3
3
|
A high-performance VPN solution with a **TypeScript control plane** and a **Rust data plane daemon**. Enterprise-ready client authentication, triple transport support (WebSocket + QUIC + WireGuard), and a typed hub API for managing clients from code.
|
|
4
4
|
|
|
5
|
-
🔐 **Noise IK** mutual authentication — per-client X25519 keypairs, server-side registry
|
|
6
|
-
🚀 **Triple transport**: WebSocket (Cloudflare-friendly), raw **QUIC** (datagrams), and **WireGuard** (standard protocol)
|
|
7
|
-
🛡️ **ACL engine** — deny-overrides-allow IP filtering, aligned with SmartProxy conventions
|
|
8
|
-
🔀 **PROXY protocol v2** — real client IPs behind reverse proxies (HAProxy, SmartProxy, Cloudflare Spectrum)
|
|
9
|
-
📊 **Per-transport metrics**: active clients and total connections broken down by websocket, QUIC, and WireGuard
|
|
10
|
-
🔄 **Hub API**: one `createClient()` call generates keys, assigns IP, returns both SmartVPN + WireGuard configs
|
|
11
|
-
📡 **Real-time telemetry**: RTT, jitter, loss ratio, link health — all via typed APIs
|
|
12
|
-
🌐 **Unified forwarding pipeline**: all transports share the same engine — TUN (kernel), userspace NAT (no root), L2 bridge, or testing mode
|
|
13
|
-
🏠 **Bridge mode**: VPN clients get IPs from your LAN subnet — seamlessly bridge remote clients onto a physical network
|
|
14
|
-
|
|
15
|
-
|
|
5
|
+
- 🔐 **Noise IK** mutual authentication — per-client X25519 keypairs, server-side registry
|
|
6
|
+
- 🚀 **Triple transport**: WebSocket (Cloudflare-friendly), raw **QUIC** (datagrams), and **WireGuard** (standard protocol)
|
|
7
|
+
- 🛡️ **ACL engine** — deny-overrides-allow IP filtering, aligned with SmartProxy conventions
|
|
8
|
+
- 🔀 **PROXY protocol v2** — real client IPs behind reverse proxies (HAProxy, SmartProxy, Cloudflare Spectrum)
|
|
9
|
+
- 📊 **Per-transport metrics**: active clients and total connections broken down by websocket, QUIC, and WireGuard
|
|
10
|
+
- 🔄 **Hub API**: one `createClient()` call generates keys, assigns IP, returns both SmartVPN + WireGuard configs
|
|
11
|
+
- 📡 **Real-time telemetry**: RTT, jitter, loss ratio, link health — all via typed APIs
|
|
12
|
+
- 🌐 **Unified forwarding pipeline**: all transports share the same engine — TUN (kernel), userspace NAT (no root), L2 bridge, hybrid, or testing mode
|
|
13
|
+
- 🏠 **Bridge mode**: VPN clients get IPs from your LAN subnet — seamlessly bridge remote clients onto a physical network
|
|
14
|
+
- 🔀 **Hybrid mode**: per-client routing — some clients bridge to the LAN, others use userspace NAT, all on the same server
|
|
15
|
+
- 🏷️ **VLAN support**: assign individual clients to 802.1Q VLANs on the bridge
|
|
16
|
+
- 🎯 **Destination routing policy**: force-target, block, or allow traffic per destination with nftables integration
|
|
17
|
+
- ⚡ **Handshake-driven WireGuard state**: peers appear as "connected" only after a successful WireGuard handshake, and auto-disconnect on idle timeout
|
|
16
18
|
|
|
17
19
|
## Issue Reporting and Security
|
|
18
20
|
|
|
@@ -85,7 +87,7 @@ await server.start({
|
|
|
85
87
|
publicKey: '<server-noise-public-key-base64>',
|
|
86
88
|
subnet: '10.8.0.0/24',
|
|
87
89
|
transportMode: 'all', // WebSocket + QUIC + WireGuard simultaneously (default)
|
|
88
|
-
forwardingMode: 'tun', // 'tun' | 'socket' | 'bridge' | 'testing'
|
|
90
|
+
forwardingMode: 'tun', // 'tun' | 'socket' | 'bridge' | 'hybrid' | 'testing'
|
|
89
91
|
wgPrivateKey: '<server-wg-private-key-base64>', // required for WireGuard transport
|
|
90
92
|
enableNat: true,
|
|
91
93
|
dns: ['1.1.1.1', '8.8.8.8'],
|
|
@@ -267,13 +269,14 @@ await server.start({
|
|
|
267
269
|
|
|
268
270
|
### 📦 Packet Forwarding Modes
|
|
269
271
|
|
|
270
|
-
SmartVPN supports
|
|
272
|
+
SmartVPN supports five forwarding modes, configurable per-server:
|
|
271
273
|
|
|
272
274
|
| Mode | Flag | Description | Root Required |
|
|
273
275
|
|------|------|-------------|---------------|
|
|
274
276
|
| **TUN** | `'tun'` | Kernel TUN device — real packet forwarding with system routing | ✅ Yes |
|
|
275
277
|
| **Userspace NAT** | `'socket'` | Userspace TCP/UDP proxy via `connect(2)` — no TUN, no root needed | ❌ No |
|
|
276
278
|
| **Bridge** | `'bridge'` | L2 bridge — VPN clients get IPs from a physical LAN subnet | ✅ Yes |
|
|
279
|
+
| **Hybrid** | `'hybrid'` | Per-client routing: some clients use socket NAT, others use bridge — both engines run simultaneously | ✅ Yes |
|
|
277
280
|
| **Testing** | `'testing'` | Monitoring only — packets are counted but not forwarded | ❌ No |
|
|
278
281
|
|
|
279
282
|
```typescript
|
|
@@ -294,6 +297,13 @@ await server.start({
|
|
|
294
297
|
bridgeIpRangeEnd: 250,
|
|
295
298
|
});
|
|
296
299
|
|
|
300
|
+
// Server with hybrid mode — per-client routing
|
|
301
|
+
await server.start({
|
|
302
|
+
// ...
|
|
303
|
+
forwardingMode: 'hybrid',
|
|
304
|
+
bridgePhysicalInterface: 'eth0', // for bridge clients
|
|
305
|
+
});
|
|
306
|
+
|
|
297
307
|
// Client with TUN device
|
|
298
308
|
const { assignedIp } = await client.connect({
|
|
299
309
|
// ...
|
|
@@ -305,6 +315,52 @@ The **userspace NAT** mode extracts destination IP/port from IP packets, opens a
|
|
|
305
315
|
|
|
306
316
|
The **bridge** mode assigns VPN clients IPs from a real LAN subnet instead of a virtual VPN subnet. Clients appear as if they're directly on the physical network — perfect for remote access to home labs, office networks, or IoT devices.
|
|
307
317
|
|
|
318
|
+
The **hybrid** mode runs both engines simultaneously with a **per-client routing table**. Each client's `useHostIp` flag determines whether its packets go through the bridge (L2, LAN IP) or socket NAT (userspace, VPN IP). This is ideal when most clients need internet NAT but some need direct LAN access.
|
|
319
|
+
|
|
320
|
+
### 🏠 Per-Client Bridge & VLAN Settings
|
|
321
|
+
|
|
322
|
+
When using `bridge` or `hybrid` mode, each client can be individually configured for LAN bridging, static IPs, DHCP, and 802.1Q VLAN assignment:
|
|
323
|
+
|
|
324
|
+
```typescript
|
|
325
|
+
// Client that bridges to the LAN with a static IP
|
|
326
|
+
await server.createClient({
|
|
327
|
+
clientId: 'office-printer',
|
|
328
|
+
useHostIp: true, // bridge to LAN instead of VPN subnet
|
|
329
|
+
staticIp: '192.168.1.210', // fixed LAN IP
|
|
330
|
+
});
|
|
331
|
+
|
|
332
|
+
// Client that gets a LAN IP via DHCP
|
|
333
|
+
await server.createClient({
|
|
334
|
+
clientId: 'roaming-laptop',
|
|
335
|
+
useHostIp: true,
|
|
336
|
+
useDhcp: true, // obtain IP from LAN DHCP server
|
|
337
|
+
});
|
|
338
|
+
|
|
339
|
+
// Client on a specific VLAN
|
|
340
|
+
await server.createClient({
|
|
341
|
+
clientId: 'iot-sensor',
|
|
342
|
+
useHostIp: true,
|
|
343
|
+
forceVlan: true,
|
|
344
|
+
vlanId: 100, // 802.1Q VLAN ID (1-4094)
|
|
345
|
+
});
|
|
346
|
+
|
|
347
|
+
// Regular NAT client (default, no bridge)
|
|
348
|
+
await server.createClient({
|
|
349
|
+
clientId: 'remote-worker',
|
|
350
|
+
// useHostIp defaults to false → uses socket NAT
|
|
351
|
+
});
|
|
352
|
+
```
|
|
353
|
+
|
|
354
|
+
| Field | Type | Description |
|
|
355
|
+
|-------|------|-------------|
|
|
356
|
+
| `useHostIp` | `boolean` | `true` = bridge to LAN (host IP), `false` = VPN subnet via NAT (default) |
|
|
357
|
+
| `useDhcp` | `boolean` | When `useHostIp` is true, obtain IP via DHCP relay instead of static/auto-assign |
|
|
358
|
+
| `staticIp` | `string` | Fixed LAN IP when `useHostIp` is true and `useDhcp` is false |
|
|
359
|
+
| `forceVlan` | `boolean` | Assign this client to a specific 802.1Q VLAN on the bridge |
|
|
360
|
+
| `vlanId` | `number` | VLAN ID (1-4094), required when `forceVlan` is true |
|
|
361
|
+
|
|
362
|
+
VLAN support uses Linux bridge VLAN filtering — each client's TAP port gets tagged with the specified VLAN ID, isolating traffic at Layer 2.
|
|
363
|
+
|
|
308
364
|
### 📊 Telemetry & QoS
|
|
309
365
|
|
|
310
366
|
- **Connection quality**: Smoothed RTT, jitter, min/max RTT, loss ratio, link health (`healthy` / `degraded` / `critical`)
|
|
@@ -473,9 +529,9 @@ server.on('reconnected', () => { /* socket transport reconnected */ });
|
|
|
473
529
|
|
|
474
530
|
| Interface | Purpose |
|
|
475
531
|
|-----------|---------|
|
|
476
|
-
| `IVpnServerConfig` | Server configuration (listen addr, keys, subnet, transport mode, forwarding mode incl. bridge, clients, proxy protocol, destination policy) |
|
|
532
|
+
| `IVpnServerConfig` | Server configuration (listen addr, keys, subnet, transport mode, forwarding mode incl. bridge/hybrid, clients, proxy protocol, destination policy) |
|
|
477
533
|
| `IVpnClientConfig` | Client configuration (server URL, keys, transport, forwarding mode, WG options, client-defined tags) |
|
|
478
|
-
| `IClientEntry` | Server-side client definition (ID, keys, security, priority, server/client tags, expiry) |
|
|
534
|
+
| `IClientEntry` | Server-side client definition (ID, keys, security, priority, server/client tags, expiry, bridge/VLAN settings) |
|
|
479
535
|
| `IClientSecurity` | Per-client ACLs, rate limits, and destination policy override (SmartProxy-aligned naming) |
|
|
480
536
|
| `IClientRateLimit` | Rate limiting config (bytesPerSec, burstBytes) |
|
|
481
537
|
| `IClientConfigBundle` | Full config bundle returned by `createClient()` — includes SmartVPN config, WireGuard .conf, and secrets |
|
package/ts/00_commitinfo_data.ts
CHANGED
|
@@ -92,8 +92,9 @@ export interface IVpnServerConfig {
|
|
|
92
92
|
/** Enable NAT/masquerade for client traffic */
|
|
93
93
|
enableNat?: boolean;
|
|
94
94
|
/** Forwarding mode: 'tun' (kernel TUN, requires root), 'socket' (userspace NAT),
|
|
95
|
+
* 'bridge' (L2 bridge to host LAN), 'hybrid' (per-client socket+bridge),
|
|
95
96
|
* or 'testing' (monitoring only). Default: 'testing'. */
|
|
96
|
-
forwardingMode?: 'tun' | 'socket' | 'bridge' | 'testing';
|
|
97
|
+
forwardingMode?: 'tun' | 'socket' | 'bridge' | 'hybrid' | 'testing';
|
|
97
98
|
/** Default rate limit for new clients (bytes/sec). Omit for unlimited. */
|
|
98
99
|
defaultRateLimitBytesPerSec?: number;
|
|
99
100
|
/** Default burst size for new clients (bytes). Omit for unlimited. */
|
|
@@ -361,6 +362,21 @@ export interface IClientEntry {
|
|
|
361
362
|
expiresAt?: string;
|
|
362
363
|
/** Assigned VPN IP address (set by server) */
|
|
363
364
|
assignedIp?: string;
|
|
365
|
+
|
|
366
|
+
// Per-client bridge/host-IP settings
|
|
367
|
+
|
|
368
|
+
/** If true, client gets a host network IP via bridge mode (L2 to LAN).
|
|
369
|
+
* If false (default), client gets a VPN subnet IP via socket/NAT mode. */
|
|
370
|
+
useHostIp?: boolean;
|
|
371
|
+
/** If true and useHostIp is true, obtain IP via DHCP relay.
|
|
372
|
+
* If false or omitted, use staticIp or auto-assign from bridge IP range. */
|
|
373
|
+
useDhcp?: boolean;
|
|
374
|
+
/** Static LAN IP when useHostIp is true and useDhcp is false. */
|
|
375
|
+
staticIp?: string;
|
|
376
|
+
/** If true, assign this client to a specific 802.1Q VLAN on the bridge. */
|
|
377
|
+
forceVlan?: boolean;
|
|
378
|
+
/** 802.1Q VLAN ID (1-4094). Required when forceVlan is true. */
|
|
379
|
+
vlanId?: number;
|
|
364
380
|
}
|
|
365
381
|
|
|
366
382
|
/**
|