@push.rocks/smartproxy 19.5.2 → 19.5.4
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_ts/00_commitinfo_data.js +1 -1
- package/dist_ts/proxies/http-proxy/models/types.js +2 -2
- package/dist_ts/proxies/smart-proxy/http-proxy-bridge.js +2 -5
- package/dist_ts/proxies/smart-proxy/models/route-types.d.ts +0 -1
- package/dist_ts/proxies/smart-proxy/models/route-types.js +1 -1
- package/dist_ts/proxies/smart-proxy/nftables-manager.js +5 -6
- package/dist_ts/proxies/smart-proxy/route-connection-handler.d.ts +2 -2
- package/dist_ts/proxies/smart-proxy/route-connection-handler.js +84 -5
- package/dist_ts/proxies/smart-proxy/route-manager.d.ts +2 -0
- package/dist_ts/proxies/smart-proxy/route-manager.js +7 -8
- package/dist_ts/proxies/smart-proxy/utils/route-helpers.js +10 -9
- package/package.json +2 -2
- package/readme.hints.md +131 -5
- package/readme.md +515 -301
- package/readme.problems.md +86 -0
- package/ts/00_commitinfo_data.ts +1 -1
- package/ts/proxies/http-proxy/models/types.ts +1 -1
- package/ts/proxies/smart-proxy/http-proxy-bridge.ts +1 -4
- package/ts/proxies/smart-proxy/models/route-types.ts +0 -3
- package/ts/proxies/smart-proxy/nftables-manager.ts +4 -5
- package/ts/proxies/smart-proxy/route-connection-handler.ts +97 -4
- package/ts/proxies/smart-proxy/route-manager.ts +7 -8
- package/ts/proxies/smart-proxy/utils/route-helpers.ts +11 -9
package/readme.md
CHANGED
|
@@ -6,14 +6,15 @@ A unified high-performance proxy toolkit for Node.js, with **SmartProxy** as the
|
|
|
6
6
|
- **SSL/TLS Support**: Automatic HTTPS with Let's Encrypt certificate provisioning
|
|
7
7
|
- **Flexible Matching Patterns**: Route by port, domain, path, client IP, and TLS version
|
|
8
8
|
- **Advanced SNI Handling**: Smart TCP/SNI-based forwarding with IP filtering
|
|
9
|
-
- **Multiple Action Types**: Forward
|
|
9
|
+
- **Multiple Action Types**: Forward traffic or handle with custom socket handlers
|
|
10
10
|
- **Dynamic Port Management**: Add or remove listening ports at runtime without restart
|
|
11
|
-
- **Security Features**: IP allowlists, connection limits,
|
|
11
|
+
- **Security Features**: Route-specific IP allowlists, blocklists, connection limits, and authentication
|
|
12
12
|
- **NFTables Integration**: High-performance kernel-level packet forwarding with Linux NFTables
|
|
13
|
+
- **Socket Handlers**: Custom socket handling for specialized protocols and use cases
|
|
13
14
|
|
|
14
15
|
## Project Architecture Overview
|
|
15
16
|
|
|
16
|
-
SmartProxy has been restructured using a modern, modular architecture with a unified route-based configuration system
|
|
17
|
+
SmartProxy has been restructured using a modern, modular architecture with a unified route-based configuration system:
|
|
17
18
|
|
|
18
19
|
```
|
|
19
20
|
/ts
|
|
@@ -21,10 +22,6 @@ SmartProxy has been restructured using a modern, modular architecture with a uni
|
|
|
21
22
|
│ ├── /models # Data models and interfaces
|
|
22
23
|
│ ├── /utils # Shared utilities (IP validation, logging, etc.)
|
|
23
24
|
│ └── /events # Common event definitions
|
|
24
|
-
├── /certificate # Certificate management (deprecated in v18+)
|
|
25
|
-
│ ├── /acme # Moved to SmartCertManager
|
|
26
|
-
│ ├── /providers # Now integrated in route configuration
|
|
27
|
-
│ └── /storage # Now uses CertStore
|
|
28
25
|
├── /forwarding # Forwarding system
|
|
29
26
|
│ ├── /handlers # Various forwarding handlers
|
|
30
27
|
│ │ ├── base-handler.ts # Abstract base handler
|
|
@@ -37,7 +34,7 @@ SmartProxy has been restructured using a modern, modular architecture with a uni
|
|
|
37
34
|
│ │ ├── /models # SmartProxy-specific interfaces
|
|
38
35
|
│ │ │ ├── route-types.ts # Route-based configuration types
|
|
39
36
|
│ │ │ └── interfaces.ts # SmartProxy interfaces
|
|
40
|
-
│ │ ├── certificate-manager.ts # SmartCertManager
|
|
37
|
+
│ │ ├── certificate-manager.ts # SmartCertManager
|
|
41
38
|
│ │ ├── cert-store.ts # Certificate file storage
|
|
42
39
|
│ │ ├── route-helpers.ts # Helper functions for creating routes
|
|
43
40
|
│ │ ├── route-manager.ts # Route management system
|
|
@@ -48,10 +45,8 @@ SmartProxy has been restructured using a modern, modular architecture with a uni
|
|
|
48
45
|
├── /tls # TLS-specific functionality
|
|
49
46
|
│ ├── /sni # SNI handling components
|
|
50
47
|
│ └── /alerts # TLS alerts system
|
|
51
|
-
└── /
|
|
52
|
-
|
|
53
|
-
├── /router # HTTP routing system
|
|
54
|
-
└── /redirects # Redirect handlers
|
|
48
|
+
└── /routing # Routing functionality
|
|
49
|
+
└── /router # HTTP routing system
|
|
55
50
|
```
|
|
56
51
|
|
|
57
52
|
## Main Components
|
|
@@ -62,31 +57,34 @@ SmartProxy has been restructured using a modern, modular architecture with a uni
|
|
|
62
57
|
The central unified API for all proxy needs, featuring:
|
|
63
58
|
- Route-based configuration with match/action pattern
|
|
64
59
|
- Flexible matching criteria (ports, domains, paths, client IPs)
|
|
65
|
-
- Multiple action types (forward, redirect, block)
|
|
60
|
+
- Multiple action types (forward, redirect, block, socket-handler)
|
|
66
61
|
- Automatic certificate management
|
|
67
62
|
- Advanced security controls
|
|
63
|
+
- Custom socket handling capabilities
|
|
68
64
|
|
|
69
65
|
### Helper Functions
|
|
70
66
|
|
|
71
|
-
- **
|
|
67
|
+
- **createHttpRoute**, **createHttpsTerminateRoute**, **createHttpsPassthroughRoute**
|
|
72
68
|
Helper functions to create different route configurations with clean syntax
|
|
73
|
-
- **
|
|
74
|
-
Helper
|
|
75
|
-
- **createLoadBalancerRoute**, **
|
|
69
|
+
- **createHttpToHttpsRedirect**
|
|
70
|
+
Helper function for HTTP to HTTPS redirects using socket handlers
|
|
71
|
+
- **createLoadBalancerRoute**, **createCompleteHttpsServer**
|
|
76
72
|
Helper functions for complex configurations
|
|
77
|
-
- **
|
|
73
|
+
- **createSocketHandlerRoute**, **SocketHandlers**
|
|
74
|
+
Helper functions for custom socket handling
|
|
75
|
+
- **createNfTablesRoute**, **createNfTablesTerminateRoute**, **createCompleteNfTablesHttpsServer**
|
|
78
76
|
Helper functions for NFTables-based high-performance kernel-level routing
|
|
77
|
+
- **createPortMappingRoute**, **createOffsetPortMappingRoute**, **createDynamicRoute**, **createSmartLoadBalancer**
|
|
78
|
+
Helper functions for dynamic routing and port mapping
|
|
79
|
+
- **createApiGatewayRoute**, **addRateLimiting**, **addBasicAuth**, **addJwtAuth**
|
|
80
|
+
Helper functions for API gateway features and authentication
|
|
79
81
|
|
|
80
82
|
### Specialized Components
|
|
81
83
|
|
|
82
84
|
- **HttpProxy** (`ts/proxies/http-proxy/http-proxy.ts`)
|
|
83
85
|
HTTP/HTTPS reverse proxy with TLS termination and WebSocket support
|
|
84
|
-
- **Port80Handler** (`ts/http/port80/port80-handler.ts`)
|
|
85
|
-
ACME HTTP-01 challenge handler for Let's Encrypt certificates
|
|
86
86
|
- **NfTablesProxy** (`ts/proxies/nftables-proxy/nftables-proxy.ts`)
|
|
87
87
|
Low-level port forwarding using nftables NAT rules
|
|
88
|
-
- **Redirect**, **SslRedirect** (`ts/http/redirects/redirect-handler.ts`)
|
|
89
|
-
HTTP-to-HTTPS redirects with customizable rules
|
|
90
88
|
- **SniHandler** (`ts/tls/sni/sni-handler.ts`)
|
|
91
89
|
Utilities for SNI extraction from TLS handshakes
|
|
92
90
|
|
|
@@ -102,7 +100,6 @@ SmartProxy has been restructured using a modern, modular architecture with a uni
|
|
|
102
100
|
- `IRouteConfig`, `IRouteMatch`, `IRouteAction` (`ts/proxies/smart-proxy/models/route-types.ts`)
|
|
103
101
|
- `IRoutedSmartProxyOptions` (`ts/proxies/smart-proxy/models/route-types.ts`)
|
|
104
102
|
- `IHttpProxyOptions` (`ts/proxies/http-proxy/models/types.ts`)
|
|
105
|
-
- `IAcmeOptions`, `IDomainOptions` (`ts/certificate/models/certificate-types.ts`)
|
|
106
103
|
- `INfTableProxySettings` (`ts/proxies/nftables-proxy/models/interfaces.ts`)
|
|
107
104
|
|
|
108
105
|
## Installation
|
|
@@ -113,7 +110,7 @@ npm install @push.rocks/smartproxy
|
|
|
113
110
|
|
|
114
111
|
## Quick Start with SmartProxy
|
|
115
112
|
|
|
116
|
-
SmartProxy v19.
|
|
113
|
+
SmartProxy v19.5.3 provides a unified route-based configuration system with enhanced certificate management, NFTables integration for high-performance kernel-level routing, custom socket handling, and improved helper functions for common proxy setups.
|
|
117
114
|
|
|
118
115
|
```typescript
|
|
119
116
|
import {
|
|
@@ -124,12 +121,21 @@ import {
|
|
|
124
121
|
createHttpToHttpsRedirect,
|
|
125
122
|
createCompleteHttpsServer,
|
|
126
123
|
createLoadBalancerRoute,
|
|
127
|
-
createStaticFileRoute,
|
|
128
124
|
createApiRoute,
|
|
129
125
|
createWebSocketRoute,
|
|
130
|
-
|
|
126
|
+
createSocketHandlerRoute,
|
|
131
127
|
createNfTablesRoute,
|
|
132
|
-
createNfTablesTerminateRoute
|
|
128
|
+
createNfTablesTerminateRoute,
|
|
129
|
+
createCompleteNfTablesHttpsServer,
|
|
130
|
+
createPortMappingRoute,
|
|
131
|
+
createOffsetPortMappingRoute,
|
|
132
|
+
createDynamicRoute,
|
|
133
|
+
createSmartLoadBalancer,
|
|
134
|
+
createApiGatewayRoute,
|
|
135
|
+
addRateLimiting,
|
|
136
|
+
addBasicAuth,
|
|
137
|
+
addJwtAuth,
|
|
138
|
+
SocketHandlers
|
|
133
139
|
} from '@push.rocks/smartproxy';
|
|
134
140
|
|
|
135
141
|
// Create a new SmartProxy instance with route-based configuration
|
|
@@ -179,12 +185,6 @@ const proxy = new SmartProxy({
|
|
|
179
185
|
pingInterval: 30000
|
|
180
186
|
}),
|
|
181
187
|
|
|
182
|
-
// Static file server for web assets
|
|
183
|
-
createStaticFileRoute('static.example.com', '/var/www/html', {
|
|
184
|
-
serveOnHttps: true,
|
|
185
|
-
certificate: 'auto',
|
|
186
|
-
indexFiles: ['index.html', 'index.htm', 'default.html']
|
|
187
|
-
}),
|
|
188
188
|
|
|
189
189
|
// Load balancer with multiple backend servers
|
|
190
190
|
createLoadBalancerRoute(
|
|
@@ -195,15 +195,16 @@ const proxy = new SmartProxy({
|
|
|
195
195
|
tls: {
|
|
196
196
|
mode: 'terminate',
|
|
197
197
|
certificate: 'auto'
|
|
198
|
-
}
|
|
199
|
-
security: createSecurityConfig({
|
|
200
|
-
allowedIps: ['10.0.0.*', '192.168.1.*'],
|
|
201
|
-
blockedIps: ['1.2.3.4'],
|
|
202
|
-
maxConnections: 1000
|
|
203
|
-
})
|
|
198
|
+
}
|
|
204
199
|
}
|
|
205
200
|
),
|
|
206
201
|
|
|
202
|
+
// Custom socket handler for specialized protocols
|
|
203
|
+
createSocketHandlerRoute('telnet.example.com', 23, SocketHandlers.lineProtocol((line, socket) => {
|
|
204
|
+
console.log('Received:', line);
|
|
205
|
+
socket.write(`Echo: ${line}\n`);
|
|
206
|
+
})),
|
|
207
|
+
|
|
207
208
|
// High-performance NFTables route (requires root/sudo)
|
|
208
209
|
createNfTablesRoute('fast.example.com', { host: 'backend-server', port: 8080 }, {
|
|
209
210
|
ports: 80,
|
|
@@ -217,7 +218,29 @@ const proxy = new SmartProxy({
|
|
|
217
218
|
ports: 443,
|
|
218
219
|
certificate: 'auto',
|
|
219
220
|
maxRate: '100mbps'
|
|
220
|
-
})
|
|
221
|
+
}),
|
|
222
|
+
|
|
223
|
+
// Route with security configuration
|
|
224
|
+
{
|
|
225
|
+
name: 'secure-admin',
|
|
226
|
+
match: {
|
|
227
|
+
ports: 443,
|
|
228
|
+
domains: 'admin.example.com'
|
|
229
|
+
},
|
|
230
|
+
action: {
|
|
231
|
+
type: 'forward',
|
|
232
|
+
target: { host: 'localhost', port: 8080 },
|
|
233
|
+
tls: {
|
|
234
|
+
mode: 'terminate',
|
|
235
|
+
certificate: 'auto'
|
|
236
|
+
}
|
|
237
|
+
},
|
|
238
|
+
security: {
|
|
239
|
+
ipAllowList: ['10.0.0.*', '192.168.1.*'],
|
|
240
|
+
ipBlockList: ['192.168.1.100'],
|
|
241
|
+
maxConnections: 100
|
|
242
|
+
}
|
|
243
|
+
}
|
|
221
244
|
]
|
|
222
245
|
});
|
|
223
246
|
|
|
@@ -243,7 +266,7 @@ await proxy.stop();
|
|
|
243
266
|
|
|
244
267
|
## Route-Based Configuration System
|
|
245
268
|
|
|
246
|
-
SmartProxy
|
|
269
|
+
SmartProxy uses a unified route configuration system based on the `IRouteConfig` interface. This system follows a match/action pattern that makes routing more powerful, flexible, and declarative.
|
|
247
270
|
|
|
248
271
|
### IRouteConfig Interface
|
|
249
272
|
|
|
@@ -257,11 +280,15 @@ interface IRouteConfig {
|
|
|
257
280
|
// What to do with matched traffic (required)
|
|
258
281
|
action: IRouteAction;
|
|
259
282
|
|
|
283
|
+
// Security configuration (optional)
|
|
284
|
+
security?: IRouteSecurity;
|
|
285
|
+
|
|
260
286
|
// Metadata (all optional)
|
|
261
287
|
name?: string; // Human-readable name for this route
|
|
262
288
|
description?: string; // Description of the route's purpose
|
|
263
289
|
priority?: number; // Controls matching order (higher = matched first)
|
|
264
290
|
tags?: string[]; // Arbitrary tags for categorization
|
|
291
|
+
enabled?: boolean; // Whether the route is active (default: true)
|
|
265
292
|
}
|
|
266
293
|
```
|
|
267
294
|
|
|
@@ -281,6 +308,7 @@ interface IRouteMatch {
|
|
|
281
308
|
path?: string; // Match specific URL paths, supports glob patterns
|
|
282
309
|
clientIp?: string[]; // Match specific client IPs, supports glob patterns
|
|
283
310
|
tlsVersion?: string[]; // Match specific TLS versions e.g. ['TLSv1.2', 'TLSv1.3']
|
|
311
|
+
headers?: Record<string, string | RegExp>; // Match specific HTTP headers
|
|
284
312
|
}
|
|
285
313
|
```
|
|
286
314
|
|
|
@@ -316,7 +344,7 @@ The `action` property defines what to do with traffic that matches the criteria:
|
|
|
316
344
|
```typescript
|
|
317
345
|
interface IRouteAction {
|
|
318
346
|
// Action type (required)
|
|
319
|
-
type: 'forward' | '
|
|
347
|
+
type: 'forward' | 'socket-handler';
|
|
320
348
|
|
|
321
349
|
// For 'forward' actions
|
|
322
350
|
target?: IRouteTarget;
|
|
@@ -324,14 +352,23 @@ interface IRouteAction {
|
|
|
324
352
|
// TLS handling for 'forward' actions
|
|
325
353
|
tls?: IRouteTls;
|
|
326
354
|
|
|
327
|
-
// For '
|
|
328
|
-
|
|
355
|
+
// For 'socket-handler' actions
|
|
356
|
+
socketHandler?: TSocketHandler;
|
|
329
357
|
|
|
330
|
-
//
|
|
331
|
-
|
|
358
|
+
// WebSocket support
|
|
359
|
+
websocket?: IRouteWebSocket;
|
|
360
|
+
|
|
361
|
+
// Load balancing options
|
|
362
|
+
loadBalancing?: IRouteLoadBalancing;
|
|
332
363
|
|
|
333
364
|
// Advanced options
|
|
334
365
|
advanced?: IRouteAdvanced;
|
|
366
|
+
|
|
367
|
+
// Additional backend-specific options
|
|
368
|
+
options?: {
|
|
369
|
+
backendProtocol?: 'http1' | 'http2';
|
|
370
|
+
[key: string]: any;
|
|
371
|
+
};
|
|
335
372
|
|
|
336
373
|
// Forwarding engine selection
|
|
337
374
|
forwardingEngine?: 'node' | 'nftables';
|
|
@@ -341,6 +378,27 @@ interface IRouteAction {
|
|
|
341
378
|
}
|
|
342
379
|
```
|
|
343
380
|
|
|
381
|
+
#### Security Configuration (IRouteSecurity)
|
|
382
|
+
|
|
383
|
+
Security is configured at the route level, not within the action:
|
|
384
|
+
|
|
385
|
+
```typescript
|
|
386
|
+
interface IRouteSecurity {
|
|
387
|
+
// Access control lists
|
|
388
|
+
ipAllowList?: string[]; // IP addresses that are allowed to connect
|
|
389
|
+
ipBlockList?: string[]; // IP addresses that are blocked from connecting
|
|
390
|
+
|
|
391
|
+
// Connection limits
|
|
392
|
+
maxConnections?: number; // Maximum concurrent connections
|
|
393
|
+
|
|
394
|
+
// Authentication (requires TLS termination)
|
|
395
|
+
authentication?: IRouteAuthentication;
|
|
396
|
+
|
|
397
|
+
// Rate limiting
|
|
398
|
+
rateLimit?: IRouteRateLimit;
|
|
399
|
+
}
|
|
400
|
+
```
|
|
401
|
+
|
|
344
402
|
### ACME/Let's Encrypt Configuration
|
|
345
403
|
|
|
346
404
|
SmartProxy supports automatic certificate provisioning and renewal with Let's Encrypt. ACME can be configured globally or per-route.
|
|
@@ -400,14 +458,16 @@ Override global settings for specific routes:
|
|
|
400
458
|
}
|
|
401
459
|
}
|
|
402
460
|
}
|
|
461
|
+
```
|
|
462
|
+
|
|
463
|
+
### Action Types
|
|
403
464
|
|
|
404
465
|
**Forward Action:**
|
|
405
466
|
When `type: 'forward'`, the traffic is forwarded to the specified target:
|
|
406
467
|
```typescript
|
|
407
468
|
interface IRouteTarget {
|
|
408
|
-
host: string | string[]; // Target host(s) - string array enables round-robin
|
|
409
|
-
port: number;
|
|
410
|
-
preservePort?: boolean; // Use incoming port as target port (default: false)
|
|
469
|
+
host: string | string[] | ((context: IRouteContext) => string | string[]); // Target host(s) - string array enables round-robin, function enables dynamic routing
|
|
470
|
+
port: number | 'preserve' | ((context: IRouteContext) => number); // Target port - 'preserve' keeps incoming port, function enables dynamic port mapping
|
|
411
471
|
}
|
|
412
472
|
```
|
|
413
473
|
|
|
@@ -447,44 +507,146 @@ interface INfTablesOptions {
|
|
|
447
507
|
}
|
|
448
508
|
```
|
|
449
509
|
|
|
450
|
-
**Redirect
|
|
451
|
-
|
|
510
|
+
**Redirect and Block Actions:**
|
|
511
|
+
Redirects and blocks are implemented using socket handlers. Use the helper functions or pre-built handlers:
|
|
452
512
|
```typescript
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
513
|
+
// HTTP to HTTPS redirect
|
|
514
|
+
createHttpToHttpsRedirect('example.com', 443)
|
|
515
|
+
|
|
516
|
+
// Block connections
|
|
517
|
+
{
|
|
518
|
+
action: {
|
|
519
|
+
type: 'socket-handler',
|
|
520
|
+
socketHandler: SocketHandlers.httpBlock(403, 'Access denied')
|
|
521
|
+
}
|
|
456
522
|
}
|
|
457
523
|
```
|
|
458
524
|
|
|
459
|
-
**
|
|
460
|
-
When `type: '
|
|
525
|
+
**Socket Handler Action:**
|
|
526
|
+
When `type: 'socket-handler'`, custom socket handling logic is applied:
|
|
527
|
+
```typescript
|
|
528
|
+
type TSocketHandler = (socket: net.Socket, context: IRouteContext) => void | Promise<void>;
|
|
529
|
+
```
|
|
530
|
+
|
|
531
|
+
The socket handler receives:
|
|
532
|
+
- `socket`: The raw Node.js Socket object
|
|
533
|
+
- `context`: Route context containing clientIp, port, domain, route info, etc.
|
|
534
|
+
|
|
535
|
+
### Socket Handlers
|
|
536
|
+
|
|
537
|
+
SmartProxy v19.5.0 introduces socket handlers for custom protocol handling:
|
|
461
538
|
|
|
462
|
-
**Security Options:**
|
|
463
|
-
For any action type, you can add security controls:
|
|
464
539
|
```typescript
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
540
|
+
// Create a custom socket handler route
|
|
541
|
+
createSocketHandlerRoute('custom.example.com', 9000, async (socket, context) => {
|
|
542
|
+
console.log(`New connection from ${context.clientIp}`);
|
|
543
|
+
|
|
544
|
+
// Custom protocol handling
|
|
545
|
+
socket.write('Welcome to custom protocol server\n');
|
|
546
|
+
|
|
547
|
+
socket.on('data', (data) => {
|
|
548
|
+
// Process custom protocol data
|
|
549
|
+
const response = processProtocolData(data);
|
|
550
|
+
socket.write(response);
|
|
551
|
+
});
|
|
552
|
+
|
|
553
|
+
socket.on('error', (err) => {
|
|
554
|
+
console.error('Socket error:', err);
|
|
555
|
+
});
|
|
556
|
+
});
|
|
557
|
+
|
|
558
|
+
// Use pre-built socket handlers
|
|
559
|
+
import { SocketHandlers } from '@push.rocks/smartproxy';
|
|
560
|
+
|
|
561
|
+
// Echo server
|
|
562
|
+
createSocketHandlerRoute('echo.example.com', 7000, SocketHandlers.echo),
|
|
563
|
+
|
|
564
|
+
// TCP proxy
|
|
565
|
+
createSocketHandlerRoute('proxy.example.com', 8000, SocketHandlers.proxy('backend-server', 8080)),
|
|
566
|
+
|
|
567
|
+
// Line-based protocol
|
|
568
|
+
createSocketHandlerRoute('telnet.example.com', 23, SocketHandlers.lineProtocol((line, socket) => {
|
|
569
|
+
socket.write(`You said: ${line}\n`);
|
|
570
|
+
})),
|
|
571
|
+
|
|
572
|
+
// HTTP response
|
|
573
|
+
createSocketHandlerRoute('simple.example.com', 8080, SocketHandlers.httpResponse(200, 'Hello World')),
|
|
574
|
+
|
|
575
|
+
// HTTP redirect
|
|
576
|
+
createSocketHandlerRoute('redirect.example.com', 80, SocketHandlers.httpRedirect('https://{domain}{path}', 301)),
|
|
577
|
+
|
|
578
|
+
// HTTP blocking with custom message
|
|
579
|
+
createSocketHandlerRoute('forbidden.example.com', 80, SocketHandlers.httpBlock(403, 'Access Forbidden')),
|
|
580
|
+
|
|
581
|
+
// Block connections immediately
|
|
582
|
+
createSocketHandlerRoute('blocked.example.com', 443, SocketHandlers.block('Access denied')),
|
|
583
|
+
|
|
584
|
+
// Full HTTP server for complex handling
|
|
585
|
+
createSocketHandlerRoute('http-api.example.com', 8080, SocketHandlers.httpServer((req, res) => {
|
|
586
|
+
if (req.url === '/health') {
|
|
587
|
+
res.status(200);
|
|
588
|
+
res.send('OK');
|
|
589
|
+
} else {
|
|
590
|
+
res.status(404);
|
|
591
|
+
res.send('Not Found');
|
|
592
|
+
}
|
|
593
|
+
}))
|
|
474
594
|
```
|
|
475
595
|
|
|
476
|
-
|
|
477
|
-
|
|
596
|
+
### Dynamic Routing
|
|
597
|
+
|
|
598
|
+
SmartProxy supports dynamic routing using functions for host and port selection:
|
|
599
|
+
|
|
478
600
|
```typescript
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
601
|
+
// Dynamic host selection based on domain
|
|
602
|
+
createDynamicRoute({
|
|
603
|
+
ports: 80,
|
|
604
|
+
domains: ['*.tenant.example.com'],
|
|
605
|
+
targetHost: (context) => {
|
|
606
|
+
// Extract tenant from subdomain
|
|
607
|
+
const tenant = context.domain.split('.')[0];
|
|
608
|
+
return `${tenant}-backend`;
|
|
609
|
+
},
|
|
610
|
+
portMapper: (context) => 8080
|
|
611
|
+
});
|
|
612
|
+
|
|
613
|
+
// Port mapping with offset
|
|
614
|
+
createOffsetPortMappingRoute({
|
|
615
|
+
ports: [8000, 8001, 8002],
|
|
616
|
+
targetHost: 'backend',
|
|
617
|
+
offset: -1000 // Maps 8000->7000, 8001->7001, etc.
|
|
618
|
+
});
|
|
619
|
+
|
|
620
|
+
// Smart load balancer with domain-based routing
|
|
621
|
+
createSmartLoadBalancer({
|
|
622
|
+
ports: 443,
|
|
623
|
+
domainTargets: {
|
|
624
|
+
'api.example.com': ['api-1', 'api-2'],
|
|
625
|
+
'web.example.com': ['web-1', 'web-2', 'web-3'],
|
|
626
|
+
'admin.example.com': 'admin-server'
|
|
627
|
+
},
|
|
628
|
+
portMapper: (context) => 8080,
|
|
629
|
+
defaultTarget: 'fallback-server'
|
|
630
|
+
});
|
|
631
|
+
```
|
|
632
|
+
|
|
633
|
+
### Route Context
|
|
634
|
+
|
|
635
|
+
The `IRouteContext` interface provides information about the current connection:
|
|
636
|
+
|
|
637
|
+
```typescript
|
|
638
|
+
interface IRouteContext {
|
|
639
|
+
clientIp: string; // Client's IP address
|
|
640
|
+
port: number; // Incoming port
|
|
641
|
+
domain?: string; // Domain from SNI or Host header
|
|
642
|
+
path?: string; // Request path (HTTP only)
|
|
643
|
+
sni?: string; // SNI hostname (TLS only)
|
|
644
|
+
protocol?: string; // Protocol information
|
|
645
|
+
route?: IRouteConfig; // Matched route configuration
|
|
484
646
|
}
|
|
485
647
|
```
|
|
486
648
|
|
|
487
|
-
|
|
649
|
+
### Template Variables
|
|
488
650
|
|
|
489
651
|
String values in redirect URLs and headers can include variables:
|
|
490
652
|
|
|
@@ -503,7 +665,7 @@ redirect: {
|
|
|
503
665
|
}
|
|
504
666
|
```
|
|
505
667
|
|
|
506
|
-
|
|
668
|
+
### Route Metadata and Prioritization
|
|
507
669
|
|
|
508
670
|
You can add metadata to routes to help with organization and control matching priority:
|
|
509
671
|
|
|
@@ -518,7 +680,7 @@ You can add metadata to routes to help with organization and control matching pr
|
|
|
518
680
|
|
|
519
681
|
Routes with higher priority values are matched first, allowing you to create specialized routes that take precedence over more general ones.
|
|
520
682
|
|
|
521
|
-
|
|
683
|
+
### Complete Route Configuration Example
|
|
522
684
|
|
|
523
685
|
```typescript
|
|
524
686
|
// Example of a complete route configuration
|
|
@@ -539,10 +701,6 @@ Routes with higher priority values are matched first, allowing you to create spe
|
|
|
539
701
|
mode: 'terminate',
|
|
540
702
|
certificate: 'auto' // Use Let's Encrypt
|
|
541
703
|
},
|
|
542
|
-
security: {
|
|
543
|
-
allowedIps: ['10.0.0.*'],
|
|
544
|
-
maxConnections: 100
|
|
545
|
-
},
|
|
546
704
|
advanced: {
|
|
547
705
|
timeout: 30000,
|
|
548
706
|
headers: {
|
|
@@ -552,6 +710,10 @@ Routes with higher priority values are matched first, allowing you to create spe
|
|
|
552
710
|
keepAlive: true
|
|
553
711
|
}
|
|
554
712
|
},
|
|
713
|
+
security: {
|
|
714
|
+
ipAllowList: ['10.0.0.*'],
|
|
715
|
+
maxConnections: 100
|
|
716
|
+
},
|
|
555
717
|
name: 'Secure API Route',
|
|
556
718
|
description: 'Route for secure API endpoints with authentication',
|
|
557
719
|
priority: 100,
|
|
@@ -576,19 +738,19 @@ Routes with higher priority values are matched first, allowing you to create spe
|
|
|
576
738
|
preserveSourceIP: true,
|
|
577
739
|
maxRate: '1gbps',
|
|
578
740
|
useIPSets: true
|
|
579
|
-
},
|
|
580
|
-
security: {
|
|
581
|
-
ipAllowList: ['10.0.0.*'],
|
|
582
|
-
blockedIps: ['malicious.ip.range.*']
|
|
583
741
|
}
|
|
584
742
|
},
|
|
743
|
+
security: {
|
|
744
|
+
ipAllowList: ['10.0.0.*'],
|
|
745
|
+
ipBlockList: ['malicious.ip.range.*']
|
|
746
|
+
},
|
|
585
747
|
name: 'High Performance NFTables Route',
|
|
586
748
|
description: 'Kernel-level forwarding for maximum performance',
|
|
587
749
|
priority: 150
|
|
588
750
|
}
|
|
589
751
|
```
|
|
590
752
|
|
|
591
|
-
|
|
753
|
+
## Using Helper Functions
|
|
592
754
|
|
|
593
755
|
While you can create route configurations manually, SmartProxy provides helper functions to make it easier:
|
|
594
756
|
|
|
@@ -610,18 +772,23 @@ Available helper functions:
|
|
|
610
772
|
- `createHttpRoute()` - Create an HTTP forwarding route
|
|
611
773
|
- `createHttpsTerminateRoute()` - Create an HTTPS route with TLS termination
|
|
612
774
|
- `createHttpsPassthroughRoute()` - Create an HTTPS passthrough route
|
|
613
|
-
- `createHttpToHttpsRedirect()` - Create an HTTP to HTTPS redirect
|
|
775
|
+
- `createHttpToHttpsRedirect()` - Create an HTTP to HTTPS redirect using socket handler
|
|
614
776
|
- `createCompleteHttpsServer()` - Create a complete HTTPS server setup with HTTP redirect
|
|
615
777
|
- `createLoadBalancerRoute()` - Create a route for load balancing across multiple backends
|
|
616
|
-
- `createStaticFileRoute()` - Create a route for serving static files
|
|
617
778
|
- `createApiRoute()` - Create an API route with path matching and CORS support
|
|
618
779
|
- `createWebSocketRoute()` - Create a route for WebSocket connections
|
|
780
|
+
- `createSocketHandlerRoute()` - Create a route with custom socket handling
|
|
619
781
|
- `createNfTablesRoute()` - Create a high-performance NFTables route
|
|
620
782
|
- `createNfTablesTerminateRoute()` - Create an NFTables route with TLS termination
|
|
621
|
-
- `
|
|
622
|
-
- `
|
|
623
|
-
- `
|
|
624
|
-
- `
|
|
783
|
+
- `createCompleteNfTablesHttpsServer()` - Create a complete NFTables HTTPS setup with HTTP redirect
|
|
784
|
+
- `createPortMappingRoute()` - Create a route with dynamic port mapping
|
|
785
|
+
- `createOffsetPortMappingRoute()` - Create a route with port offset mapping
|
|
786
|
+
- `createDynamicRoute()` - Create a route with dynamic host/port selection
|
|
787
|
+
- `createSmartLoadBalancer()` - Create a smart load balancer with domain-based routing
|
|
788
|
+
- `createApiGatewayRoute()` - Create an API gateway route with advanced features
|
|
789
|
+
- `addRateLimiting()` - Add rate limiting to a route
|
|
790
|
+
- `addBasicAuth()` - Add basic authentication to a route
|
|
791
|
+
- `addJwtAuth()` - Add JWT authentication to a route
|
|
625
792
|
|
|
626
793
|
## What You Can Do with SmartProxy
|
|
627
794
|
|
|
@@ -660,13 +827,18 @@ Available helper functions:
|
|
|
660
827
|
4. **Security Controls**
|
|
661
828
|
```typescript
|
|
662
829
|
// Restrict access based on IP addresses
|
|
663
|
-
|
|
664
|
-
|
|
830
|
+
{
|
|
831
|
+
match: { ports: 443, domains: 'admin.example.com' },
|
|
832
|
+
action: {
|
|
833
|
+
type: 'forward',
|
|
834
|
+
target: { host: 'localhost', port: 8080 },
|
|
835
|
+
tls: { mode: 'terminate', certificate: 'auto' }
|
|
836
|
+
},
|
|
665
837
|
security: {
|
|
666
|
-
|
|
838
|
+
ipAllowList: ['10.0.0.*', '192.168.1.*'],
|
|
667
839
|
maxConnections: 100
|
|
668
840
|
}
|
|
669
|
-
}
|
|
841
|
+
}
|
|
670
842
|
```
|
|
671
843
|
|
|
672
844
|
5. **Wildcard Domains**
|
|
@@ -686,11 +858,15 @@ Available helper functions:
|
|
|
686
858
|
|
|
687
859
|
7. **Block Malicious Traffic**
|
|
688
860
|
```typescript
|
|
689
|
-
// Block traffic from specific IPs
|
|
690
|
-
|
|
691
|
-
clientIp: ['1.2.3.*', '5.6.7.*'],
|
|
861
|
+
// Block traffic from specific IPs or patterns
|
|
862
|
+
{
|
|
863
|
+
match: { ports: [80, 443], clientIp: ['1.2.3.*', '5.6.7.*'] },
|
|
864
|
+
action: {
|
|
865
|
+
type: 'socket-handler',
|
|
866
|
+
socketHandler: SocketHandlers.httpBlock(403, 'Access denied')
|
|
867
|
+
},
|
|
692
868
|
priority: 1000 // High priority to ensure blocking
|
|
693
|
-
}
|
|
869
|
+
}
|
|
694
870
|
```
|
|
695
871
|
|
|
696
872
|
8. **Dynamic Port Management**
|
|
@@ -728,6 +904,21 @@ Available helper functions:
|
|
|
728
904
|
})
|
|
729
905
|
```
|
|
730
906
|
|
|
907
|
+
10. **Custom Protocol Handling**
|
|
908
|
+
```typescript
|
|
909
|
+
// Implement custom protocols or specialized handling
|
|
910
|
+
createSocketHandlerRoute('custom.example.com', 9000, async (socket, context) => {
|
|
911
|
+
// Your custom protocol logic here
|
|
912
|
+
socket.write('CUSTOM PROTOCOL v1.0\n');
|
|
913
|
+
|
|
914
|
+
socket.on('data', (data) => {
|
|
915
|
+
// Handle custom protocol messages
|
|
916
|
+
const response = processCustomProtocol(data);
|
|
917
|
+
socket.write(response);
|
|
918
|
+
});
|
|
919
|
+
})
|
|
920
|
+
```
|
|
921
|
+
|
|
731
922
|
## Other Components
|
|
732
923
|
|
|
733
924
|
While SmartProxy provides a unified API for most needs, you can also use individual components:
|
|
@@ -779,32 +970,6 @@ await proxy.updateRouteConfigs([
|
|
|
779
970
|
}
|
|
780
971
|
}
|
|
781
972
|
]);
|
|
782
|
-
|
|
783
|
-
// Legacy configuration (for backward compatibility)
|
|
784
|
-
await proxy.updateProxyConfigs([
|
|
785
|
-
{
|
|
786
|
-
hostName: 'legacy.example.com',
|
|
787
|
-
destinationIps: ['127.0.0.1'],
|
|
788
|
-
destinationPorts: [3000],
|
|
789
|
-
publicKey: fs.readFileSync('cert.pem', 'utf8'),
|
|
790
|
-
privateKey: fs.readFileSync('key.pem', 'utf8'),
|
|
791
|
-
}
|
|
792
|
-
]);
|
|
793
|
-
```
|
|
794
|
-
|
|
795
|
-
### Port80Handler
|
|
796
|
-
For standalone ACME certificate management:
|
|
797
|
-
|
|
798
|
-
```typescript
|
|
799
|
-
import { Port80Handler } from '@push.rocks/smartproxy';
|
|
800
|
-
|
|
801
|
-
const acme = new Port80Handler({
|
|
802
|
-
port: 80,
|
|
803
|
-
contactEmail: 'admin@example.com',
|
|
804
|
-
useProduction: true
|
|
805
|
-
});
|
|
806
|
-
acme.on('certificate-issued', evt => console.log(`Certificate ready: ${evt.domain}`));
|
|
807
|
-
await acme.start();
|
|
808
973
|
```
|
|
809
974
|
|
|
810
975
|
### NfTablesProxy
|
|
@@ -822,15 +987,14 @@ const nft = new NfTablesProxy({
|
|
|
822
987
|
await nft.start();
|
|
823
988
|
```
|
|
824
989
|
|
|
825
|
-
###
|
|
826
|
-
For
|
|
990
|
+
### SniHandler
|
|
991
|
+
For SNI extraction from TLS handshakes:
|
|
827
992
|
|
|
828
993
|
```typescript
|
|
829
|
-
import {
|
|
994
|
+
import { SniHandler } from '@push.rocks/smartproxy';
|
|
830
995
|
|
|
831
|
-
//
|
|
832
|
-
|
|
833
|
-
await redirect.start();
|
|
996
|
+
// The SniHandler is typically used internally by SmartProxy
|
|
997
|
+
// but can be used directly for custom implementations
|
|
834
998
|
```
|
|
835
999
|
|
|
836
1000
|
## NFTables Integration
|
|
@@ -898,6 +1062,15 @@ const proxy = new SmartProxy({
|
|
|
898
1062
|
ports: 443,
|
|
899
1063
|
certificate: 'auto',
|
|
900
1064
|
useAdvancedNAT: true
|
|
1065
|
+
}),
|
|
1066
|
+
|
|
1067
|
+
// Complete NFTables HTTPS server with HTTP redirect
|
|
1068
|
+
...createCompleteNfTablesHttpsServer('complete-nftables.example.com', {
|
|
1069
|
+
host: 'backend',
|
|
1070
|
+
port: 8080
|
|
1071
|
+
}, {
|
|
1072
|
+
certificate: 'auto',
|
|
1073
|
+
preserveSourceIP: true
|
|
901
1074
|
})
|
|
902
1075
|
]
|
|
903
1076
|
});
|
|
@@ -953,78 +1126,84 @@ NFTables routing has some limitations:
|
|
|
953
1126
|
|
|
954
1127
|
For scenarios requiring application-level features (header manipulation, WebSocket handling, etc.), use the standard SmartProxy routes without NFTables.
|
|
955
1128
|
|
|
956
|
-
## Migration to
|
|
1129
|
+
## Migration to v19.5.3
|
|
957
1130
|
|
|
958
|
-
Version
|
|
1131
|
+
Version 19.5.3 includes important fixes and improvements:
|
|
959
1132
|
|
|
960
1133
|
### Key Changes
|
|
961
1134
|
|
|
962
|
-
1. **
|
|
963
|
-
2. **
|
|
964
|
-
3. **Improved
|
|
965
|
-
4. **
|
|
966
|
-
5. **
|
|
1135
|
+
1. **Security Configuration Location**: Security configuration is now at the route level (`route.security`), not inside the action (`route.action.security`)
|
|
1136
|
+
2. **Socket Handler Support**: New `socket-handler` action type for custom protocol handling
|
|
1137
|
+
3. **Improved ACME Timing**: Certificate provisioning now waits for ports to be ready
|
|
1138
|
+
4. **Route-Specific Security**: IP allow/block lists are now properly enforced per route
|
|
1139
|
+
5. **Enhanced Helper Functions**: New helpers for socket handling and NFTables complete server setup
|
|
967
1140
|
|
|
968
1141
|
### Migration Example
|
|
969
1142
|
|
|
970
|
-
**
|
|
1143
|
+
**Before (v18.x and earlier)**:
|
|
971
1144
|
```typescript
|
|
972
|
-
|
|
973
|
-
|
|
974
|
-
|
|
975
|
-
|
|
976
|
-
|
|
977
|
-
|
|
978
|
-
|
|
979
|
-
|
|
980
|
-
|
|
981
|
-
|
|
982
|
-
sniEnabled: true
|
|
983
|
-
});
|
|
1145
|
+
{
|
|
1146
|
+
match: { ports: 443, domains: 'api.example.com' },
|
|
1147
|
+
action: {
|
|
1148
|
+
type: 'forward',
|
|
1149
|
+
target: { host: 'localhost', port: 3000 },
|
|
1150
|
+
security: { // WRONG: Security was incorrectly placed here
|
|
1151
|
+
ipAllowList: ['10.0.0.*']
|
|
1152
|
+
}
|
|
1153
|
+
}
|
|
1154
|
+
}
|
|
984
1155
|
```
|
|
985
1156
|
|
|
986
|
-
**
|
|
1157
|
+
**After (v19.5.3)**:
|
|
987
1158
|
```typescript
|
|
988
|
-
|
|
989
|
-
|
|
990
|
-
|
|
991
|
-
|
|
992
|
-
|
|
993
|
-
|
|
994
|
-
|
|
995
|
-
|
|
996
|
-
acme: {
|
|
997
|
-
enabled: true,
|
|
998
|
-
useProduction: true
|
|
1159
|
+
{
|
|
1160
|
+
match: { ports: 443, domains: 'api.example.com' },
|
|
1161
|
+
action: {
|
|
1162
|
+
type: 'forward',
|
|
1163
|
+
target: { host: 'localhost', port: 3000 }
|
|
1164
|
+
},
|
|
1165
|
+
security: { // CORRECT: Security is at the route level
|
|
1166
|
+
ipAllowList: ['10.0.0.*']
|
|
999
1167
|
}
|
|
1000
|
-
}
|
|
1168
|
+
}
|
|
1001
1169
|
```
|
|
1002
1170
|
|
|
1003
|
-
###
|
|
1171
|
+
### New Features in v19.5.x
|
|
1004
1172
|
|
|
1005
|
-
|
|
1173
|
+
1. **Socket Handlers** - Custom protocol handling:
|
|
1174
|
+
```typescript
|
|
1175
|
+
createSocketHandlerRoute('custom.example.com', 9000, async (socket, context) => {
|
|
1176
|
+
// Custom protocol implementation
|
|
1177
|
+
})
|
|
1178
|
+
```
|
|
1006
1179
|
|
|
1007
|
-
|
|
1008
|
-
|
|
1009
|
-
|
|
1010
|
-
|
|
1011
|
-
|
|
1012
|
-
|
|
1013
|
-
|
|
1014
|
-
|
|
1015
|
-
|
|
1016
|
-
|
|
1017
|
-
|
|
1018
|
-
|
|
1019
|
-
|
|
1180
|
+
2. **Pre-built Socket Handlers** - Common patterns:
|
|
1181
|
+
- `SocketHandlers.echo` - Echo server
|
|
1182
|
+
- `SocketHandlers.proxy` - TCP proxy
|
|
1183
|
+
- `SocketHandlers.lineProtocol` - Line-based protocols
|
|
1184
|
+
- `SocketHandlers.httpResponse` - Simple HTTP responses
|
|
1185
|
+
- `SocketHandlers.httpRedirect` - HTTP redirects
|
|
1186
|
+
- `SocketHandlers.httpBlock` - HTTP blocking with status code
|
|
1187
|
+
- `SocketHandlers.block` - Connection blocking
|
|
1188
|
+
- `SocketHandlers.httpServer` - Full HTTP server handler
|
|
1189
|
+
|
|
1190
|
+
3. **Complete NFTables Server** - HTTPS with HTTP redirect:
|
|
1191
|
+
```typescript
|
|
1192
|
+
...createCompleteNfTablesHttpsServer('example.com', {
|
|
1193
|
+
host: 'backend',
|
|
1194
|
+
port: 8080
|
|
1195
|
+
}, {
|
|
1196
|
+
certificate: 'auto'
|
|
1197
|
+
})
|
|
1198
|
+
```
|
|
1020
1199
|
|
|
1021
1200
|
### Complete Migration Steps
|
|
1022
1201
|
|
|
1023
|
-
1.
|
|
1024
|
-
2. Update
|
|
1025
|
-
3.
|
|
1026
|
-
4.
|
|
1027
|
-
5.
|
|
1202
|
+
1. Move any security configuration from `action.security` to `route.security`
|
|
1203
|
+
2. Update to use new socket handler features for custom protocols
|
|
1204
|
+
3. Take advantage of improved ACME timing (no action needed, just update)
|
|
1205
|
+
4. Use the new helper functions for cleaner configuration
|
|
1206
|
+
5. Review and update any custom route creation code
|
|
1028
1207
|
|
|
1029
1208
|
## Architecture & Flow Diagrams
|
|
1030
1209
|
|
|
@@ -1036,9 +1215,11 @@ flowchart TB
|
|
|
1036
1215
|
direction TB
|
|
1037
1216
|
RouteConfig["Route Configuration<br>(Match/Action)"]
|
|
1038
1217
|
RouteManager["Route Manager"]
|
|
1039
|
-
HTTPS443["HTTPS Port 443<br>HttpProxy"]
|
|
1040
1218
|
SmartProxy["SmartProxy<br>(TCP/SNI Proxy)"]
|
|
1041
|
-
|
|
1219
|
+
HttpProxyBridge["HttpProxy Bridge"]
|
|
1220
|
+
HttpProxy["HttpProxy<br>(HTTPS/TLS Termination)"]
|
|
1221
|
+
NfTablesManager["NFTables Manager<br>(Kernel Routing)"]
|
|
1222
|
+
CertManager["SmartCertManager<br>(ACME/Let's Encrypt)"]
|
|
1042
1223
|
Certs[(SSL Certificates)]
|
|
1043
1224
|
end
|
|
1044
1225
|
|
|
@@ -1054,20 +1235,25 @@ flowchart TB
|
|
|
1054
1235
|
RouteManager -->|Use| RouteConfig
|
|
1055
1236
|
RouteManager -->|Execute Action| SmartProxy
|
|
1056
1237
|
|
|
1238
|
+
SmartProxy -->|TLS Termination| HttpProxyBridge
|
|
1239
|
+
HttpProxyBridge -->|Forward| HttpProxy
|
|
1240
|
+
SmartProxy -->|Kernel Routing| NfTablesManager
|
|
1241
|
+
|
|
1057
1242
|
SmartProxy -->|Forward| Service1
|
|
1058
1243
|
SmartProxy -->|Redirect| Client
|
|
1059
1244
|
SmartProxy -->|Forward| Service2
|
|
1060
1245
|
SmartProxy -->|Forward| Service3
|
|
1061
1246
|
|
|
1062
|
-
|
|
1247
|
+
CertManager -.->|Generate/Manage| Certs
|
|
1063
1248
|
Certs -.->|Provide TLS Certs| SmartProxy
|
|
1249
|
+
Certs -.->|Provide TLS Certs| HttpProxy
|
|
1064
1250
|
|
|
1065
1251
|
classDef component fill:#f9f,stroke:#333,stroke-width:2px;
|
|
1066
1252
|
classDef backend fill:#bbf,stroke:#333,stroke-width:1px;
|
|
1067
1253
|
classDef client fill:#dfd,stroke:#333,stroke-width:2px;
|
|
1068
1254
|
|
|
1069
1255
|
class Client client;
|
|
1070
|
-
class RouteConfig,RouteManager,
|
|
1256
|
+
class RouteConfig,RouteManager,SmartProxy,HttpProxyBridge,HttpProxy,NfTablesManager,CertManager component;
|
|
1071
1257
|
class Service1,Service2,Service3 backend;
|
|
1072
1258
|
```
|
|
1073
1259
|
|
|
@@ -1079,6 +1265,7 @@ sequenceDiagram
|
|
|
1079
1265
|
participant Client
|
|
1080
1266
|
participant SmartProxy
|
|
1081
1267
|
participant RouteManager
|
|
1268
|
+
participant SecurityManager
|
|
1082
1269
|
participant Backend
|
|
1083
1270
|
|
|
1084
1271
|
Client->>SmartProxy: Connection (TCP/HTTP/HTTPS)
|
|
@@ -1093,28 +1280,40 @@ sequenceDiagram
|
|
|
1093
1280
|
|
|
1094
1281
|
RouteManager->>RouteManager: Determine highest priority matching route
|
|
1095
1282
|
|
|
1096
|
-
alt
|
|
1097
|
-
|
|
1283
|
+
alt Route Matched
|
|
1284
|
+
SmartProxy->>SecurityManager: Check route security
|
|
1285
|
+
SecurityManager->>SecurityManager: Validate IP allow/block lists
|
|
1286
|
+
SecurityManager->>SecurityManager: Check connection limits
|
|
1098
1287
|
|
|
1099
|
-
alt
|
|
1100
|
-
|
|
1101
|
-
|
|
1102
|
-
|
|
1103
|
-
|
|
1288
|
+
alt Security Check Passed
|
|
1289
|
+
alt Forward Action
|
|
1290
|
+
SmartProxy->>SmartProxy: Apply action configuration
|
|
1291
|
+
|
|
1292
|
+
alt TLS Termination
|
|
1293
|
+
SmartProxy->>SmartProxy: Terminate TLS
|
|
1294
|
+
SmartProxy->>Backend: Forward as HTTP/HTTPS
|
|
1295
|
+
else TLS Passthrough
|
|
1296
|
+
SmartProxy->>Backend: Forward raw TCP
|
|
1297
|
+
else Socket Handler
|
|
1298
|
+
SmartProxy->>SmartProxy: Execute custom handler
|
|
1299
|
+
end
|
|
1300
|
+
|
|
1301
|
+
else Redirect Action
|
|
1302
|
+
SmartProxy->>Client: Send redirect response
|
|
1303
|
+
|
|
1304
|
+
else Block Action
|
|
1305
|
+
SmartProxy->>Client: Close connection
|
|
1306
|
+
end
|
|
1307
|
+
else Security Check Failed
|
|
1308
|
+
SmartProxy->>Client: Close connection (unauthorized)
|
|
1104
1309
|
end
|
|
1105
|
-
|
|
1106
|
-
|
|
1107
|
-
RouteManager->>SmartProxy: Use redirect action
|
|
1108
|
-
SmartProxy->>Client: Send redirect response
|
|
1109
|
-
|
|
1110
|
-
else Block Action
|
|
1111
|
-
RouteManager->>SmartProxy: Use block action
|
|
1112
|
-
SmartProxy->>Client: Close connection
|
|
1310
|
+
else No Route Matched
|
|
1311
|
+
SmartProxy->>Client: Close connection (no route)
|
|
1113
1312
|
end
|
|
1114
1313
|
|
|
1115
1314
|
loop Connection Active
|
|
1116
1315
|
SmartProxy-->>SmartProxy: Monitor Activity
|
|
1117
|
-
SmartProxy-->>
|
|
1316
|
+
SmartProxy-->>SecurityManager: Check Security Rules
|
|
1118
1317
|
alt Security Violation or Timeout
|
|
1119
1318
|
SmartProxy->>Client: Close Connection
|
|
1120
1319
|
SmartProxy->>Backend: Close Connection
|
|
@@ -1127,7 +1326,7 @@ sequenceDiagram
|
|
|
1127
1326
|
- **Route-Based Traffic Management**
|
|
1128
1327
|
• Match/action pattern for flexible routing
|
|
1129
1328
|
• Port, domain, path, client IP, and TLS version matching
|
|
1130
|
-
•
|
|
1329
|
+
• Forward traffic or use custom socket handlers for any protocol
|
|
1131
1330
|
|
|
1132
1331
|
- **TLS Handling Options**
|
|
1133
1332
|
• TLS passthrough for end-to-end encryption
|
|
@@ -1138,29 +1337,44 @@ sequenceDiagram
|
|
|
1138
1337
|
• HTTP-01 challenge handling
|
|
1139
1338
|
• Certificate issuance/renewal
|
|
1140
1339
|
• Pluggable storage
|
|
1340
|
+
• Per-route and global configuration
|
|
1141
1341
|
|
|
1142
1342
|
- **Security Controls**
|
|
1143
|
-
• IP allow/block lists with glob pattern support
|
|
1343
|
+
• Route-specific IP allow/block lists with glob pattern support
|
|
1144
1344
|
• Connection limits and rate limiting
|
|
1145
1345
|
• Timeout controls and connection monitoring
|
|
1346
|
+
• Authentication support (Basic, JWT, OAuth)
|
|
1146
1347
|
|
|
1147
1348
|
- **Load Balancing**
|
|
1148
1349
|
• Round-robin distribution across multiple backends
|
|
1350
|
+
• Dynamic host selection based on context
|
|
1149
1351
|
• Health checks and failure handling
|
|
1150
1352
|
|
|
1353
|
+
- **Custom Protocol Support**
|
|
1354
|
+
• Socket handler action type for custom protocols
|
|
1355
|
+
• Pre-built handlers for common patterns
|
|
1356
|
+
• Full control over socket lifecycle
|
|
1357
|
+
|
|
1151
1358
|
- **Advanced Features**
|
|
1152
1359
|
• Custom header manipulation
|
|
1360
|
+
• URL rewriting
|
|
1153
1361
|
• Template variables for dynamic values
|
|
1154
1362
|
• Priority-based route matching
|
|
1363
|
+
• WebSocket support with configuration
|
|
1364
|
+
• Static file serving
|
|
1365
|
+
|
|
1366
|
+
- **High Performance**
|
|
1367
|
+
• NFTables integration for kernel-level forwarding
|
|
1368
|
+
• Connection pooling and keep-alive
|
|
1369
|
+
• Efficient SNI extraction
|
|
1370
|
+
• Minimal overhead routing
|
|
1155
1371
|
|
|
1156
1372
|
## Certificate Hooks & Events
|
|
1157
1373
|
|
|
1158
1374
|
Listen for certificate events via EventEmitter:
|
|
1159
|
-
- **Port80Handler**:
|
|
1160
|
-
- `certificate-issued`, `certificate-renewed`, `certificate-failed`
|
|
1161
|
-
- `manager-started`, `manager-stopped`, `request-forwarded`
|
|
1162
1375
|
- **SmartProxy**:
|
|
1163
1376
|
- `certificate` (domain, publicKey, privateKey, expiryDate, source, isRenewal)
|
|
1377
|
+
- Events from CertManager are propagated
|
|
1164
1378
|
|
|
1165
1379
|
Provide a `certProvisionFunction(domain)` in SmartProxy settings to supply static certs or return `'http01'`.
|
|
1166
1380
|
|
|
@@ -1192,12 +1406,17 @@ const apiGateway = new SmartProxy({
|
|
|
1192
1406
|
}),
|
|
1193
1407
|
|
|
1194
1408
|
// Admin dashboard with extra security
|
|
1195
|
-
|
|
1196
|
-
|
|
1409
|
+
{
|
|
1410
|
+
match: { ports: 443, domains: 'admin.example.com' },
|
|
1411
|
+
action: {
|
|
1412
|
+
type: 'forward',
|
|
1413
|
+
target: { host: 'admin-dashboard', port: 8080 },
|
|
1414
|
+
tls: { mode: 'terminate', certificate: 'auto' }
|
|
1415
|
+
},
|
|
1197
1416
|
security: {
|
|
1198
|
-
|
|
1417
|
+
ipAllowList: ['10.0.0.*', '192.168.1.*'] // Only allow internal network
|
|
1199
1418
|
}
|
|
1200
|
-
}
|
|
1419
|
+
}
|
|
1201
1420
|
]
|
|
1202
1421
|
});
|
|
1203
1422
|
|
|
@@ -1209,16 +1428,13 @@ await apiGateway.start();
|
|
|
1209
1428
|
Easily set up a secure HTTPS server with automatic redirection from HTTP:
|
|
1210
1429
|
|
|
1211
1430
|
```typescript
|
|
1212
|
-
import { SmartProxy,
|
|
1431
|
+
import { SmartProxy, createCompleteHttpsServer } from '@push.rocks/smartproxy';
|
|
1213
1432
|
|
|
1214
1433
|
const webServer = new SmartProxy({
|
|
1215
1434
|
routes: [
|
|
1216
|
-
//
|
|
1217
|
-
...
|
|
1218
|
-
|
|
1219
|
-
target: { host: 'localhost', port: 8080 },
|
|
1220
|
-
certificate: 'auto',
|
|
1221
|
-
addHttpRedirect: true
|
|
1435
|
+
// createCompleteHttpsServer creates both the HTTPS route and HTTP redirect
|
|
1436
|
+
...createCompleteHttpsServer('example.com', { host: 'localhost', port: 8080 }, {
|
|
1437
|
+
certificate: 'auto'
|
|
1222
1438
|
})
|
|
1223
1439
|
]
|
|
1224
1440
|
});
|
|
@@ -1231,28 +1447,24 @@ await webServer.start();
|
|
|
1231
1447
|
Support dynamically created tenants with wildcard domain matching:
|
|
1232
1448
|
|
|
1233
1449
|
```typescript
|
|
1234
|
-
import { SmartProxy,
|
|
1450
|
+
import { SmartProxy, createDynamicRoute } from '@push.rocks/smartproxy';
|
|
1235
1451
|
|
|
1236
1452
|
const multiTenantApp = new SmartProxy({
|
|
1237
1453
|
routes: [
|
|
1238
|
-
//
|
|
1239
|
-
|
|
1454
|
+
// Dynamic routing based on subdomain
|
|
1455
|
+
createDynamicRoute({
|
|
1240
1456
|
ports: 443,
|
|
1241
|
-
domains: '*.example.com',
|
|
1242
|
-
|
|
1243
|
-
|
|
1244
|
-
|
|
1245
|
-
|
|
1246
|
-
|
|
1247
|
-
|
|
1248
|
-
}
|
|
1249
|
-
}
|
|
1457
|
+
domains: '*.tenant.example.com',
|
|
1458
|
+
targetHost: (context) => {
|
|
1459
|
+
// Extract tenant ID from subdomain
|
|
1460
|
+
const tenant = context.domain.split('.')[0];
|
|
1461
|
+
return `${tenant}-backend.internal`;
|
|
1462
|
+
},
|
|
1463
|
+
portMapper: (context) => 8080
|
|
1250
1464
|
}),
|
|
1251
1465
|
|
|
1252
1466
|
// Redirect HTTP to HTTPS for all subdomains
|
|
1253
|
-
createHttpToHttpsRedirect(
|
|
1254
|
-
domains: ['*.example.com']
|
|
1255
|
-
})
|
|
1467
|
+
createHttpToHttpsRedirect(['*.tenant.example.com'])
|
|
1256
1468
|
]
|
|
1257
1469
|
});
|
|
1258
1470
|
|
|
@@ -1266,68 +1478,63 @@ Create a comprehensive proxy solution with multiple services and security contro
|
|
|
1266
1478
|
```typescript
|
|
1267
1479
|
import {
|
|
1268
1480
|
SmartProxy,
|
|
1269
|
-
|
|
1270
|
-
|
|
1271
|
-
|
|
1272
|
-
createHttpToHttpsRedirect
|
|
1481
|
+
createHttpsTerminateRoute,
|
|
1482
|
+
createHttpsPassthroughRoute,
|
|
1483
|
+
createSocketHandlerRoute,
|
|
1484
|
+
createHttpToHttpsRedirect,
|
|
1485
|
+
SocketHandlers
|
|
1273
1486
|
} from '@push.rocks/smartproxy';
|
|
1274
1487
|
|
|
1275
1488
|
const enterpriseProxy = new SmartProxy({
|
|
1276
1489
|
routes: [
|
|
1277
1490
|
// Web application with automatic HTTPS
|
|
1278
|
-
|
|
1279
|
-
ports: 443,
|
|
1280
|
-
domains: 'app.example.com',
|
|
1281
|
-
target: { host: 'web-app', port: 8080 },
|
|
1491
|
+
createHttpsTerminateRoute('app.example.com', { host: 'web-app', port: 8080 }, {
|
|
1282
1492
|
certificate: 'auto'
|
|
1283
1493
|
}),
|
|
1284
1494
|
|
|
1285
1495
|
// Legacy system that needs HTTPS passthrough
|
|
1286
|
-
|
|
1287
|
-
ports: 443,
|
|
1288
|
-
domains: 'legacy.example.com',
|
|
1289
|
-
target: { host: 'legacy-server', port: 443 }
|
|
1290
|
-
}),
|
|
1496
|
+
createHttpsPassthroughRoute('legacy.example.com', { host: 'legacy-server', port: 443 }),
|
|
1291
1497
|
|
|
1292
1498
|
// Internal APIs with IP restrictions
|
|
1293
|
-
|
|
1294
|
-
ports: 443,
|
|
1295
|
-
|
|
1296
|
-
|
|
1297
|
-
|
|
1499
|
+
{
|
|
1500
|
+
match: { ports: 443, domains: 'api.internal.example.com' },
|
|
1501
|
+
action: {
|
|
1502
|
+
type: 'forward',
|
|
1503
|
+
target: { host: 'api-gateway', port: 3000 },
|
|
1504
|
+
tls: { mode: 'terminate', certificate: 'auto' }
|
|
1505
|
+
},
|
|
1298
1506
|
security: {
|
|
1299
|
-
|
|
1507
|
+
ipAllowList: ['10.0.0.0/16', '192.168.0.0/16'],
|
|
1300
1508
|
maxConnections: 500
|
|
1301
1509
|
}
|
|
1302
|
-
}
|
|
1510
|
+
},
|
|
1511
|
+
|
|
1512
|
+
// Custom protocol handler
|
|
1513
|
+
createSocketHandlerRoute('telnet.example.com', 23, SocketHandlers.lineProtocol((line, socket) => {
|
|
1514
|
+
// Handle telnet-like protocol
|
|
1515
|
+
socket.write(`Command received: ${line}\n`);
|
|
1516
|
+
})),
|
|
1303
1517
|
|
|
1304
1518
|
// Block known malicious IPs
|
|
1305
|
-
|
|
1306
|
-
ports: [80, 443],
|
|
1307
|
-
|
|
1308
|
-
|
|
1309
|
-
|
|
1519
|
+
{
|
|
1520
|
+
match: { ports: [80, 443], clientIp: ['1.2.3.*', '5.6.7.*'] },
|
|
1521
|
+
action: {
|
|
1522
|
+
type: 'socket-handler',
|
|
1523
|
+
socketHandler: SocketHandlers.block('Access denied')
|
|
1524
|
+
},
|
|
1525
|
+
priority: 1000 // High priority to ensure blocking
|
|
1526
|
+
},
|
|
1310
1527
|
|
|
1311
1528
|
// Redirect all HTTP to HTTPS
|
|
1312
|
-
createHttpToHttpsRedirect(
|
|
1313
|
-
domains: ['*.example.com', 'example.com']
|
|
1314
|
-
})
|
|
1529
|
+
createHttpToHttpsRedirect(['*.example.com', 'example.com'])
|
|
1315
1530
|
],
|
|
1316
1531
|
|
|
1317
|
-
// Global settings that apply to all routes
|
|
1318
|
-
defaults: {
|
|
1319
|
-
security: {
|
|
1320
|
-
maxConnections: 1000
|
|
1321
|
-
}
|
|
1322
|
-
},
|
|
1323
|
-
|
|
1324
1532
|
// Enable connection timeouts for security
|
|
1325
1533
|
inactivityTimeout: 30000,
|
|
1326
1534
|
|
|
1327
1535
|
// Using global certificate management
|
|
1328
1536
|
acme: {
|
|
1329
|
-
|
|
1330
|
-
contactEmail: 'admin@example.com',
|
|
1537
|
+
email: 'admin@example.com',
|
|
1331
1538
|
useProduction: true,
|
|
1332
1539
|
renewThresholdDays: 30
|
|
1333
1540
|
}
|
|
@@ -1355,6 +1562,9 @@ await enterpriseProxy.start();
|
|
|
1355
1562
|
- **tlsVersion**: `string[]` (optional)
|
|
1356
1563
|
Match specific TLS versions (e.g., `TLSv1.2`, `TLSv1.3`)
|
|
1357
1564
|
|
|
1565
|
+
- **headers**: `Record<string, string | RegExp>` (optional)
|
|
1566
|
+
Match specific HTTP headers
|
|
1567
|
+
|
|
1358
1568
|
### Action Types
|
|
1359
1569
|
|
|
1360
1570
|
1. **Forward**:
|
|
@@ -1366,18 +1576,13 @@ await enterpriseProxy.start();
|
|
|
1366
1576
|
}
|
|
1367
1577
|
```
|
|
1368
1578
|
|
|
1369
|
-
2. **
|
|
1579
|
+
2. **Socket Handler**:
|
|
1370
1580
|
```typescript
|
|
1371
1581
|
{
|
|
1372
|
-
type: '
|
|
1373
|
-
|
|
1374
|
-
|
|
1375
|
-
|
|
1376
|
-
|
|
1377
|
-
3. **Block**:
|
|
1378
|
-
```typescript
|
|
1379
|
-
{
|
|
1380
|
-
type: 'block'
|
|
1582
|
+
type: 'socket-handler',
|
|
1583
|
+
socketHandler: async (socket, context) => {
|
|
1584
|
+
// Custom protocol handling
|
|
1585
|
+
}
|
|
1381
1586
|
}
|
|
1382
1587
|
```
|
|
1383
1588
|
|
|
@@ -1400,10 +1605,17 @@ Template variables can be used in string values:
|
|
|
1400
1605
|
|
|
1401
1606
|
Example:
|
|
1402
1607
|
```typescript
|
|
1403
|
-
|
|
1404
|
-
|
|
1405
|
-
|
|
1406
|
-
|
|
1608
|
+
// Using the HTTP redirect helper
|
|
1609
|
+
createHttpToHttpsRedirect('old.example.com', 443)
|
|
1610
|
+
|
|
1611
|
+
// Or with custom redirect using socket handler
|
|
1612
|
+
{
|
|
1613
|
+
match: { ports: 80, domains: 'old.example.com' },
|
|
1614
|
+
action: {
|
|
1615
|
+
type: 'socket-handler',
|
|
1616
|
+
socketHandler: SocketHandlers.httpRedirect('https://new.example.com{path}?source=redirect', 301)
|
|
1617
|
+
}
|
|
1618
|
+
}
|
|
1407
1619
|
```
|
|
1408
1620
|
|
|
1409
1621
|
## Configuration Options
|
|
@@ -1447,17 +1659,6 @@ HttpProxy now supports full route-based configuration including:
|
|
|
1447
1659
|
- WebSocket configuration with path rewriting, custom headers, ping control, and size limits
|
|
1448
1660
|
- Context-aware CORS configuration
|
|
1449
1661
|
|
|
1450
|
-
### Port80Handler (IAcmeOptions)
|
|
1451
|
-
- `enabled` (boolean, default true)
|
|
1452
|
-
- `port` (number, default 80)
|
|
1453
|
-
- `contactEmail` (string)
|
|
1454
|
-
- `useProduction` (boolean, default false)
|
|
1455
|
-
- `renewThresholdDays` (number, default 30)
|
|
1456
|
-
- `autoRenew` (boolean, default true)
|
|
1457
|
-
- `certificateStore` (string)
|
|
1458
|
-
- `skipConfiguredCerts` (boolean)
|
|
1459
|
-
- `domainForwards` (IDomainForwardConfig[])
|
|
1460
|
-
|
|
1461
1662
|
### NfTablesProxy (INfTableProxySettings)
|
|
1462
1663
|
- `fromPort` / `toPort` (number|range|array)
|
|
1463
1664
|
- `toHost` (string, default 'localhost')
|
|
@@ -1479,6 +1680,7 @@ HttpProxy now supports full route-based configuration including:
|
|
|
1479
1680
|
- For domain matching issues, verify SNI extraction is working
|
|
1480
1681
|
- Use higher priority for block routes to ensure they take precedence
|
|
1481
1682
|
- Enable `enableDetailedLogging` or `enableTlsDebugLogging` for debugging
|
|
1683
|
+
- Security configuration must be at route level (`route.security`), not in action
|
|
1482
1684
|
|
|
1483
1685
|
### ACME HTTP-01 Challenges
|
|
1484
1686
|
- If ACME HTTP-01 challenges fail, ensure:
|
|
@@ -1502,6 +1704,12 @@ HttpProxy now supports full route-based configuration including:
|
|
|
1502
1704
|
- "Connection refused" during challenges → Update to v19.3.9+ for timing fix
|
|
1503
1705
|
- HTTP requests not parsed → Ensure port is in `useHttpProxy` array
|
|
1504
1706
|
|
|
1707
|
+
### Socket Handlers
|
|
1708
|
+
- Socket handlers require initial data from the client to trigger routing
|
|
1709
|
+
- For async handlers, initial data is buffered until handler setup completes (v19.5.0+)
|
|
1710
|
+
- Use `SocketHandlers.httpServer` for ACME challenge handling in custom implementations
|
|
1711
|
+
- Test socket handlers with telnet or nc for debugging
|
|
1712
|
+
|
|
1505
1713
|
### NFTables Integration
|
|
1506
1714
|
- Ensure NFTables is installed: `apt install nftables` or `yum install nftables`
|
|
1507
1715
|
- Verify root/sudo permissions for NFTables operations
|
|
@@ -1513,19 +1721,25 @@ HttpProxy now supports full route-based configuration including:
|
|
|
1513
1721
|
- For certificate issues, check the ACME settings and domain validation
|
|
1514
1722
|
- Ensure domains are publicly accessible for Let's Encrypt validation
|
|
1515
1723
|
- For TLS handshake issues, increase `initialDataTimeout` and `maxPendingDataSize`
|
|
1724
|
+
- Certificate configuration can be global or per-route
|
|
1516
1725
|
|
|
1517
1726
|
### HttpProxy
|
|
1518
1727
|
- Verify ports, certificates and `rejectUnauthorized` for TLS errors
|
|
1519
1728
|
- Configure CORS for preflight issues
|
|
1520
1729
|
- Increase `maxConnections` or `connectionPoolSize` under load
|
|
1730
|
+
- HttpProxy is designed for HTTPS/TLS termination, use direct forwarding for plain HTTP
|
|
1521
1731
|
|
|
1522
|
-
###
|
|
1523
|
-
-
|
|
1524
|
-
-
|
|
1732
|
+
### Security Configuration
|
|
1733
|
+
- Security must be defined at route level: `route.security`
|
|
1734
|
+
- IP lists support glob patterns: `192.168.*`, `10.?.?.1`
|
|
1735
|
+
- Block lists take precedence over allow lists
|
|
1736
|
+
- Authentication requires TLS termination
|
|
1737
|
+
- Route matching is separate from security enforcement
|
|
1525
1738
|
|
|
1526
1739
|
### NfTablesProxy
|
|
1527
1740
|
- Ensure `nft` is installed and run with sufficient privileges
|
|
1528
1741
|
- Use `forceCleanSlate:true` to clear conflicting rules
|
|
1742
|
+
- Check kernel modules are loaded: `lsmod | grep nf_tables`
|
|
1529
1743
|
|
|
1530
1744
|
## License and Legal Information
|
|
1531
1745
|
|