@push.rocks/smartproxy 13.1.3 → 15.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist_ts/00_commitinfo_data.js +3 -3
- package/dist_ts/proxies/smart-proxy/index.d.ts +5 -3
- package/dist_ts/proxies/smart-proxy/index.js +9 -5
- package/dist_ts/proxies/smart-proxy/models/index.d.ts +2 -0
- package/dist_ts/proxies/smart-proxy/models/index.js +2 -1
- package/dist_ts/proxies/smart-proxy/models/interfaces.d.ts +82 -15
- package/dist_ts/proxies/smart-proxy/models/interfaces.js +10 -1
- package/dist_ts/proxies/smart-proxy/models/route-types.d.ts +133 -0
- package/dist_ts/proxies/smart-proxy/models/route-types.js +2 -0
- package/dist_ts/proxies/smart-proxy/route-connection-handler.d.ts +55 -0
- package/dist_ts/proxies/smart-proxy/route-connection-handler.js +804 -0
- package/dist_ts/proxies/smart-proxy/route-helpers.d.ts +127 -0
- package/dist_ts/proxies/smart-proxy/route-helpers.js +196 -0
- package/dist_ts/proxies/smart-proxy/route-manager.d.ts +103 -0
- package/dist_ts/proxies/smart-proxy/route-manager.js +483 -0
- package/dist_ts/proxies/smart-proxy/smart-proxy.d.ts +19 -8
- package/dist_ts/proxies/smart-proxy/smart-proxy.js +239 -46
- package/package.json +2 -2
- package/readme.md +675 -446
- package/readme.plan.md +311 -250
- package/ts/00_commitinfo_data.ts +2 -2
- package/ts/proxies/smart-proxy/index.ts +20 -4
- package/ts/proxies/smart-proxy/models/index.ts +4 -0
- package/ts/proxies/smart-proxy/models/interfaces.ts +91 -13
- package/ts/proxies/smart-proxy/models/route-types.ts +184 -0
- package/ts/proxies/smart-proxy/route-connection-handler.ts +1117 -0
- package/ts/proxies/smart-proxy/route-helpers.ts +344 -0
- package/ts/proxies/smart-proxy/route-manager.ts +587 -0
- package/ts/proxies/smart-proxy/smart-proxy.ts +300 -69
package/readme.md
CHANGED
|
@@ -2,16 +2,16 @@
|
|
|
2
2
|
|
|
3
3
|
A unified high-performance proxy toolkit for Node.js, with **SmartProxy** as the central API to handle all your proxy needs:
|
|
4
4
|
|
|
5
|
-
- **Unified Configuration
|
|
5
|
+
- **Unified Route-Based Configuration**: Match/action pattern for clean, consistent traffic routing
|
|
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
|
|
9
|
+
- **Multiple Action Types**: Forward (with TLS modes), redirect, or block traffic
|
|
10
10
|
- **Security Features**: IP allowlists, connection limits, timeouts, and more
|
|
11
11
|
|
|
12
12
|
## Project Architecture Overview
|
|
13
13
|
|
|
14
|
-
SmartProxy has been restructured using a modern, modular architecture
|
|
14
|
+
SmartProxy has been restructured using a modern, modular architecture with a unified route-based configuration system in v14.0.0:
|
|
15
15
|
|
|
16
16
|
```
|
|
17
17
|
/ts
|
|
@@ -29,19 +29,17 @@ SmartProxy has been restructured using a modern, modular architecture to improve
|
|
|
29
29
|
│ │ ├── http-handler.ts # HTTP-only handler
|
|
30
30
|
│ │ └── ... # Other handlers
|
|
31
31
|
│ ├── /config # Configuration models
|
|
32
|
-
│ │ ├── forwarding-types.ts # Type definitions
|
|
33
|
-
│ │ ├── domain-config.ts # Domain config utilities
|
|
34
|
-
│ │ └── domain-manager.ts # Domain routing manager
|
|
35
32
|
│ └── /factory # Factory for creating handlers
|
|
36
33
|
├── /proxies # Different proxy implementations
|
|
37
34
|
│ ├── /smart-proxy # SmartProxy implementation
|
|
38
35
|
│ │ ├── /models # SmartProxy-specific interfaces
|
|
36
|
+
│ │ │ ├── route-types.ts # Route-based configuration types
|
|
37
|
+
│ │ │ └── interfaces.ts # SmartProxy interfaces
|
|
38
|
+
│ │ ├── route-helpers.ts # Helper functions for creating routes
|
|
39
|
+
│ │ ├── route-manager.ts # Route management system
|
|
39
40
|
│ │ ├── smart-proxy.ts # Main SmartProxy class
|
|
40
41
|
│ │ └── ... # Supporting classes
|
|
41
42
|
│ ├── /network-proxy # NetworkProxy implementation
|
|
42
|
-
│ │ ├── /models # NetworkProxy-specific interfaces
|
|
43
|
-
│ │ ├── network-proxy.ts # Main NetworkProxy class
|
|
44
|
-
│ │ └── ... # Supporting classes
|
|
45
43
|
│ └── /nftables-proxy # NfTablesProxy implementation
|
|
46
44
|
├── /tls # TLS-specific functionality
|
|
47
45
|
│ ├── /sni # SNI handling components
|
|
@@ -58,18 +56,20 @@ SmartProxy has been restructured using a modern, modular architecture to improve
|
|
|
58
56
|
|
|
59
57
|
- **SmartProxy** (`ts/proxies/smart-proxy/smart-proxy.ts`)
|
|
60
58
|
The central unified API for all proxy needs, featuring:
|
|
61
|
-
-
|
|
59
|
+
- Route-based configuration with match/action pattern
|
|
60
|
+
- Flexible matching criteria (ports, domains, paths, client IPs)
|
|
61
|
+
- Multiple action types (forward, redirect, block)
|
|
62
62
|
- Automatic certificate management
|
|
63
|
-
- Multiple forwarding types in one configuration
|
|
64
63
|
- Advanced security controls
|
|
65
|
-
- Flexible backend targeting options
|
|
66
64
|
|
|
67
65
|
### Helper Functions
|
|
68
66
|
|
|
69
|
-
- **
|
|
70
|
-
|
|
71
|
-
- **
|
|
72
|
-
Helper functions
|
|
67
|
+
- **createRoute**, **createHttpRoute**, **createHttpsRoute**, **createPassthroughRoute**
|
|
68
|
+
Helper functions to create different route configurations with clean syntax
|
|
69
|
+
- **createRedirectRoute**, **createHttpToHttpsRedirect**, **createBlockRoute**
|
|
70
|
+
Helper functions for common redirect and security configurations
|
|
71
|
+
- **createLoadBalancerRoute**, **createHttpsServer**
|
|
72
|
+
Helper functions for complex configurations
|
|
73
73
|
|
|
74
74
|
### Specialized Components
|
|
75
75
|
|
|
@@ -93,8 +93,8 @@ SmartProxy has been restructured using a modern, modular architecture to improve
|
|
|
93
93
|
|
|
94
94
|
### Interfaces and Types
|
|
95
95
|
|
|
96
|
-
- `
|
|
97
|
-
- `
|
|
96
|
+
- `IRouteConfig`, `IRouteMatch`, `IRouteAction` (`ts/proxies/smart-proxy/models/route-types.ts`)
|
|
97
|
+
- `IRoutedSmartProxyOptions` (`ts/proxies/smart-proxy/models/route-types.ts`)
|
|
98
98
|
- `INetworkProxyOptions` (`ts/proxies/network-proxy/models/types.ts`)
|
|
99
99
|
- `IAcmeOptions`, `IDomainOptions` (`ts/certificate/models/certificate-types.ts`)
|
|
100
100
|
- `INfTableProxySettings` (`ts/proxies/nftables-proxy/models/interfaces.ts`)
|
|
@@ -105,51 +105,71 @@ Install via npm:
|
|
|
105
105
|
npm install @push.rocks/smartproxy
|
|
106
106
|
```
|
|
107
107
|
|
|
108
|
-
## Quick Start with SmartProxy
|
|
108
|
+
## Quick Start with SmartProxy v14.0.0
|
|
109
109
|
|
|
110
|
-
SmartProxy
|
|
110
|
+
SmartProxy v14.0.0 introduces a new unified route-based configuration system that makes configuring proxies more flexible and intuitive.
|
|
111
111
|
|
|
112
112
|
```typescript
|
|
113
|
-
import {
|
|
114
|
-
|
|
115
|
-
|
|
113
|
+
import {
|
|
114
|
+
SmartProxy,
|
|
115
|
+
createHttpRoute,
|
|
116
|
+
createHttpsRoute,
|
|
117
|
+
createPassthroughRoute,
|
|
118
|
+
createHttpToHttpsRedirect
|
|
119
|
+
} from '@push.rocks/smartproxy';
|
|
120
|
+
|
|
121
|
+
// Create a new SmartProxy instance with route-based configuration
|
|
116
122
|
const proxy = new SmartProxy({
|
|
117
|
-
//
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
createDomainConfig('api.example.com', httpOnly({
|
|
123
|
+
// Define all your routing rules in one array
|
|
124
|
+
routes: [
|
|
125
|
+
// Basic HTTP route - forward traffic from port 80 to internal service
|
|
126
|
+
createHttpRoute({
|
|
127
|
+
ports: 80,
|
|
128
|
+
domains: 'api.example.com',
|
|
124
129
|
target: { host: 'localhost', port: 3000 }
|
|
125
|
-
})
|
|
130
|
+
}),
|
|
126
131
|
|
|
127
|
-
// HTTPS
|
|
128
|
-
|
|
132
|
+
// HTTPS route with TLS termination and automatic certificates
|
|
133
|
+
createHttpsRoute({
|
|
134
|
+
ports: 443,
|
|
135
|
+
domains: 'secure.example.com',
|
|
129
136
|
target: { host: 'localhost', port: 8080 },
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
137
|
+
certificate: 'auto' // Use Let's Encrypt
|
|
138
|
+
}),
|
|
139
|
+
|
|
140
|
+
// HTTPS passthrough for legacy systems
|
|
141
|
+
createPassthroughRoute({
|
|
142
|
+
ports: 443,
|
|
143
|
+
domains: 'legacy.example.com',
|
|
144
|
+
target: { host: '192.168.1.10', port: 443 }
|
|
145
|
+
}),
|
|
146
|
+
|
|
147
|
+
// Redirect HTTP to HTTPS
|
|
148
|
+
createHttpToHttpsRedirect({
|
|
149
|
+
domains: ['example.com', '*.example.com']
|
|
150
|
+
}),
|
|
151
|
+
|
|
152
|
+
// Complex load balancer setup with security controls
|
|
153
|
+
createLoadBalancerRoute({
|
|
154
|
+
domains: ['app.example.com'],
|
|
155
|
+
targets: ['192.168.1.10', '192.168.1.11', '192.168.1.12'],
|
|
156
|
+
targetPort: 8080,
|
|
157
|
+
tlsMode: 'terminate',
|
|
158
|
+
certificate: 'auto',
|
|
143
159
|
security: {
|
|
144
|
-
// IP filtering for enhanced security
|
|
145
160
|
allowedIps: ['10.0.0.*', '192.168.1.*'],
|
|
146
|
-
blockedIps: ['1.2.3.4']
|
|
161
|
+
blockedIps: ['1.2.3.4'],
|
|
162
|
+
maxConnections: 1000
|
|
147
163
|
}
|
|
148
|
-
})
|
|
164
|
+
})
|
|
149
165
|
],
|
|
150
166
|
|
|
151
|
-
//
|
|
152
|
-
|
|
167
|
+
// Global settings that apply to all routes
|
|
168
|
+
defaults: {
|
|
169
|
+
security: {
|
|
170
|
+
maxConnections: 500
|
|
171
|
+
}
|
|
172
|
+
},
|
|
153
173
|
|
|
154
174
|
// Automatic Let's Encrypt integration
|
|
155
175
|
acme: {
|
|
@@ -167,65 +187,359 @@ proxy.on('certificate', evt => {
|
|
|
167
187
|
// Start the proxy
|
|
168
188
|
await proxy.start();
|
|
169
189
|
|
|
170
|
-
// Dynamically add
|
|
171
|
-
await proxy.
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
190
|
+
// Dynamically add new routes later
|
|
191
|
+
await proxy.addRoutes([
|
|
192
|
+
createHttpsRoute({
|
|
193
|
+
domains: 'new-domain.com',
|
|
194
|
+
target: { host: 'localhost', port: 9000 },
|
|
195
|
+
certificate: 'auto'
|
|
196
|
+
})
|
|
175
197
|
]);
|
|
176
198
|
|
|
177
199
|
// Later, gracefully shut down
|
|
178
200
|
await proxy.stop();
|
|
179
201
|
```
|
|
180
202
|
|
|
181
|
-
|
|
203
|
+
## Route-Based Configuration System
|
|
204
|
+
|
|
205
|
+
SmartProxy v14.0.0 introduces a new unified route configuration system based on the `IRouteConfig` interface. This system follows a match/action pattern that makes routing more powerful, flexible, and declarative.
|
|
206
|
+
|
|
207
|
+
### IRouteConfig Interface
|
|
208
|
+
|
|
209
|
+
The `IRouteConfig` interface is the core building block of SmartProxy's configuration system. Each route definition consists of match criteria and an action to perform on matched traffic:
|
|
210
|
+
|
|
211
|
+
```typescript
|
|
212
|
+
interface IRouteConfig {
|
|
213
|
+
// What traffic to match (required)
|
|
214
|
+
match: IRouteMatch;
|
|
215
|
+
|
|
216
|
+
// What to do with matched traffic (required)
|
|
217
|
+
action: IRouteAction;
|
|
218
|
+
|
|
219
|
+
// Metadata (all optional)
|
|
220
|
+
name?: string; // Human-readable name for this route
|
|
221
|
+
description?: string; // Description of the route's purpose
|
|
222
|
+
priority?: number; // Controls matching order (higher = matched first)
|
|
223
|
+
tags?: string[]; // Arbitrary tags for categorization
|
|
224
|
+
}
|
|
225
|
+
```
|
|
226
|
+
|
|
227
|
+
#### Match Criteria (IRouteMatch)
|
|
228
|
+
|
|
229
|
+
The `match` property defines criteria for identifying which incoming traffic should be handled by this route:
|
|
230
|
+
|
|
231
|
+
```typescript
|
|
232
|
+
interface IRouteMatch {
|
|
233
|
+
// Listen on these ports (required)
|
|
234
|
+
ports: TPortRange; // number | number[] | Array<{ from: number; to: number }>
|
|
235
|
+
|
|
236
|
+
// Optional domain patterns to match (default: all domains)
|
|
237
|
+
domains?: string | string[]; // Supports wildcards like '*.example.com'
|
|
238
|
+
|
|
239
|
+
// Advanced matching criteria (all optional)
|
|
240
|
+
path?: string; // Match specific URL paths, supports glob patterns
|
|
241
|
+
clientIp?: string[]; // Match specific client IPs, supports glob patterns
|
|
242
|
+
tlsVersion?: string[]; // Match specific TLS versions e.g. ['TLSv1.2', 'TLSv1.3']
|
|
243
|
+
}
|
|
244
|
+
```
|
|
245
|
+
|
|
246
|
+
**Port Specification:**
|
|
247
|
+
- **Single port:** `ports: 80`
|
|
248
|
+
- **Multiple ports:** `ports: [80, 443]`
|
|
249
|
+
- **Port ranges:** `ports: [{ from: 8000, to: 8100 }]`
|
|
250
|
+
- **Mixed format:** `ports: [80, 443, { from: 8000, to: 8100 }]`
|
|
251
|
+
|
|
252
|
+
**Domain Matching:**
|
|
253
|
+
- **Single domain:** `domains: 'example.com'`
|
|
254
|
+
- **Multiple domains:** `domains: ['example.com', 'api.example.com']`
|
|
255
|
+
- **Wildcard domains:** `domains: '*.example.com'` (matches any subdomain)
|
|
256
|
+
- **Root domain + subdomains:** `domains: ['example.com', '*.example.com']`
|
|
257
|
+
|
|
258
|
+
**Path Matching:**
|
|
259
|
+
- **Exact path:** `path: '/api'` (matches only /api exactly)
|
|
260
|
+
- **Prefix match:** `path: '/api/*'` (matches /api and any paths under it)
|
|
261
|
+
- **Multiple patterns:** Use multiple routes with different priorities
|
|
262
|
+
|
|
263
|
+
**Client IP Matching:**
|
|
264
|
+
- **Exact IP:** `clientIp: ['192.168.1.1']`
|
|
265
|
+
- **Subnet wildcards:** `clientIp: ['10.0.0.*', '192.168.1.*']`
|
|
266
|
+
- **CIDR notation:** `clientIp: ['10.0.0.0/24']`
|
|
267
|
+
|
|
268
|
+
**TLS Version Matching:**
|
|
269
|
+
- `tlsVersion: ['TLSv1.2', 'TLSv1.3']` (only match these TLS versions)
|
|
270
|
+
|
|
271
|
+
#### Action Configuration (IRouteAction)
|
|
272
|
+
|
|
273
|
+
The `action` property defines what to do with traffic that matches the criteria:
|
|
274
|
+
|
|
275
|
+
```typescript
|
|
276
|
+
interface IRouteAction {
|
|
277
|
+
// Action type (required)
|
|
278
|
+
type: 'forward' | 'redirect' | 'block';
|
|
279
|
+
|
|
280
|
+
// For 'forward' actions
|
|
281
|
+
target?: IRouteTarget;
|
|
282
|
+
|
|
283
|
+
// TLS handling for 'forward' actions
|
|
284
|
+
tls?: IRouteTls;
|
|
285
|
+
|
|
286
|
+
// For 'redirect' actions
|
|
287
|
+
redirect?: IRouteRedirect;
|
|
288
|
+
|
|
289
|
+
// Security options for any action
|
|
290
|
+
security?: IRouteSecurity;
|
|
291
|
+
|
|
292
|
+
// Advanced options
|
|
293
|
+
advanced?: IRouteAdvanced;
|
|
294
|
+
}
|
|
295
|
+
```
|
|
296
|
+
|
|
297
|
+
**Forward Action:**
|
|
298
|
+
When `type: 'forward'`, the traffic is forwarded to the specified target:
|
|
299
|
+
```typescript
|
|
300
|
+
interface IRouteTarget {
|
|
301
|
+
host: string | string[]; // Target host(s) - string array enables round-robin
|
|
302
|
+
port: number; // Target port
|
|
303
|
+
preservePort?: boolean; // Use incoming port as target port (default: false)
|
|
304
|
+
}
|
|
305
|
+
```
|
|
306
|
+
|
|
307
|
+
**TLS Configuration:**
|
|
308
|
+
When forwarding with TLS, you can configure how TLS is handled:
|
|
309
|
+
```typescript
|
|
310
|
+
interface IRouteTls {
|
|
311
|
+
mode: 'passthrough' | 'terminate' | 'terminate-and-reencrypt';
|
|
312
|
+
certificate?: 'auto' | { // 'auto' = use ACME (Let's Encrypt)
|
|
313
|
+
key: string; // TLS private key content
|
|
314
|
+
cert: string; // TLS certificate content
|
|
315
|
+
};
|
|
316
|
+
}
|
|
317
|
+
```
|
|
318
|
+
|
|
319
|
+
**TLS Modes:**
|
|
320
|
+
- **passthrough:** Forward raw encrypted TLS traffic without decryption
|
|
321
|
+
- **terminate:** Terminate TLS and forward as HTTP
|
|
322
|
+
- **terminate-and-reencrypt:** Terminate TLS and create a new TLS connection to the backend
|
|
323
|
+
|
|
324
|
+
**Redirect Action:**
|
|
325
|
+
When `type: 'redirect'`, the client is redirected:
|
|
326
|
+
```typescript
|
|
327
|
+
interface IRouteRedirect {
|
|
328
|
+
to: string; // URL or template with variables
|
|
329
|
+
status: 301 | 302 | 307 | 308; // HTTP status code
|
|
330
|
+
}
|
|
331
|
+
```
|
|
332
|
+
|
|
333
|
+
**Block Action:**
|
|
334
|
+
When `type: 'block'`, the connection is immediately closed.
|
|
335
|
+
|
|
336
|
+
**Security Options:**
|
|
337
|
+
For any action type, you can add security controls:
|
|
338
|
+
```typescript
|
|
339
|
+
interface IRouteSecurity {
|
|
340
|
+
allowedIps?: string[]; // IP allowlist with glob pattern support
|
|
341
|
+
blockedIps?: string[]; // IP blocklist with glob pattern support
|
|
342
|
+
maxConnections?: number; // Maximum concurrent connections
|
|
343
|
+
authentication?: { // Optional authentication (future support)
|
|
344
|
+
type: 'basic' | 'digest' | 'oauth';
|
|
345
|
+
// Auth-specific options
|
|
346
|
+
};
|
|
347
|
+
}
|
|
348
|
+
```
|
|
349
|
+
|
|
350
|
+
**Advanced Options:**
|
|
351
|
+
Additional advanced configurations:
|
|
352
|
+
```typescript
|
|
353
|
+
interface IRouteAdvanced {
|
|
354
|
+
timeout?: number; // Connection timeout in milliseconds
|
|
355
|
+
headers?: Record<string, string>; // Custom HTTP headers
|
|
356
|
+
keepAlive?: boolean; // Enable connection pooling
|
|
357
|
+
// Additional advanced options
|
|
358
|
+
}
|
|
359
|
+
```
|
|
360
|
+
|
|
361
|
+
#### Template Variables
|
|
362
|
+
|
|
363
|
+
String values in redirect URLs and headers can include variables:
|
|
364
|
+
|
|
365
|
+
- `{domain}`: The requested domain name
|
|
366
|
+
- `{port}`: The incoming port number
|
|
367
|
+
- `{path}`: The requested URL path
|
|
368
|
+
- `{query}`: The query string
|
|
369
|
+
- `{clientIp}`: The client's IP address
|
|
370
|
+
- `{sni}`: The SNI hostname
|
|
371
|
+
|
|
372
|
+
Example with template variables:
|
|
373
|
+
```typescript
|
|
374
|
+
redirect: {
|
|
375
|
+
to: 'https://{domain}{path}?source=redirect',
|
|
376
|
+
status: 301
|
|
377
|
+
}
|
|
378
|
+
```
|
|
379
|
+
|
|
380
|
+
#### Route Metadata and Prioritization
|
|
381
|
+
|
|
382
|
+
You can add metadata to routes to help with organization and control matching priority:
|
|
383
|
+
|
|
384
|
+
```typescript
|
|
385
|
+
{
|
|
386
|
+
name: 'API Server', // Human-readable name
|
|
387
|
+
description: 'Main API endpoints', // Description
|
|
388
|
+
priority: 100, // Matching priority (higher = matched first)
|
|
389
|
+
tags: ['api', 'internal'] // Arbitrary tags
|
|
390
|
+
}
|
|
391
|
+
```
|
|
392
|
+
|
|
393
|
+
Routes with higher priority values are matched first, allowing you to create specialized routes that take precedence over more general ones.
|
|
394
|
+
|
|
395
|
+
#### Complete Route Configuration Example
|
|
396
|
+
|
|
397
|
+
```typescript
|
|
398
|
+
// Example of a complete route configuration
|
|
399
|
+
{
|
|
400
|
+
match: {
|
|
401
|
+
ports: 443,
|
|
402
|
+
domains: ['api.example.com', 'api-v2.example.com'],
|
|
403
|
+
path: '/secure/*',
|
|
404
|
+
clientIp: ['10.0.0.*', '192.168.1.*']
|
|
405
|
+
},
|
|
406
|
+
action: {
|
|
407
|
+
type: 'forward',
|
|
408
|
+
target: {
|
|
409
|
+
host: ['10.0.0.1', '10.0.0.2'], // Round-robin between these hosts
|
|
410
|
+
port: 8080
|
|
411
|
+
},
|
|
412
|
+
tls: {
|
|
413
|
+
mode: 'terminate',
|
|
414
|
+
certificate: 'auto' // Use Let's Encrypt
|
|
415
|
+
},
|
|
416
|
+
security: {
|
|
417
|
+
allowedIps: ['10.0.0.*'],
|
|
418
|
+
maxConnections: 100
|
|
419
|
+
},
|
|
420
|
+
advanced: {
|
|
421
|
+
timeout: 30000,
|
|
422
|
+
headers: {
|
|
423
|
+
'X-Original-Host': '{domain}',
|
|
424
|
+
'X-Client-IP': '{clientIp}'
|
|
425
|
+
},
|
|
426
|
+
keepAlive: true
|
|
427
|
+
}
|
|
428
|
+
},
|
|
429
|
+
name: 'Secure API Route',
|
|
430
|
+
description: 'Route for secure API endpoints with authentication',
|
|
431
|
+
priority: 100,
|
|
432
|
+
tags: ['api', 'secure', 'internal']
|
|
433
|
+
}
|
|
434
|
+
```
|
|
435
|
+
|
|
436
|
+
### Using Helper Functions
|
|
437
|
+
|
|
438
|
+
While you can create route configurations manually, SmartProxy provides helper functions to make it easier:
|
|
439
|
+
|
|
440
|
+
```typescript
|
|
441
|
+
// Instead of building the full object:
|
|
442
|
+
const route = {
|
|
443
|
+
match: { ports: 80, domains: 'example.com' },
|
|
444
|
+
action: { type: 'forward', target: { host: 'localhost', port: 8080 } },
|
|
445
|
+
name: 'Web Server'
|
|
446
|
+
};
|
|
447
|
+
|
|
448
|
+
// Use the helper function:
|
|
449
|
+
const route = createHttpRoute({
|
|
450
|
+
domains: 'example.com',
|
|
451
|
+
target: { host: 'localhost', port: 8080 },
|
|
452
|
+
name: 'Web Server'
|
|
453
|
+
});
|
|
454
|
+
```
|
|
455
|
+
|
|
456
|
+
Available helper functions:
|
|
457
|
+
- `createRoute()` - Basic function to create any route configuration
|
|
458
|
+
- `createHttpRoute()` - Create an HTTP forwarding route
|
|
459
|
+
- `createHttpsRoute()` - Create an HTTPS route with TLS termination
|
|
460
|
+
- `createPassthroughRoute()` - Create an HTTPS passthrough route
|
|
461
|
+
- `createRedirectRoute()` - Create a generic redirect route
|
|
462
|
+
- `createHttpToHttpsRedirect()` - Create an HTTP to HTTPS redirect
|
|
463
|
+
- `createBlockRoute()` - Create a route to block specific traffic
|
|
464
|
+
- `createLoadBalancerRoute()` - Create a route for load balancing
|
|
465
|
+
- `createHttpsServer()` - Create a complete HTTPS server setup with HTTP redirect
|
|
182
466
|
|
|
183
|
-
|
|
467
|
+
## What You Can Do with SmartProxy
|
|
468
|
+
|
|
469
|
+
1. **Route-Based Traffic Management**
|
|
184
470
|
```typescript
|
|
185
471
|
// Route requests for different domains to different backend servers
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
472
|
+
createHttpsRoute({
|
|
473
|
+
domains: 'api.example.com',
|
|
474
|
+
target: { host: 'api-server', port: 3000 },
|
|
475
|
+
certificate: 'auto'
|
|
476
|
+
})
|
|
189
477
|
```
|
|
190
478
|
|
|
191
479
|
2. **Automatic SSL with Let's Encrypt**
|
|
192
480
|
```typescript
|
|
193
481
|
// Get and automatically renew certificates
|
|
194
|
-
|
|
482
|
+
createHttpsRoute({
|
|
483
|
+
domains: 'secure.example.com',
|
|
195
484
|
target: { host: 'localhost', port: 8080 },
|
|
196
|
-
|
|
197
|
-
})
|
|
485
|
+
certificate: 'auto'
|
|
486
|
+
})
|
|
198
487
|
```
|
|
199
488
|
|
|
200
489
|
3. **Load Balancing**
|
|
201
490
|
```typescript
|
|
202
491
|
// Distribute traffic across multiple backend servers
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
492
|
+
createLoadBalancerRoute({
|
|
493
|
+
domains: 'app.example.com',
|
|
494
|
+
targets: ['10.0.0.1', '10.0.0.2', '10.0.0.3'],
|
|
495
|
+
targetPort: 8080,
|
|
496
|
+
tlsMode: 'terminate',
|
|
497
|
+
certificate: 'auto'
|
|
498
|
+
})
|
|
209
499
|
```
|
|
210
500
|
|
|
211
501
|
4. **Security Controls**
|
|
212
502
|
```typescript
|
|
213
503
|
// Restrict access based on IP addresses
|
|
214
|
-
|
|
504
|
+
createHttpsRoute({
|
|
505
|
+
domains: 'admin.example.com',
|
|
215
506
|
target: { host: 'localhost', port: 8080 },
|
|
507
|
+
certificate: 'auto',
|
|
216
508
|
security: {
|
|
217
509
|
allowedIps: ['10.0.0.*', '192.168.1.*'],
|
|
218
510
|
maxConnections: 100
|
|
219
511
|
}
|
|
220
|
-
})
|
|
512
|
+
})
|
|
221
513
|
```
|
|
222
514
|
|
|
223
515
|
5. **Wildcard Domains**
|
|
224
516
|
```typescript
|
|
225
517
|
// Handle all subdomains with one config
|
|
226
|
-
|
|
518
|
+
createPassthroughRoute({
|
|
519
|
+
domains: ['example.com', '*.example.com'],
|
|
227
520
|
target: { host: 'backend-server', port: 443 }
|
|
228
|
-
})
|
|
521
|
+
})
|
|
522
|
+
```
|
|
523
|
+
|
|
524
|
+
6. **Path-Based Routing**
|
|
525
|
+
```typescript
|
|
526
|
+
// Route based on URL path
|
|
527
|
+
createHttpsRoute({
|
|
528
|
+
domains: 'example.com',
|
|
529
|
+
path: '/api/*',
|
|
530
|
+
target: { host: 'api-server', port: 3000 },
|
|
531
|
+
certificate: 'auto'
|
|
532
|
+
})
|
|
533
|
+
```
|
|
534
|
+
|
|
535
|
+
7. **Block Malicious Traffic**
|
|
536
|
+
```typescript
|
|
537
|
+
// Block traffic from specific IPs
|
|
538
|
+
createBlockRoute({
|
|
539
|
+
ports: [80, 443],
|
|
540
|
+
clientIp: ['1.2.3.*', '5.6.7.*'],
|
|
541
|
+
priority: 1000 // High priority to ensure blocking
|
|
542
|
+
})
|
|
229
543
|
```
|
|
230
544
|
|
|
231
545
|
## Other Components
|
|
@@ -293,13 +607,57 @@ const redirect = new SslRedirect(80);
|
|
|
293
607
|
await redirect.start();
|
|
294
608
|
```
|
|
295
609
|
|
|
296
|
-
##
|
|
297
|
-
|
|
298
|
-
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
610
|
+
## Migration from v13.x to v14.0.0
|
|
611
|
+
|
|
612
|
+
Version 14.0.0 introduces a breaking change with the new route-based configuration system:
|
|
613
|
+
|
|
614
|
+
### Key Changes
|
|
615
|
+
|
|
616
|
+
1. **Configuration Structure**: The configuration now uses the match/action pattern instead of the old domain-based and port-based approach
|
|
617
|
+
2. **SmartProxy Options**: Now takes an array of route configurations instead of `domainConfigs` and port ranges
|
|
618
|
+
3. **Helper Functions**: New helper functions have been introduced to simplify configuration
|
|
619
|
+
|
|
620
|
+
### Migration Example
|
|
621
|
+
|
|
622
|
+
**v13.x Configuration**:
|
|
623
|
+
```typescript
|
|
624
|
+
import { SmartProxy, createDomainConfig, httpOnly, tlsTerminateToHttp } from '@push.rocks/smartproxy';
|
|
625
|
+
|
|
626
|
+
const proxy = new SmartProxy({
|
|
627
|
+
fromPort: 443,
|
|
628
|
+
domainConfigs: [
|
|
629
|
+
createDomainConfig('example.com', tlsTerminateToHttp({
|
|
630
|
+
target: { host: 'localhost', port: 8080 },
|
|
631
|
+
acme: { enabled: true, production: true }
|
|
632
|
+
}))
|
|
633
|
+
],
|
|
634
|
+
sniEnabled: true
|
|
635
|
+
});
|
|
636
|
+
```
|
|
637
|
+
|
|
638
|
+
**v14.0.0 Configuration**:
|
|
639
|
+
```typescript
|
|
640
|
+
import { SmartProxy, createHttpsRoute } from '@push.rocks/smartproxy';
|
|
641
|
+
|
|
642
|
+
const proxy = new SmartProxy({
|
|
643
|
+
routes: [
|
|
644
|
+
createHttpsRoute({
|
|
645
|
+
ports: 443,
|
|
646
|
+
domains: 'example.com',
|
|
647
|
+
target: { host: 'localhost', port: 8080 },
|
|
648
|
+
certificate: 'auto'
|
|
649
|
+
})
|
|
650
|
+
]
|
|
651
|
+
});
|
|
652
|
+
```
|
|
653
|
+
|
|
654
|
+
### Migration Steps
|
|
655
|
+
|
|
656
|
+
1. Replace `domainConfigs` with an array of route configurations using `routes`
|
|
657
|
+
2. Convert each domain configuration to use the new helper functions
|
|
658
|
+
3. Update any code that uses `updateDomainConfigs()` to use `addRoutes()` or `updateRoutes()`
|
|
659
|
+
4. For port-only configurations, create route configurations with port matching only
|
|
660
|
+
5. For SNI-based routing, SNI is now automatically enabled when needed
|
|
303
661
|
|
|
304
662
|
## Architecture & Flow Diagrams
|
|
305
663
|
|
|
@@ -309,11 +667,10 @@ flowchart TB
|
|
|
309
667
|
|
|
310
668
|
subgraph "SmartProxy Components"
|
|
311
669
|
direction TB
|
|
312
|
-
|
|
670
|
+
RouteConfig["Route Configuration<br>(Match/Action)"]
|
|
671
|
+
RouteManager["Route Manager"]
|
|
313
672
|
HTTPS443["HTTPS Port 443<br>NetworkProxy"]
|
|
314
673
|
SmartProxy["SmartProxy<br>(TCP/SNI Proxy)"]
|
|
315
|
-
NfTables[NfTablesProxy]
|
|
316
|
-
Router[ProxyRouter]
|
|
317
674
|
ACME["Port80Handler<br>(ACME HTTP-01)"]
|
|
318
675
|
Certs[(SSL Certificates)]
|
|
319
676
|
end
|
|
@@ -324,188 +681,110 @@ flowchart TB
|
|
|
324
681
|
Service3[Service 3]
|
|
325
682
|
end
|
|
326
683
|
|
|
327
|
-
Client -->|HTTP Request|
|
|
328
|
-
HTTP80 -->|Redirect| Client
|
|
329
|
-
Client -->|HTTPS Request| HTTPS443
|
|
330
|
-
Client -->|TLS/TCP| SmartProxy
|
|
331
|
-
|
|
332
|
-
HTTPS443 -->|Route Request| Router
|
|
333
|
-
Router -->|Proxy Request| Service1
|
|
334
|
-
Router -->|Proxy Request| Service2
|
|
684
|
+
Client -->|HTTP/HTTPS Request| SmartProxy
|
|
335
685
|
|
|
336
|
-
SmartProxy -->|
|
|
337
|
-
|
|
686
|
+
SmartProxy -->|Route Matching| RouteManager
|
|
687
|
+
RouteManager -->|Use| RouteConfig
|
|
688
|
+
RouteManager -->|Execute Action| SmartProxy
|
|
338
689
|
|
|
339
|
-
|
|
690
|
+
SmartProxy -->|Forward| Service1
|
|
691
|
+
SmartProxy -->|Redirect| Client
|
|
692
|
+
SmartProxy -->|Forward| Service2
|
|
693
|
+
SmartProxy -->|Forward| Service3
|
|
340
694
|
|
|
341
|
-
HTTP80 -.->|Challenge Response| ACME
|
|
342
695
|
ACME -.->|Generate/Manage| Certs
|
|
343
|
-
Certs -.->|Provide TLS Certs|
|
|
696
|
+
Certs -.->|Provide TLS Certs| SmartProxy
|
|
344
697
|
|
|
345
698
|
classDef component fill:#f9f,stroke:#333,stroke-width:2px;
|
|
346
699
|
classDef backend fill:#bbf,stroke:#333,stroke-width:1px;
|
|
347
700
|
classDef client fill:#dfd,stroke:#333,stroke-width:2px;
|
|
348
701
|
|
|
349
702
|
class Client client;
|
|
350
|
-
class
|
|
703
|
+
class RouteConfig,RouteManager,HTTPS443,SmartProxy,ACME component;
|
|
351
704
|
class Service1,Service2,Service3 backend;
|
|
352
705
|
```
|
|
353
706
|
|
|
354
|
-
###
|
|
355
|
-
This diagram
|
|
707
|
+
### Route-Based Connection Handling
|
|
708
|
+
This diagram illustrates how requests are matched and processed using the route-based configuration:
|
|
356
709
|
|
|
357
710
|
```mermaid
|
|
358
711
|
sequenceDiagram
|
|
359
712
|
participant Client
|
|
360
|
-
participant
|
|
361
|
-
participant
|
|
713
|
+
participant SmartProxy
|
|
714
|
+
participant RouteManager
|
|
362
715
|
participant Backend
|
|
363
716
|
|
|
364
|
-
Client->>
|
|
717
|
+
Client->>SmartProxy: Connection (TCP/HTTP/HTTPS)
|
|
365
718
|
|
|
366
|
-
|
|
719
|
+
SmartProxy->>RouteManager: Match connection against routes
|
|
367
720
|
|
|
368
|
-
|
|
369
|
-
|
|
721
|
+
RouteManager->>RouteManager: Check port match
|
|
722
|
+
RouteManager->>RouteManager: Check domain match (if SNI)
|
|
723
|
+
RouteManager->>RouteManager: Check path match (if HTTP)
|
|
724
|
+
RouteManager->>RouteManager: Check client IP match
|
|
725
|
+
RouteManager->>RouteManager: Check TLS version match
|
|
370
726
|
|
|
371
|
-
|
|
372
|
-
NetworkProxy->>Client: Request Authentication
|
|
373
|
-
Client->>NetworkProxy: Send Credentials
|
|
374
|
-
NetworkProxy->>NetworkProxy: Validate Credentials
|
|
375
|
-
end
|
|
727
|
+
RouteManager->>RouteManager: Determine highest priority matching route
|
|
376
728
|
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
Note over NetworkProxy: Add Default Headers
|
|
381
|
-
|
|
382
|
-
NetworkProxy->>Client: Forward Response
|
|
383
|
-
|
|
384
|
-
alt WebSocket Request
|
|
385
|
-
Client->>NetworkProxy: Upgrade to WebSocket
|
|
386
|
-
NetworkProxy->>Backend: Upgrade to WebSocket
|
|
387
|
-
loop WebSocket Active
|
|
388
|
-
Client->>NetworkProxy: WebSocket Message
|
|
389
|
-
NetworkProxy->>Backend: Forward Message
|
|
390
|
-
Backend->>NetworkProxy: WebSocket Message
|
|
391
|
-
NetworkProxy->>Client: Forward Message
|
|
392
|
-
NetworkProxy-->>NetworkProxy: Heartbeat Check
|
|
393
|
-
end
|
|
394
|
-
end
|
|
395
|
-
```
|
|
396
|
-
|
|
397
|
-
### SNI-based Connection Handling
|
|
398
|
-
This diagram illustrates how TCP connections with SNI (Server Name Indication) are processed and forwarded:
|
|
399
|
-
|
|
400
|
-
```mermaid
|
|
401
|
-
sequenceDiagram
|
|
402
|
-
participant Client
|
|
403
|
-
participant SmartProxy
|
|
404
|
-
participant Backend
|
|
405
|
-
|
|
406
|
-
Client->>SmartProxy: TLS Connection
|
|
407
|
-
|
|
408
|
-
alt SNI Enabled
|
|
409
|
-
SmartProxy->>Client: Accept Connection
|
|
410
|
-
Client->>SmartProxy: TLS ClientHello with SNI
|
|
411
|
-
SmartProxy->>SmartProxy: Extract SNI Hostname
|
|
412
|
-
SmartProxy->>SmartProxy: Match Domain Config
|
|
413
|
-
SmartProxy->>SmartProxy: Validate Client IP
|
|
729
|
+
alt Forward Action
|
|
730
|
+
RouteManager->>SmartProxy: Use forward action
|
|
414
731
|
|
|
415
|
-
alt
|
|
416
|
-
SmartProxy->>
|
|
417
|
-
|
|
418
|
-
else
|
|
419
|
-
SmartProxy->>
|
|
732
|
+
alt TLS Termination
|
|
733
|
+
SmartProxy->>SmartProxy: Terminate TLS
|
|
734
|
+
SmartProxy->>Backend: Forward as HTTP/HTTPS
|
|
735
|
+
else TLS Passthrough
|
|
736
|
+
SmartProxy->>Backend: Forward raw TCP
|
|
420
737
|
end
|
|
421
|
-
else Port-based Routing
|
|
422
|
-
SmartProxy->>SmartProxy: Match Port Range
|
|
423
|
-
SmartProxy->>SmartProxy: Find Domain Config
|
|
424
|
-
SmartProxy->>SmartProxy: Validate Client IP
|
|
425
738
|
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
739
|
+
else Redirect Action
|
|
740
|
+
RouteManager->>SmartProxy: Use redirect action
|
|
741
|
+
SmartProxy->>Client: Send redirect response
|
|
742
|
+
|
|
743
|
+
else Block Action
|
|
744
|
+
RouteManager->>SmartProxy: Use block action
|
|
745
|
+
SmartProxy->>Client: Close connection
|
|
432
746
|
end
|
|
433
747
|
|
|
434
748
|
loop Connection Active
|
|
435
749
|
SmartProxy-->>SmartProxy: Monitor Activity
|
|
436
|
-
SmartProxy-->>SmartProxy: Check
|
|
437
|
-
alt
|
|
750
|
+
SmartProxy-->>SmartProxy: Check Security Rules
|
|
751
|
+
alt Security Violation or Timeout
|
|
438
752
|
SmartProxy->>Client: Close Connection
|
|
439
753
|
SmartProxy->>Backend: Close Connection
|
|
440
754
|
end
|
|
441
755
|
end
|
|
442
756
|
```
|
|
443
757
|
|
|
444
|
-
### Let's Encrypt Certificate Acquisition
|
|
445
|
-
This diagram shows how certificates are automatically acquired through the ACME protocol:
|
|
446
|
-
|
|
447
|
-
```mermaid
|
|
448
|
-
sequenceDiagram
|
|
449
|
-
participant Client
|
|
450
|
-
participant Port80Handler
|
|
451
|
-
participant ACME as Let's Encrypt ACME
|
|
452
|
-
participant NetworkProxy
|
|
453
|
-
|
|
454
|
-
Client->>Port80Handler: HTTP Request for domain
|
|
455
|
-
|
|
456
|
-
alt Certificate Exists
|
|
457
|
-
Port80Handler->>Client: Redirect to HTTPS
|
|
458
|
-
else No Certificate
|
|
459
|
-
Port80Handler->>Port80Handler: Mark domain as obtaining cert
|
|
460
|
-
Port80Handler->>ACME: Create account & new order
|
|
461
|
-
ACME->>Port80Handler: Challenge information
|
|
462
|
-
|
|
463
|
-
Port80Handler->>Port80Handler: Store challenge token & key authorization
|
|
464
|
-
|
|
465
|
-
ACME->>Port80Handler: HTTP-01 Challenge Request
|
|
466
|
-
Port80Handler->>ACME: Challenge Response
|
|
467
|
-
|
|
468
|
-
ACME->>ACME: Validate domain ownership
|
|
469
|
-
ACME->>Port80Handler: Challenge validated
|
|
470
|
-
|
|
471
|
-
Port80Handler->>Port80Handler: Generate CSR
|
|
472
|
-
Port80Handler->>ACME: Submit CSR
|
|
473
|
-
ACME->>Port80Handler: Issue Certificate
|
|
474
|
-
|
|
475
|
-
Port80Handler->>Port80Handler: Store certificate & private key
|
|
476
|
-
Port80Handler->>Port80Handler: Mark certificate as obtained
|
|
477
|
-
|
|
478
|
-
Note over Port80Handler,NetworkProxy: Certificate available for use
|
|
479
|
-
|
|
480
|
-
Client->>Port80Handler: Another HTTP Request
|
|
481
|
-
Port80Handler->>Client: Redirect to HTTPS
|
|
482
|
-
Client->>NetworkProxy: HTTPS Request
|
|
483
|
-
Note over NetworkProxy: Uses new certificate
|
|
484
|
-
end
|
|
485
|
-
```
|
|
486
|
-
|
|
487
758
|
## Features
|
|
488
759
|
|
|
489
|
-
-
|
|
490
|
-
•
|
|
760
|
+
- **Route-Based Traffic Management**
|
|
761
|
+
• Match/action pattern for flexible routing
|
|
762
|
+
• Port, domain, path, client IP, and TLS version matching
|
|
763
|
+
• Multiple action types (forward, redirect, block)
|
|
491
764
|
|
|
492
|
-
-
|
|
493
|
-
•
|
|
765
|
+
- **TLS Handling Options**
|
|
766
|
+
• TLS passthrough for end-to-end encryption
|
|
767
|
+
• TLS termination for content inspection
|
|
768
|
+
• TLS termination with re-encryption for gateway scenarios
|
|
494
769
|
|
|
495
|
-
-
|
|
496
|
-
•
|
|
770
|
+
- **Automatic ACME Certificates**
|
|
771
|
+
• HTTP-01 challenge handling
|
|
772
|
+
• Certificate issuance/renewal
|
|
773
|
+
• Pluggable storage
|
|
497
774
|
|
|
498
|
-
-
|
|
499
|
-
•
|
|
775
|
+
- **Security Controls**
|
|
776
|
+
• IP allow/block lists with glob pattern support
|
|
777
|
+
• Connection limits and rate limiting
|
|
778
|
+
• Timeout controls and connection monitoring
|
|
500
779
|
|
|
501
|
-
-
|
|
502
|
-
•
|
|
780
|
+
- **Load Balancing**
|
|
781
|
+
• Round-robin distribution across multiple backends
|
|
782
|
+
• Health checks and failure handling
|
|
503
783
|
|
|
504
|
-
-
|
|
505
|
-
•
|
|
506
|
-
|
|
507
|
-
-
|
|
508
|
-
• ValidationUtils and IpUtils for configuration validation and IP management
|
|
784
|
+
- **Advanced Features**
|
|
785
|
+
• Custom header manipulation
|
|
786
|
+
• Template variables for dynamic values
|
|
787
|
+
• Priority-based route matching
|
|
509
788
|
|
|
510
789
|
## Certificate Hooks & Events
|
|
511
790
|
|
|
@@ -520,176 +799,171 @@ Provide a `certProvisionFunction(domain)` in SmartProxy settings to supply stati
|
|
|
520
799
|
|
|
521
800
|
## SmartProxy: Common Use Cases
|
|
522
801
|
|
|
523
|
-
The SmartProxy component offers a clean, unified approach to handle virtually any proxy scenario.
|
|
802
|
+
The SmartProxy component with route-based configuration offers a clean, unified approach to handle virtually any proxy scenario.
|
|
524
803
|
|
|
525
804
|
### 1. API Gateway / Backend Routing
|
|
526
805
|
|
|
527
|
-
Create a flexible API gateway to route traffic to different microservices based on domain:
|
|
806
|
+
Create a flexible API gateway to route traffic to different microservices based on domain and path:
|
|
528
807
|
|
|
529
808
|
```typescript
|
|
530
|
-
import { SmartProxy,
|
|
809
|
+
import { SmartProxy, createHttpsRoute } from '@push.rocks/smartproxy';
|
|
531
810
|
|
|
532
811
|
const apiGateway = new SmartProxy({
|
|
533
|
-
|
|
534
|
-
domainConfigs: [
|
|
812
|
+
routes: [
|
|
535
813
|
// Users API
|
|
536
|
-
|
|
814
|
+
createHttpsRoute({
|
|
815
|
+
ports: 443,
|
|
816
|
+
domains: 'api.example.com',
|
|
817
|
+
path: '/users/*',
|
|
537
818
|
target: { host: 'users-service', port: 3000 },
|
|
538
|
-
|
|
539
|
-
})
|
|
819
|
+
certificate: 'auto'
|
|
820
|
+
}),
|
|
540
821
|
|
|
541
822
|
// Products API
|
|
542
|
-
|
|
823
|
+
createHttpsRoute({
|
|
824
|
+
ports: 443,
|
|
825
|
+
domains: 'api.example.com',
|
|
826
|
+
path: '/products/*',
|
|
543
827
|
target: { host: 'products-service', port: 3001 },
|
|
544
|
-
|
|
545
|
-
})
|
|
828
|
+
certificate: 'auto'
|
|
829
|
+
}),
|
|
546
830
|
|
|
547
|
-
// Admin dashboard
|
|
548
|
-
|
|
831
|
+
// Admin dashboard with extra security
|
|
832
|
+
createHttpsRoute({
|
|
833
|
+
ports: 443,
|
|
834
|
+
domains: 'admin.example.com',
|
|
549
835
|
target: { host: 'admin-dashboard', port: 8080 },
|
|
836
|
+
certificate: 'auto',
|
|
550
837
|
security: {
|
|
551
838
|
allowedIps: ['10.0.0.*', '192.168.1.*'] // Only allow internal network
|
|
552
839
|
}
|
|
553
|
-
})
|
|
554
|
-
],
|
|
555
|
-
sniEnabled: true
|
|
556
|
-
});
|
|
557
|
-
|
|
558
|
-
await apiGateway.start();
|
|
559
|
-
```
|
|
560
|
-
|
|
561
|
-
### 2. Automatic HTTPS for Development
|
|
562
|
-
|
|
563
|
-
Easily add HTTPS to your local development environment with automatic certificates:
|
|
564
|
-
|
|
565
|
-
```typescript
|
|
566
|
-
import { SmartProxy, createDomainConfig, tlsTerminateToHttp } from '@push.rocks/smartproxy';
|
|
567
|
-
|
|
568
|
-
const devProxy = new SmartProxy({
|
|
569
|
-
fromPort: 443,
|
|
570
|
-
domainConfigs: [
|
|
571
|
-
createDomainConfig('dev.local', tlsTerminateToHttp({
|
|
572
|
-
target: { host: 'localhost', port: 3000 },
|
|
573
|
-
// For development, use self-signed or existing certificates
|
|
574
|
-
https: {
|
|
575
|
-
customCert: {
|
|
576
|
-
key: fs.readFileSync('dev-cert.key', 'utf8'),
|
|
577
|
-
cert: fs.readFileSync('dev-cert.pem', 'utf8')
|
|
578
|
-
}
|
|
579
|
-
},
|
|
580
|
-
// Auto-redirect HTTP to HTTPS
|
|
581
|
-
http: {
|
|
582
|
-
enabled: true,
|
|
583
|
-
redirectToHttps: true
|
|
584
|
-
}
|
|
585
|
-
}))
|
|
840
|
+
})
|
|
586
841
|
]
|
|
587
842
|
});
|
|
588
843
|
|
|
589
|
-
await
|
|
844
|
+
await apiGateway.start();
|
|
590
845
|
```
|
|
591
846
|
|
|
592
|
-
###
|
|
847
|
+
### 2. Complete HTTPS Server with HTTP Redirect
|
|
593
848
|
|
|
594
|
-
|
|
849
|
+
Easily set up a secure HTTPS server with automatic redirection from HTTP:
|
|
595
850
|
|
|
596
851
|
```typescript
|
|
597
|
-
import { SmartProxy,
|
|
852
|
+
import { SmartProxy, createHttpsServer } from '@push.rocks/smartproxy';
|
|
598
853
|
|
|
599
|
-
const
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
'10.0.0.12'
|
|
609
|
-
],
|
|
610
|
-
port: 8080
|
|
611
|
-
},
|
|
612
|
-
acme: { enabled: true, production: true }
|
|
613
|
-
}))
|
|
854
|
+
const webServer = new SmartProxy({
|
|
855
|
+
routes: [
|
|
856
|
+
// createHttpsServer creates both the HTTPS route and HTTP redirect
|
|
857
|
+
...createHttpsServer({
|
|
858
|
+
domains: 'example.com',
|
|
859
|
+
target: { host: 'localhost', port: 8080 },
|
|
860
|
+
certificate: 'auto',
|
|
861
|
+
addHttpRedirect: true
|
|
862
|
+
})
|
|
614
863
|
]
|
|
615
864
|
});
|
|
616
865
|
|
|
617
|
-
await
|
|
866
|
+
await webServer.start();
|
|
618
867
|
```
|
|
619
868
|
|
|
620
|
-
###
|
|
869
|
+
### 3. Multi-Tenant Application with Wildcard Domains
|
|
621
870
|
|
|
622
|
-
Support
|
|
871
|
+
Support dynamically created tenants with wildcard domain matching:
|
|
623
872
|
|
|
624
873
|
```typescript
|
|
625
|
-
import { SmartProxy,
|
|
626
|
-
|
|
627
|
-
const
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
874
|
+
import { SmartProxy, createHttpsRoute, createHttpToHttpsRedirect } from '@push.rocks/smartproxy';
|
|
875
|
+
|
|
876
|
+
const multiTenantApp = new SmartProxy({
|
|
877
|
+
routes: [
|
|
878
|
+
// Handle all tenant subdomains with one route
|
|
879
|
+
createHttpsRoute({
|
|
880
|
+
ports: 443,
|
|
881
|
+
domains: '*.example.com',
|
|
632
882
|
target: { host: 'tenant-router', port: 8080 },
|
|
633
|
-
|
|
883
|
+
certificate: 'auto',
|
|
634
884
|
// Pass original hostname to backend for tenant identification
|
|
635
885
|
advanced: {
|
|
636
886
|
headers: {
|
|
637
887
|
'X-Original-Host': '{sni}'
|
|
638
888
|
}
|
|
639
889
|
}
|
|
640
|
-
})
|
|
641
|
-
|
|
642
|
-
|
|
890
|
+
}),
|
|
891
|
+
|
|
892
|
+
// Redirect HTTP to HTTPS for all subdomains
|
|
893
|
+
createHttpToHttpsRedirect({
|
|
894
|
+
domains: ['*.example.com']
|
|
895
|
+
})
|
|
896
|
+
]
|
|
643
897
|
});
|
|
644
898
|
|
|
645
|
-
await
|
|
899
|
+
await multiTenantApp.start();
|
|
646
900
|
```
|
|
647
901
|
|
|
648
|
-
###
|
|
902
|
+
### 4. Complex Multi-Service Infrastructure
|
|
649
903
|
|
|
650
|
-
Create a
|
|
904
|
+
Create a comprehensive proxy solution with multiple services and security controls:
|
|
651
905
|
|
|
652
906
|
```typescript
|
|
653
|
-
import {
|
|
907
|
+
import {
|
|
908
|
+
SmartProxy,
|
|
909
|
+
createHttpsRoute,
|
|
910
|
+
createPassthroughRoute,
|
|
911
|
+
createBlockRoute,
|
|
912
|
+
createHttpToHttpsRedirect
|
|
913
|
+
} from '@push.rocks/smartproxy';
|
|
654
914
|
|
|
655
915
|
const enterpriseProxy = new SmartProxy({
|
|
656
|
-
|
|
657
|
-
domainConfigs: [
|
|
916
|
+
routes: [
|
|
658
917
|
// Web application with automatic HTTPS
|
|
659
|
-
|
|
918
|
+
createHttpsRoute({
|
|
919
|
+
ports: 443,
|
|
920
|
+
domains: 'app.example.com',
|
|
660
921
|
target: { host: 'web-app', port: 8080 },
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
})),
|
|
922
|
+
certificate: 'auto'
|
|
923
|
+
}),
|
|
664
924
|
|
|
665
925
|
// Legacy system that needs HTTPS passthrough
|
|
666
|
-
|
|
926
|
+
createPassthroughRoute({
|
|
927
|
+
ports: 443,
|
|
928
|
+
domains: 'legacy.example.com',
|
|
667
929
|
target: { host: 'legacy-server', port: 443 }
|
|
668
|
-
})
|
|
930
|
+
}),
|
|
669
931
|
|
|
670
932
|
// Internal APIs with IP restrictions
|
|
671
|
-
|
|
933
|
+
createHttpsRoute({
|
|
934
|
+
ports: 443,
|
|
935
|
+
domains: 'api.internal.example.com',
|
|
672
936
|
target: { host: 'api-gateway', port: 3000 },
|
|
937
|
+
certificate: 'auto',
|
|
673
938
|
security: {
|
|
674
939
|
allowedIps: ['10.0.0.0/16', '192.168.0.0/16'],
|
|
675
940
|
maxConnections: 500
|
|
676
941
|
}
|
|
677
|
-
})
|
|
678
|
-
|
|
679
|
-
//
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
942
|
+
}),
|
|
943
|
+
|
|
944
|
+
// Block known malicious IPs
|
|
945
|
+
createBlockRoute({
|
|
946
|
+
ports: [80, 443],
|
|
947
|
+
clientIp: ['1.2.3.*', '5.6.7.*'],
|
|
948
|
+
priority: 1000
|
|
949
|
+
}),
|
|
950
|
+
|
|
951
|
+
// Redirect all HTTP to HTTPS
|
|
952
|
+
createHttpToHttpsRedirect({
|
|
953
|
+
domains: ['*.example.com', 'example.com']
|
|
954
|
+
})
|
|
689
955
|
],
|
|
690
|
-
|
|
956
|
+
|
|
957
|
+
// Global settings that apply to all routes
|
|
958
|
+
defaults: {
|
|
959
|
+
security: {
|
|
960
|
+
maxConnections: 1000
|
|
961
|
+
}
|
|
962
|
+
},
|
|
963
|
+
|
|
691
964
|
// Enable connection timeouts for security
|
|
692
965
|
inactivityTimeout: 30000,
|
|
966
|
+
|
|
693
967
|
// Using global certificate management
|
|
694
968
|
acme: {
|
|
695
969
|
enabled: true,
|
|
@@ -702,116 +976,86 @@ const enterpriseProxy = new SmartProxy({
|
|
|
702
976
|
await enterpriseProxy.start();
|
|
703
977
|
```
|
|
704
978
|
|
|
705
|
-
##
|
|
979
|
+
## Route-Based Configuration Details
|
|
706
980
|
|
|
707
|
-
|
|
981
|
+
### Match Criteria Options
|
|
708
982
|
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
3. **HTTPS Termination to HTTP (`https-terminate-to-http`)**: Terminates TLS and forwards the decrypted traffic to an HTTP backend.
|
|
712
|
-
4. **HTTPS Termination to HTTPS (`https-terminate-to-https`)**: Terminates TLS and creates a new TLS connection to an HTTPS backend.
|
|
983
|
+
- **ports**: `number | number[] | Array<{ from: number; to: number }>` (required)
|
|
984
|
+
Listen on specific ports or port ranges
|
|
713
985
|
|
|
714
|
-
|
|
986
|
+
- **domains**: `string | string[]` (optional)
|
|
987
|
+
Match specific domain names, supports wildcards (e.g., `*.example.com`)
|
|
715
988
|
|
|
716
|
-
|
|
989
|
+
- **path**: `string` (optional)
|
|
990
|
+
Match specific URL paths, supports glob patterns
|
|
717
991
|
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
domains: ['example.com'], // Single domain or array of domains (with wildcard support)
|
|
721
|
-
forwarding: {
|
|
722
|
-
type: 'http-only', // One of the four forwarding types
|
|
723
|
-
target: {
|
|
724
|
-
host: 'localhost', // Backend server (string or array for load balancing)
|
|
725
|
-
port: 3000 // Backend port
|
|
726
|
-
}
|
|
727
|
-
// Additional options as needed
|
|
728
|
-
}
|
|
729
|
-
}
|
|
730
|
-
```
|
|
992
|
+
- **clientIp**: `string[]` (optional)
|
|
993
|
+
Match client IP addresses, supports glob patterns
|
|
731
994
|
|
|
732
|
-
|
|
995
|
+
- **tlsVersion**: `string[]` (optional)
|
|
996
|
+
Match specific TLS versions (e.g., `TLSv1.2`, `TLSv1.3`)
|
|
733
997
|
|
|
734
|
-
|
|
998
|
+
### Action Types
|
|
735
999
|
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
}
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
// - httpsPassthrough() - For SNI-based passthrough
|
|
745
|
-
// - tlsTerminateToHttp() - For HTTPS termination to HTTP
|
|
746
|
-
// - tlsTerminateToHttps() - For HTTPS termination to HTTPS
|
|
747
|
-
```
|
|
1000
|
+
1. **Forward**:
|
|
1001
|
+
```typescript
|
|
1002
|
+
{
|
|
1003
|
+
type: 'forward',
|
|
1004
|
+
target: { host: 'localhost', port: 8080 },
|
|
1005
|
+
tls: { mode: 'terminate', certificate: 'auto' }
|
|
1006
|
+
}
|
|
1007
|
+
```
|
|
748
1008
|
|
|
749
|
-
|
|
1009
|
+
2. **Redirect**:
|
|
1010
|
+
```typescript
|
|
1011
|
+
{
|
|
1012
|
+
type: 'redirect',
|
|
1013
|
+
redirect: { to: 'https://{domain}{path}', status: 301 }
|
|
1014
|
+
}
|
|
1015
|
+
```
|
|
750
1016
|
|
|
751
|
-
|
|
1017
|
+
3. **Block**:
|
|
1018
|
+
```typescript
|
|
1019
|
+
{
|
|
1020
|
+
type: 'block'
|
|
1021
|
+
}
|
|
1022
|
+
```
|
|
752
1023
|
|
|
753
|
-
|
|
754
|
-
createDomainConfig('api.example.com', tlsTerminateToHttps({
|
|
755
|
-
// Target configuration with load balancing
|
|
756
|
-
target: {
|
|
757
|
-
host: ['10.0.0.10', '10.0.0.11'], // Round-robin load balancing
|
|
758
|
-
port: 8443
|
|
759
|
-
},
|
|
1024
|
+
### TLS Modes
|
|
760
1025
|
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
redirectToHttps: true // Automatically redirect to HTTPS
|
|
765
|
-
},
|
|
1026
|
+
- **passthrough**: Forward raw TLS traffic without decryption
|
|
1027
|
+
- **terminate**: Terminate TLS and forward as HTTP
|
|
1028
|
+
- **terminate-and-reencrypt**: Terminate TLS and create a new TLS connection to the backend
|
|
766
1029
|
|
|
767
|
-
|
|
768
|
-
https: {
|
|
769
|
-
customCert: { // Provide your own certificate
|
|
770
|
-
key: '-----BEGIN PRIVATE KEY-----\n...',
|
|
771
|
-
cert: '-----BEGIN CERTIFICATE-----\n...'
|
|
772
|
-
},
|
|
773
|
-
forwardSni: true // Forward original SNI to backend
|
|
774
|
-
},
|
|
1030
|
+
### Template Variables
|
|
775
1031
|
|
|
776
|
-
|
|
777
|
-
acme: {
|
|
778
|
-
enabled: true, // Enable automatic certificates
|
|
779
|
-
production: true, // Use production Let's Encrypt
|
|
780
|
-
maintenance: true // Auto-renew certificates
|
|
781
|
-
},
|
|
1032
|
+
Template variables can be used in string values:
|
|
782
1033
|
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
1034
|
+
- `{domain}`: The requested domain name
|
|
1035
|
+
- `{port}`: The incoming port number
|
|
1036
|
+
- `{path}`: The requested URL path
|
|
1037
|
+
- `{query}`: The query string
|
|
1038
|
+
- `{clientIp}`: The client's IP address
|
|
1039
|
+
- `{sni}`: The SNI hostname
|
|
789
1040
|
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
},
|
|
797
|
-
keepAlive: true // Keep connections alive
|
|
798
|
-
}
|
|
799
|
-
}))
|
|
1041
|
+
Example:
|
|
1042
|
+
```typescript
|
|
1043
|
+
createRedirectRoute({
|
|
1044
|
+
domains: 'old.example.com',
|
|
1045
|
+
redirectTo: 'https://new.example.com{path}?source=redirect'
|
|
1046
|
+
})
|
|
800
1047
|
```
|
|
801
1048
|
|
|
802
|
-
### Extended Configuration Options
|
|
803
|
-
|
|
804
|
-
#### IForwardConfig
|
|
805
|
-
- `type`: 'http-only' | 'https-passthrough' | 'https-terminate-to-http' | 'https-terminate-to-https'
|
|
806
|
-
- `target`: { host: string | string[], port: number }
|
|
807
|
-
- `http?`: { enabled?: boolean, redirectToHttps?: boolean, headers?: Record<string, string> }
|
|
808
|
-
- `https?`: { customCert?: { key: string, cert: string }, forwardSni?: boolean }
|
|
809
|
-
- `acme?`: { enabled?: boolean, maintenance?: boolean, production?: boolean, forwardChallenges?: { host: string, port: number, useTls?: boolean } }
|
|
810
|
-
- `security?`: { allowedIps?: string[], blockedIps?: string[], maxConnections?: number }
|
|
811
|
-
- `advanced?`: { portRanges?: Array<{ from: number, to: number }>, networkProxyPort?: number, keepAlive?: boolean, timeout?: number, headers?: Record<string, string> }
|
|
812
|
-
|
|
813
1049
|
## Configuration Options
|
|
814
1050
|
|
|
1051
|
+
### SmartProxy (IRoutedSmartProxyOptions)
|
|
1052
|
+
- `routes` (IRouteConfig[], required) - Array of route configurations
|
|
1053
|
+
- `defaults` (object) - Default settings for all routes
|
|
1054
|
+
- `acme` (IAcmeOptions) - ACME certificate options
|
|
1055
|
+
- Connection timeouts: `initialDataTimeout`, `socketTimeout`, `inactivityTimeout`, etc.
|
|
1056
|
+
- Socket opts: `noDelay`, `keepAlive`, `enableKeepAliveProbes`
|
|
1057
|
+
- `certProvisionFunction` (callback) - Custom certificate provisioning
|
|
1058
|
+
|
|
815
1059
|
### NetworkProxy (INetworkProxyOptions)
|
|
816
1060
|
- `port` (number, required)
|
|
817
1061
|
- `backendProtocol` ('http1'|'http2', default 'http1')
|
|
@@ -844,25 +1088,22 @@ createDomainConfig('api.example.com', tlsTerminateToHttps({
|
|
|
844
1088
|
- `useIPSets` (boolean, default true)
|
|
845
1089
|
- `qos`, `netProxyIntegration` (objects)
|
|
846
1090
|
|
|
847
|
-
### Redirect / SslRedirect
|
|
848
|
-
- Constructor options: `httpPort`, `httpsPort`, `sslOptions`, `rules` (IRedirectRule[])
|
|
849
|
-
|
|
850
|
-
### SmartProxy (ISmartProxyOptions)
|
|
851
|
-
- `fromPort`, `toPort` (number)
|
|
852
|
-
- `domainConfigs` (IDomainConfig[]) - Using unified forwarding configuration
|
|
853
|
-
- `sniEnabled`, `preserveSourceIP` (booleans)
|
|
854
|
-
- `defaultAllowedIPs`, `defaultBlockedIPs` (string[]) - Default IP allowlists/blocklists
|
|
855
|
-
- Timeouts: `initialDataTimeout`, `socketTimeout`, `inactivityTimeout`, etc.
|
|
856
|
-
- Socket opts: `noDelay`, `keepAlive`, `enableKeepAliveProbes`
|
|
857
|
-
- `acme` (IAcmeOptions), `certProvisionFunction` (callback)
|
|
858
|
-
- `useNetworkProxy` (number[]), `networkProxyPort` (number)
|
|
859
|
-
- `globalPortRanges` (Array<{ from: number; to: number }>)
|
|
860
|
-
|
|
861
1091
|
## Troubleshooting
|
|
862
1092
|
|
|
1093
|
+
### SmartProxy
|
|
1094
|
+
- If routes aren't matching as expected, check their priorities
|
|
1095
|
+
- For domain matching issues, verify SNI extraction is working
|
|
1096
|
+
- Use higher priority for block routes to ensure they take precedence
|
|
1097
|
+
- Enable `enableDetailedLogging` or `enableTlsDebugLogging` for debugging
|
|
1098
|
+
|
|
1099
|
+
### TLS/Certificates
|
|
1100
|
+
- For certificate issues, check the ACME settings and domain validation
|
|
1101
|
+
- Ensure domains are publicly accessible for Let's Encrypt validation
|
|
1102
|
+
- For TLS handshake issues, increase `initialDataTimeout` and `maxPendingDataSize`
|
|
1103
|
+
|
|
863
1104
|
### NetworkProxy
|
|
864
1105
|
- Verify ports, certificates and `rejectUnauthorized` for TLS errors
|
|
865
|
-
- Configure CORS
|
|
1106
|
+
- Configure CORS for preflight issues
|
|
866
1107
|
- Increase `maxConnections` or `connectionPoolSize` under load
|
|
867
1108
|
|
|
868
1109
|
### Port80Handler
|
|
@@ -873,18 +1114,6 @@ createDomainConfig('api.example.com', tlsTerminateToHttps({
|
|
|
873
1114
|
- Ensure `nft` is installed and run with sufficient privileges
|
|
874
1115
|
- Use `forceCleanSlate:true` to clear conflicting rules
|
|
875
1116
|
|
|
876
|
-
### Redirect / SslRedirect
|
|
877
|
-
- Check `fromHost`/`fromPath` patterns and Host headers
|
|
878
|
-
- Validate `sslOptions` key/cert correctness
|
|
879
|
-
|
|
880
|
-
### SmartProxy & SniHandler
|
|
881
|
-
- Increase `initialDataTimeout`/`maxPendingDataSize` for large ClientHello
|
|
882
|
-
- Enable `enableTlsDebugLogging` to trace handshake
|
|
883
|
-
- Ensure `allowSessionTicket` and fragmentation support for resumption
|
|
884
|
-
- Double-check forwarding configuration to ensure correct `type` for your use case
|
|
885
|
-
- Use helper functions like `httpOnly()`, `httpsPassthrough()`, etc. to create correct configurations
|
|
886
|
-
- For IP filtering issues, check the `security.allowedIps` and `security.blockedIps` settings
|
|
887
|
-
|
|
888
1117
|
## License and Legal Information
|
|
889
1118
|
|
|
890
1119
|
This repository contains open-source code that is licensed under the MIT License. A copy of the MIT License can be found in the [license](license) file within this repository.
|