@push.rocks/smartproxy 26.2.4 → 27.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.
Files changed (64) hide show
  1. package/changelog.md +16 -0
  2. package/dist_rust/rustproxy_linux_amd64 +0 -0
  3. package/dist_rust/rustproxy_linux_arm64 +0 -0
  4. package/dist_ts/00_commitinfo_data.js +1 -1
  5. package/dist_ts/core/models/wrapped-socket.js +4 -1
  6. package/dist_ts/core/routing/route-manager.js +9 -7
  7. package/dist_ts/plugins.d.ts +2 -1
  8. package/dist_ts/plugins.js +3 -2
  9. package/dist_ts/proxies/smart-proxy/datagram-handler-server.js +7 -5
  10. package/dist_ts/proxies/smart-proxy/route-preprocessor.js +6 -8
  11. package/dist_ts/proxies/smart-proxy/rust-metrics-adapter.js +186 -184
  12. package/dist_ts/proxies/smart-proxy/rust-proxy-bridge.d.ts +0 -1
  13. package/dist_ts/proxies/smart-proxy/rust-proxy-bridge.js +2 -4
  14. package/dist_ts/proxies/smart-proxy/smart-proxy.d.ts +9 -4
  15. package/dist_ts/proxies/smart-proxy/smart-proxy.js +70 -10
  16. package/dist_ts/proxies/smart-proxy/socket-handler-server.js +5 -3
  17. package/dist_ts/proxies/smart-proxy/utils/concurrency-semaphore.js +4 -3
  18. package/dist_ts/proxies/smart-proxy/utils/index.d.ts +2 -3
  19. package/dist_ts/proxies/smart-proxy/utils/index.js +4 -6
  20. package/dist_ts/proxies/smart-proxy/utils/mutex.js +3 -5
  21. package/dist_ts/proxies/smart-proxy/utils/route-validator.js +7 -7
  22. package/dist_ts/proxies/smart-proxy/utils/{route-helpers/socket-handlers.d.ts → socket-handlers.d.ts} +2 -10
  23. package/dist_ts/proxies/smart-proxy/utils/socket-handlers.js +268 -0
  24. package/dist_ts/routing/models/http-types.js +5 -1
  25. package/package.json +2 -1
  26. package/readme.hints.md +42 -20
  27. package/readme.md +165 -163
  28. package/ts/00_commitinfo_data.ts +1 -1
  29. package/ts/plugins.ts +2 -0
  30. package/ts/proxies/smart-proxy/rust-proxy-bridge.ts +0 -5
  31. package/ts/proxies/smart-proxy/smart-proxy.ts +67 -5
  32. package/ts/proxies/smart-proxy/utils/index.ts +3 -11
  33. package/ts/proxies/smart-proxy/utils/{route-helpers/socket-handlers.ts → socket-handlers.ts} +3 -31
  34. package/dist_ts/proxies/smart-proxy/utils/route-helpers/api-helpers.d.ts +0 -49
  35. package/dist_ts/proxies/smart-proxy/utils/route-helpers/api-helpers.js +0 -108
  36. package/dist_ts/proxies/smart-proxy/utils/route-helpers/dynamic-helpers.d.ts +0 -57
  37. package/dist_ts/proxies/smart-proxy/utils/route-helpers/dynamic-helpers.js +0 -90
  38. package/dist_ts/proxies/smart-proxy/utils/route-helpers/http-helpers.d.ts +0 -17
  39. package/dist_ts/proxies/smart-proxy/utils/route-helpers/http-helpers.js +0 -32
  40. package/dist_ts/proxies/smart-proxy/utils/route-helpers/https-helpers.d.ts +0 -68
  41. package/dist_ts/proxies/smart-proxy/utils/route-helpers/https-helpers.js +0 -117
  42. package/dist_ts/proxies/smart-proxy/utils/route-helpers/index.d.ts +0 -17
  43. package/dist_ts/proxies/smart-proxy/utils/route-helpers/index.js +0 -27
  44. package/dist_ts/proxies/smart-proxy/utils/route-helpers/load-balancer-helpers.d.ts +0 -63
  45. package/dist_ts/proxies/smart-proxy/utils/route-helpers/load-balancer-helpers.js +0 -105
  46. package/dist_ts/proxies/smart-proxy/utils/route-helpers/nftables-helpers.d.ts +0 -83
  47. package/dist_ts/proxies/smart-proxy/utils/route-helpers/nftables-helpers.js +0 -126
  48. package/dist_ts/proxies/smart-proxy/utils/route-helpers/security-helpers.d.ts +0 -47
  49. package/dist_ts/proxies/smart-proxy/utils/route-helpers/security-helpers.js +0 -66
  50. package/dist_ts/proxies/smart-proxy/utils/route-helpers/socket-handlers.js +0 -286
  51. package/dist_ts/proxies/smart-proxy/utils/route-helpers/websocket-helpers.d.ts +0 -46
  52. package/dist_ts/proxies/smart-proxy/utils/route-helpers/websocket-helpers.js +0 -67
  53. package/dist_ts/proxies/smart-proxy/utils/route-helpers.d.ts +0 -9
  54. package/dist_ts/proxies/smart-proxy/utils/route-helpers.js +0 -11
  55. package/ts/proxies/smart-proxy/utils/route-helpers/api-helpers.ts +0 -144
  56. package/ts/proxies/smart-proxy/utils/route-helpers/dynamic-helpers.ts +0 -125
  57. package/ts/proxies/smart-proxy/utils/route-helpers/http-helpers.ts +0 -40
  58. package/ts/proxies/smart-proxy/utils/route-helpers/https-helpers.ts +0 -163
  59. package/ts/proxies/smart-proxy/utils/route-helpers/index.ts +0 -62
  60. package/ts/proxies/smart-proxy/utils/route-helpers/load-balancer-helpers.ts +0 -154
  61. package/ts/proxies/smart-proxy/utils/route-helpers/nftables-helpers.ts +0 -202
  62. package/ts/proxies/smart-proxy/utils/route-helpers/security-helpers.ts +0 -96
  63. package/ts/proxies/smart-proxy/utils/route-helpers/websocket-helpers.ts +0 -98
  64. package/ts/proxies/smart-proxy/utils/route-helpers.ts +0 -11
package/readme.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # @push.rocks/smartproxy 🚀
2
2
 
3
- **A high-performance, Rust-powered proxy toolkit for Node.js** — unified route-based configuration for SSL/TLS termination, HTTP/HTTPS reverse proxying, WebSocket support, UDP/QUIC/HTTP3, load balancing, custom protocol handlers, and kernel-level NFTables forwarding.
3
+ **A high-performance, Rust-powered proxy toolkit for Node.js** — unified route-based configuration for SSL/TLS termination, HTTP/HTTPS reverse proxying, WebSocket support, UDP/QUIC/HTTP3, load balancing, custom protocol handlers, and kernel-level NFTables forwarding via [`@push.rocks/smartnftables`](https://code.foss.global/push.rocks/smartnftables).
4
4
 
5
5
  ## 📦 Installation
6
6
 
@@ -44,7 +44,7 @@ Whether you're building microservices, deploying edge infrastructure, proxying U
44
44
  Get up and running in 30 seconds:
45
45
 
46
46
  ```typescript
47
- import { SmartProxy, createCompleteHttpsServer } from '@push.rocks/smartproxy';
47
+ import { SmartProxy, SocketHandlers } from '@push.rocks/smartproxy';
48
48
 
49
49
  // Create a proxy with automatic HTTPS
50
50
  const proxy = new SmartProxy({
@@ -53,13 +53,25 @@ const proxy = new SmartProxy({
53
53
  useProduction: true
54
54
  },
55
55
  routes: [
56
- // Complete HTTPS setup in one call!
57
- ...createCompleteHttpsServer('app.example.com', {
58
- host: 'localhost',
59
- port: 3000
60
- }, {
61
- certificate: 'auto' // Automatic Let's Encrypt cert 🎩
62
- })
56
+ // HTTPS route with automatic Let's Encrypt cert
57
+ {
58
+ name: 'https-app',
59
+ match: { ports: 443, domains: 'app.example.com' },
60
+ action: {
61
+ type: 'forward',
62
+ targets: [{ host: 'localhost', port: 3000 }],
63
+ tls: { mode: 'terminate', certificate: 'auto' }
64
+ }
65
+ },
66
+ // HTTP → HTTPS redirect
67
+ {
68
+ name: 'http-redirect',
69
+ match: { ports: 80, domains: 'app.example.com' },
70
+ action: {
71
+ type: 'socket-handler',
72
+ socketHandler: SocketHandlers.httpRedirect('https://{domain}:443{path}', 301)
73
+ }
74
+ }
63
75
  ]
64
76
  });
65
77
 
@@ -111,31 +123,38 @@ SmartProxy supports three TLS handling modes:
111
123
  ### 🌐 HTTP to HTTPS Redirect
112
124
 
113
125
  ```typescript
114
- import { SmartProxy, createHttpToHttpsRedirect } from '@push.rocks/smartproxy';
126
+ import { SmartProxy, SocketHandlers } from '@push.rocks/smartproxy';
115
127
 
116
128
  const proxy = new SmartProxy({
117
- routes: [
118
- createHttpToHttpsRedirect(['example.com', '*.example.com'])
119
- ]
129
+ routes: [{
130
+ name: 'http-to-https',
131
+ match: { ports: 80, domains: ['example.com', '*.example.com'] },
132
+ action: {
133
+ type: 'socket-handler',
134
+ socketHandler: SocketHandlers.httpRedirect('https://{domain}:443{path}', 301)
135
+ }
136
+ }]
120
137
  });
121
138
  ```
122
139
 
123
140
  ### ⚖️ Load Balancer with Health Checks
124
141
 
125
142
  ```typescript
126
- import { SmartProxy, createLoadBalancerRoute } from '@push.rocks/smartproxy';
143
+ import { SmartProxy } from '@push.rocks/smartproxy';
127
144
 
128
145
  const proxy = new SmartProxy({
129
- routes: [
130
- createLoadBalancerRoute(
131
- 'app.example.com',
132
- [
146
+ routes: [{
147
+ name: 'load-balancer',
148
+ match: { ports: 443, domains: 'app.example.com' },
149
+ action: {
150
+ type: 'forward',
151
+ targets: [
133
152
  { host: 'server1.internal', port: 8080 },
134
153
  { host: 'server2.internal', port: 8080 },
135
154
  { host: 'server3.internal', port: 8080 }
136
155
  ],
137
- {
138
- tls: { mode: 'terminate', certificate: 'auto' },
156
+ tls: { mode: 'terminate', certificate: 'auto' },
157
+ loadBalancing: {
139
158
  algorithm: 'round-robin',
140
159
  healthCheck: {
141
160
  path: '/health',
@@ -145,57 +164,68 @@ const proxy = new SmartProxy({
145
164
  healthyThreshold: 2
146
165
  }
147
166
  }
148
- )
149
- ]
167
+ }
168
+ }]
150
169
  });
151
170
  ```
152
171
 
153
172
  ### 🔌 WebSocket Proxy
154
173
 
155
174
  ```typescript
156
- import { SmartProxy, createWebSocketRoute } from '@push.rocks/smartproxy';
175
+ import { SmartProxy } from '@push.rocks/smartproxy';
157
176
 
158
177
  const proxy = new SmartProxy({
159
- routes: [
160
- createWebSocketRoute(
161
- 'ws.example.com',
162
- { host: 'websocket-server', port: 8080 },
163
- {
164
- path: '/socket',
165
- useTls: true,
166
- certificate: 'auto',
178
+ routes: [{
179
+ name: 'websocket',
180
+ match: { ports: 443, domains: 'ws.example.com', path: '/socket' },
181
+ priority: 100,
182
+ action: {
183
+ type: 'forward',
184
+ targets: [{ host: 'websocket-server', port: 8080 }],
185
+ tls: { mode: 'terminate', certificate: 'auto' },
186
+ websocket: {
187
+ enabled: true,
167
188
  pingInterval: 30000,
168
189
  pingTimeout: 10000
169
190
  }
170
- )
171
- ]
191
+ }
192
+ }]
172
193
  });
173
194
  ```
174
195
 
175
196
  ### 🚦 API Gateway with Rate Limiting
176
197
 
177
198
  ```typescript
178
- import { SmartProxy, createApiGatewayRoute, addRateLimiting } from '@push.rocks/smartproxy';
179
-
180
- let apiRoute = createApiGatewayRoute(
181
- 'api.example.com',
182
- '/api',
183
- { host: 'api-backend', port: 8080 },
184
- {
185
- useTls: true,
186
- certificate: 'auto',
187
- addCorsHeaders: true
188
- }
189
- );
199
+ import { SmartProxy } from '@push.rocks/smartproxy';
190
200
 
191
- // Add rate limiting — 100 requests per minute per IP
192
- apiRoute = addRateLimiting(apiRoute, {
193
- maxRequests: 100,
194
- window: 60,
195
- keyBy: 'ip'
201
+ const proxy = new SmartProxy({
202
+ routes: [{
203
+ name: 'api-gateway',
204
+ match: { ports: 443, domains: 'api.example.com', path: '/api/*' },
205
+ priority: 100,
206
+ action: {
207
+ type: 'forward',
208
+ targets: [{ host: 'api-backend', port: 8080 }],
209
+ tls: { mode: 'terminate', certificate: 'auto' }
210
+ },
211
+ headers: {
212
+ response: {
213
+ 'Access-Control-Allow-Origin': '*',
214
+ 'Access-Control-Allow-Methods': 'GET, POST, PUT, DELETE, OPTIONS',
215
+ 'Access-Control-Allow-Headers': 'Content-Type, Authorization',
216
+ 'Access-Control-Max-Age': '86400'
217
+ }
218
+ },
219
+ security: {
220
+ rateLimit: {
221
+ enabled: true,
222
+ maxRequests: 100,
223
+ window: 60,
224
+ keyBy: 'ip'
225
+ }
226
+ }
227
+ }]
196
228
  });
197
-
198
- const proxy = new SmartProxy({ routes: [apiRoute] });
199
229
  ```
200
230
 
201
231
  ### 🎮 Custom Protocol Handler (TCP)
@@ -203,36 +233,40 @@ const proxy = new SmartProxy({ routes: [apiRoute] });
203
233
  SmartProxy lets you implement any protocol with full socket control. Routes with JavaScript socket handlers are automatically relayed from the Rust engine back to your TypeScript code:
204
234
 
205
235
  ```typescript
206
- import { SmartProxy, createSocketHandlerRoute, SocketHandlers } from '@push.rocks/smartproxy';
207
-
208
- // Use pre-built handlers
209
- const echoRoute = createSocketHandlerRoute(
210
- 'echo.example.com',
211
- 7777,
212
- SocketHandlers.echo
213
- );
214
-
215
- // Or create your own custom protocol
216
- const customRoute = createSocketHandlerRoute(
217
- 'custom.example.com',
218
- 9999,
219
- async (socket) => {
220
- console.log(`New connection on custom protocol`);
221
- socket.write('Welcome to my custom protocol!\n');
222
-
223
- socket.on('data', (data) => {
224
- const command = data.toString().trim();
225
- switch (command) {
226
- case 'PING': socket.write('PONG\n'); break;
227
- case 'TIME': socket.write(`${new Date().toISOString()}\n`); break;
228
- case 'QUIT': socket.end('Goodbye!\n'); break;
229
- default: socket.write(`Unknown: ${command}\n`);
230
- }
231
- });
232
- }
233
- );
236
+ import { SmartProxy, SocketHandlers } from '@push.rocks/smartproxy';
234
237
 
235
- const proxy = new SmartProxy({ routes: [echoRoute, customRoute] });
238
+ const proxy = new SmartProxy({
239
+ routes: [
240
+ // Use pre-built handlers
241
+ {
242
+ name: 'echo-server',
243
+ match: { ports: 7777, domains: 'echo.example.com' },
244
+ action: { type: 'socket-handler', socketHandler: SocketHandlers.echo }
245
+ },
246
+ // Or create your own custom protocol
247
+ {
248
+ name: 'custom-protocol',
249
+ match: { ports: 9999, domains: 'custom.example.com' },
250
+ action: {
251
+ type: 'socket-handler',
252
+ socketHandler: async (socket) => {
253
+ console.log(`New connection on custom protocol`);
254
+ socket.write('Welcome to my custom protocol!\n');
255
+
256
+ socket.on('data', (data) => {
257
+ const command = data.toString().trim();
258
+ switch (command) {
259
+ case 'PING': socket.write('PONG\n'); break;
260
+ case 'TIME': socket.write(`${new Date().toISOString()}\n`); break;
261
+ case 'QUIT': socket.end('Goodbye!\n'); break;
262
+ default: socket.write(`Unknown: ${command}\n`);
263
+ }
264
+ });
265
+ }
266
+ }
267
+ }
268
+ ]
269
+ });
236
270
  ```
237
271
 
238
272
  **Pre-built Socket Handlers:**
@@ -384,23 +418,26 @@ const dualStackRoute: IRouteConfig = {
384
418
 
385
419
  ### ⚡ High-Performance NFTables Forwarding
386
420
 
387
- For ultra-low latency on Linux, use kernel-level forwarding (requires root):
421
+ For ultra-low latency on Linux, use kernel-level forwarding via [`@push.rocks/smartnftables`](https://code.foss.global/push.rocks/smartnftables) (requires root):
388
422
 
389
423
  ```typescript
390
- import { SmartProxy, createNfTablesTerminateRoute } from '@push.rocks/smartproxy';
424
+ import { SmartProxy } from '@push.rocks/smartproxy';
391
425
 
392
426
  const proxy = new SmartProxy({
393
- routes: [
394
- createNfTablesTerminateRoute(
395
- 'fast.example.com',
396
- { host: 'backend', port: 8080 },
397
- {
398
- ports: 443,
399
- certificate: 'auto',
427
+ routes: [{
428
+ name: 'nftables-fast',
429
+ match: { ports: 443, domains: 'fast.example.com' },
430
+ action: {
431
+ type: 'forward',
432
+ forwardingEngine: 'nftables',
433
+ targets: [{ host: 'backend', port: 8080 }],
434
+ tls: { mode: 'terminate', certificate: 'auto' },
435
+ nftables: {
436
+ protocol: 'tcp',
400
437
  preserveSourceIP: true // Backend sees real client IP
401
438
  }
402
- )
403
- ]
439
+ }
440
+ }]
404
441
  });
405
442
  ```
406
443
 
@@ -409,15 +446,18 @@ const proxy = new SmartProxy({
409
446
  Forward encrypted traffic to backends without terminating TLS — the proxy routes based on the SNI hostname alone:
410
447
 
411
448
  ```typescript
412
- import { SmartProxy, createHttpsPassthroughRoute } from '@push.rocks/smartproxy';
449
+ import { SmartProxy } from '@push.rocks/smartproxy';
413
450
 
414
451
  const proxy = new SmartProxy({
415
- routes: [
416
- createHttpsPassthroughRoute('secure.example.com', {
417
- host: 'backend-that-handles-tls',
418
- port: 8443
419
- })
420
- ]
452
+ routes: [{
453
+ name: 'sni-passthrough',
454
+ match: { ports: 443, domains: 'secure.example.com' },
455
+ action: {
456
+ type: 'forward',
457
+ targets: [{ host: 'backend-that-handles-tls', port: 8443 }],
458
+ tls: { mode: 'passthrough' }
459
+ }
460
+ }]
421
461
  });
422
462
  ```
423
463
 
@@ -524,15 +564,7 @@ Comprehensive per-route security options:
524
564
  }
525
565
  ```
526
566
 
527
- **Security modifier helpers** let you add security to any existing route:
528
-
529
- ```typescript
530
- import { addRateLimiting, addBasicAuth, addJwtAuth } from '@push.rocks/smartproxy';
531
-
532
- let route = createHttpsTerminateRoute('api.example.com', { host: 'backend', port: 8080 });
533
- route = addRateLimiting(route, { maxRequests: 100, window: 60, keyBy: 'ip' });
534
- route = addBasicAuth(route, { users: [{ username: 'admin', password: 'secret' }] });
535
- ```
567
+ Security options are configured directly on each route's `security` property no separate helpers needed.
536
568
 
537
569
  ### 📊 Runtime Management
538
570
 
@@ -694,22 +726,26 @@ SmartProxy uses a hybrid **Rust + TypeScript** architecture:
694
726
  │ │ Listener│ │ Reverse │ │ Matcher │ │ Cert Mgr │ │
695
727
  │ │ │ │ Proxy │ │ │ │ │ │
696
728
  │ └─────────┘ └─────────┘ └─────────┘ └──────────┘ │
697
- │ ┌─────────┐ ┌─────────┐ ┌─────────┐ ┌──────────┐
698
- │ │ UDP │ │ Security│ │ Metrics │ NFTables │ │
699
- │ │ QUIC │ │ Enforce │ │ Collect │ Mgr │ │
700
- │ │ HTTP/3 │ │ │ │ │ │ │
701
- │ └─────────┘ └─────────┘ └─────────┘ └──────────┘
729
+ │ ┌─────────┐ ┌─────────┐ ┌─────────┐
730
+ │ │ UDP │ │ Security│ │ Metrics │
731
+ │ │ QUIC │ │ Enforce │ │ Collect │
732
+ │ │ HTTP/3 │ │ │ │ │
733
+ │ └─────────┘ └─────────┘ └─────────┘
702
734
  └──────────────────┬──────────────────────────────────┘
703
735
  │ Unix Socket Relay
704
736
  ┌──────────────────▼──────────────────────────────────┐
705
737
  │ TypeScript Socket & Datagram Handler Servers │
706
738
  │ (for JS socket handlers, datagram handlers, │
707
739
  │ and dynamic routes) │
740
+ ├─────────────────────────────────────────────────────┤
741
+ │ @push.rocks/smartnftables (kernel-level NFTables) │
742
+ │ (DNAT/SNAT, firewall, rate limiting via nft CLI) │
708
743
  └─────────────────────────────────────────────────────┘
709
744
  ```
710
745
 
711
746
  - **Rust Engine** handles all networking: TCP, UDP, TLS, QUIC, HTTP proxying, connection management, security, and metrics
712
- - **TypeScript** provides the npm API, configuration types, route helpers, validation, and handler callbacks
747
+ - **TypeScript** provides the npm API, configuration types, validation, and handler callbacks
748
+ - **NFTables** managed by [`@push.rocks/smartnftables`](https://code.foss.global/push.rocks/smartnftables) — kernel-level DNAT/SNAT forwarding, firewall rules, and rate limiting via the `nft` CLI
713
749
  - **IPC** — The TypeScript wrapper uses JSON commands/events over stdin/stdout to communicate with the Rust binary
714
750
  - **Socket/Datagram Relay** — Unix domain socket servers for routes requiring TypeScript-side handling (socket handlers, datagram handlers, dynamic host/port functions)
715
751
 
@@ -854,47 +890,13 @@ interface IRouteQuic {
854
890
  }
855
891
  ```
856
892
 
857
- ## 🛠️ Helper Functions Reference
858
-
859
- All helpers are fully typed and return `IRouteConfig` or `IRouteConfig[]`:
893
+ ## 🛠️ Exports Reference
860
894
 
861
895
  ```typescript
862
896
  import {
863
- // HTTP/HTTPS
864
- createHttpRoute, // Plain HTTP route
865
- createHttpsTerminateRoute, // HTTPS with TLS termination
866
- createHttpsPassthroughRoute, // SNI passthrough (no termination)
867
- createHttpToHttpsRedirect, // HTTP → HTTPS redirect
868
- createCompleteHttpsServer, // HTTPS + redirect combo (returns IRouteConfig[])
869
-
870
- // Load Balancing
871
- createLoadBalancerRoute, // Multi-backend with health checks
872
- createSmartLoadBalancer, // Dynamic domain-based backend selection
873
-
874
- // API & WebSocket
875
- createApiRoute, // API route with path matching
876
- createApiGatewayRoute, // API gateway with CORS
877
- createWebSocketRoute, // WebSocket-enabled route
878
-
879
- // Custom Protocols
880
- createSocketHandlerRoute, // Custom TCP socket handler
881
- SocketHandlers, // Pre-built handlers (echo, proxy, block, etc.)
882
-
883
- // NFTables (Linux, requires root)
884
- createNfTablesRoute, // Kernel-level packet forwarding
885
- createNfTablesTerminateRoute, // NFTables + TLS termination
886
- createCompleteNfTablesHttpsServer, // NFTables HTTPS + redirect combo
887
-
888
- // Dynamic Routing
889
- createPortMappingRoute, // Port mapping with context
890
- createOffsetPortMappingRoute, // Simple port offset
891
- createDynamicRoute, // Dynamic host/port via functions
892
- createPortOffset, // Port offset factory
893
-
894
- // Security Modifiers
895
- addRateLimiting, // Add rate limiting to any route
896
- addBasicAuth, // Add basic auth to any route
897
- addJwtAuth, // Add JWT auth to any route
897
+ // Core
898
+ SmartProxy, // Main proxy class
899
+ SocketHandlers, // Pre-built socket handlers (echo, proxy, block, httpRedirect, httpServer, etc.)
898
900
 
899
901
  // Route Utilities
900
902
  mergeRouteConfigs, // Deep-merge two route configs
@@ -906,7 +908,7 @@ import {
906
908
  } from '@push.rocks/smartproxy';
907
909
  ```
908
910
 
909
- > **Tip:** For UDP datagram handler routes or QUIC/HTTP3 routes, construct `IRouteConfig` objects directly there are no helper functions for these yet. See the [UDP Datagram Handler](#-udp-datagram-handler) and [QUIC / HTTP3 Forwarding](#-quic--http3-forwarding) examples above.
911
+ All routes are configured as plain `IRouteConfig` objects with `match` and `action` properties see the examples throughout this document.
910
912
 
911
913
  ## 📖 API Documentation
912
914
 
@@ -938,8 +940,8 @@ class SmartProxy extends EventEmitter {
938
940
  getCertificateStatus(routeName: string): Promise<any>;
939
941
  getEligibleDomainsForCertificates(): string[];
940
942
 
941
- // NFTables
942
- getNfTablesStatus(): Promise<Record<string, any>>;
943
+ // NFTables (managed by @push.rocks/smartnftables)
944
+ getNfTablesStatus(): INftStatus | null;
943
945
 
944
946
  // Events
945
947
  on(event: 'error', handler: (err: Error) => void): this;
@@ -991,11 +993,11 @@ interface ISmartProxyOptions {
991
993
  sendProxyProtocol?: boolean; // Send PROXY protocol to targets
992
994
 
993
995
  // Timeouts
994
- connectionTimeout?: number; // Backend connection timeout (default: 30s)
995
- initialDataTimeout?: number; // Initial data/SNI timeout (default: 120s)
996
- socketTimeout?: number; // Socket inactivity timeout (default: 1h)
997
- maxConnectionLifetime?: number; // Max connection lifetime (default: 24h)
998
- inactivityTimeout?: number; // Inactivity timeout (default: 4h)
996
+ connectionTimeout?: number; // Backend connection timeout (default: 60s)
997
+ initialDataTimeout?: number; // Initial data/SNI timeout (default: 60s)
998
+ socketTimeout?: number; // Socket inactivity timeout (default: 60s)
999
+ maxConnectionLifetime?: number; // Max connection lifetime (default: 1h)
1000
+ inactivityTimeout?: number; // Inactivity timeout (default: 75s)
999
1001
  gracefulShutdownTimeout?: number; // Shutdown grace period (default: 30s)
1000
1002
 
1001
1003
  // Connection limits
@@ -1004,8 +1006,8 @@ interface ISmartProxyOptions {
1004
1006
 
1005
1007
  // Keep-alive
1006
1008
  keepAliveTreatment?: 'standard' | 'extended' | 'immortal';
1007
- keepAliveInactivityMultiplier?: number; // (default: 6)
1008
- extendedKeepAliveLifetime?: number; // (default: 7 days)
1009
+ keepAliveInactivityMultiplier?: number; // (default: 4)
1010
+ extendedKeepAliveLifetime?: number; // (default: 1h)
1009
1011
 
1010
1012
  // Metrics
1011
1013
  metrics?: {
@@ -1137,7 +1139,7 @@ SmartProxy searches for the Rust binary in this order:
1137
1139
 
1138
1140
  ## License and Legal Information
1139
1141
 
1140
- This repository contains open-source code licensed under the MIT License. A copy of the license can be found in the [LICENSE](./LICENSE) file.
1142
+ This repository contains open-source code licensed under the MIT License. A copy of the license can be found in the [license](./license) file.
1141
1143
 
1142
1144
  **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.
1143
1145
 
@@ -3,6 +3,6 @@
3
3
  */
4
4
  export const commitinfo = {
5
5
  name: '@push.rocks/smartproxy',
6
- version: '26.2.4',
6
+ version: '27.0.0',
7
7
  description: 'A powerful proxy package with unified route-based configuration for high traffic management. Features include SSL/TLS support, flexible routing patterns, WebSocket handling, advanced security options, and automatic ACME certificate management.'
8
8
  }
package/ts/plugins.ts CHANGED
@@ -19,12 +19,14 @@ export { tsclass };
19
19
  import * as smartcrypto from '@push.rocks/smartcrypto';
20
20
  import * as smartlog from '@push.rocks/smartlog';
21
21
  import * as smartlogDestinationLocal from '@push.rocks/smartlog/destination-local';
22
+ import * as smartnftables from '@push.rocks/smartnftables';
22
23
  import * as smartrust from '@push.rocks/smartrust';
23
24
 
24
25
  export {
25
26
  smartcrypto,
26
27
  smartlog,
27
28
  smartlogDestinationLocal,
29
+ smartnftables,
28
30
  smartrust,
29
31
  };
30
32
 
@@ -15,7 +15,6 @@ type TSmartProxyCommands = {
15
15
  renewCertificate: { params: { routeName: string }; result: void };
16
16
  getCertificateStatus: { params: { routeName: string }; result: any };
17
17
  getListeningPorts: { params: Record<string, never>; result: { ports: number[] } };
18
- getNftablesStatus: { params: Record<string, never>; result: any };
19
18
  setSocketHandlerRelay: { params: { socketPath: string }; result: void };
20
19
  addListeningPort: { params: { port: number }; result: void };
21
20
  removeListeningPort: { params: { port: number }; result: void };
@@ -159,10 +158,6 @@ export class RustProxyBridge extends plugins.EventEmitter {
159
158
  return result?.ports ?? [];
160
159
  }
161
160
 
162
- public async getNftablesStatus(): Promise<any> {
163
- return this.bridge.sendCommand('getNftablesStatus', {} as Record<string, never>);
164
- }
165
-
166
161
  public async setSocketHandlerRelay(socketPath: string): Promise<void> {
167
162
  await this.bridge.sendCommand('setSocketHandlerRelay', { socketPath });
168
163
  }
@@ -23,8 +23,8 @@ import type { IMetrics } from './models/metrics-types.js';
23
23
  /**
24
24
  * SmartProxy - Rust-backed proxy engine with TypeScript configuration API.
25
25
  *
26
- * All networking (TCP, TLS, HTTP reverse proxy, connection management, security,
27
- * NFTables) is handled by the Rust binary. TypeScript is only:
26
+ * All networking (TCP, TLS, HTTP reverse proxy, connection management, security)
27
+ * is handled by the Rust binary. TypeScript is only:
28
28
  * - The npm module interface (types, route helpers)
29
29
  * - The thin IPC wrapper (this class)
30
30
  * - Socket-handler callback relay (for JS-defined handlers)
@@ -39,6 +39,7 @@ export class SmartProxy extends plugins.EventEmitter {
39
39
  private socketHandlerServer: SocketHandlerServer | null = null;
40
40
  private datagramHandlerServer: DatagramHandlerServer | null = null;
41
41
  private metricsAdapter: RustMetricsAdapter;
42
+ private nftablesManager: InstanceType<typeof plugins.smartnftables.SmartNftables> | null = null;
42
43
  private routeUpdateLock: Mutex;
43
44
  private stopping = false;
44
45
  private certProvisionPromise: Promise<void> | null = null;
@@ -211,6 +212,9 @@ export class SmartProxy extends plugins.EventEmitter {
211
212
  }
212
213
  }
213
214
 
215
+ // Apply NFTables rules for routes using nftables forwarding engine
216
+ await this.applyNftablesRules(this.settings.routes);
217
+
214
218
  // Start metrics polling BEFORE cert provisioning — the Rust engine is already
215
219
  // running and accepting connections, so metrics should be available immediately.
216
220
  // Cert provisioning can hang indefinitely (e.g. DNS-01 ACME timeouts) and must
@@ -238,6 +242,12 @@ export class SmartProxy extends plugins.EventEmitter {
238
242
  this.certProvisionPromise = null;
239
243
  }
240
244
 
245
+ // Clean up NFTables rules
246
+ if (this.nftablesManager) {
247
+ await this.nftablesManager.cleanup();
248
+ this.nftablesManager = null;
249
+ }
250
+
241
251
  // Stop metrics polling
242
252
  this.metricsAdapter.stopPolling();
243
253
 
@@ -319,6 +329,13 @@ export class SmartProxy extends plugins.EventEmitter {
319
329
  this.datagramHandlerServer = null;
320
330
  }
321
331
 
332
+ // Update NFTables rules
333
+ if (this.nftablesManager) {
334
+ await this.nftablesManager.cleanup();
335
+ this.nftablesManager = null;
336
+ }
337
+ await this.applyNftablesRules(newRoutes);
338
+
322
339
  // Update stored routes
323
340
  this.settings.routes = newRoutes;
324
341
 
@@ -411,14 +428,59 @@ export class SmartProxy extends plugins.EventEmitter {
411
428
  }
412
429
 
413
430
  /**
414
- * Get NFTables status (async - calls Rust).
431
+ * Get NFTables status.
415
432
  */
416
- public async getNfTablesStatus(): Promise<Record<string, any>> {
417
- return this.bridge.getNftablesStatus();
433
+ public getNfTablesStatus(): plugins.smartnftables.INftStatus | null {
434
+ return this.nftablesManager?.status() ?? null;
418
435
  }
419
436
 
420
437
  // --- Private helpers ---
421
438
 
439
+ /**
440
+ * Apply NFTables rules for routes using the nftables forwarding engine.
441
+ */
442
+ private async applyNftablesRules(routes: IRouteConfig[]): Promise<void> {
443
+ const nftRoutes = routes.filter(r => r.action.forwardingEngine === 'nftables');
444
+ if (nftRoutes.length === 0) return;
445
+
446
+ const tableName = nftRoutes.find(r => r.action.nftables?.tableName)?.action.nftables?.tableName ?? 'smartproxy';
447
+ const nft = new plugins.smartnftables.SmartNftables({ tableName });
448
+ await nft.initialize();
449
+
450
+ for (const route of nftRoutes) {
451
+ const routeId = route.name || 'unnamed';
452
+ const targets = route.action.targets;
453
+ if (!targets) continue;
454
+
455
+ const nftOpts = route.action.nftables;
456
+ const protocol: plugins.smartnftables.TNftProtocol = (nftOpts?.protocol as any) ?? 'tcp';
457
+ const preserveSourceIP = nftOpts?.preserveSourceIP ?? false;
458
+
459
+ const ports = Array.isArray(route.match.ports)
460
+ ? route.match.ports.flatMap(p => typeof p === 'number' ? [p] : [])
461
+ : typeof route.match.ports === 'number' ? [route.match.ports] : [];
462
+
463
+ for (const target of targets) {
464
+ const targetHost = Array.isArray(target.host) ? target.host[0] : target.host;
465
+ if (typeof targetHost !== 'string') continue;
466
+
467
+ for (const sourcePort of ports) {
468
+ const targetPort = typeof target.port === 'number' ? target.port : sourcePort;
469
+ await nft.nat.addPortForwarding(`${routeId}-${sourcePort}-${targetPort}`, {
470
+ sourcePort,
471
+ targetHost,
472
+ targetPort,
473
+ protocol,
474
+ preserveSourceIP,
475
+ });
476
+ }
477
+ }
478
+ }
479
+
480
+ this.nftablesManager = nft;
481
+ logger.log('info', `Applied NFTables rules for ${nftRoutes.length} route(s)`, { component: 'smart-proxy' });
482
+ }
483
+
422
484
  /**
423
485
  * Build the Rust configuration object from TS settings.
424
486
  */