@push.rocks/smartproxy 19.6.16 → 20.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/core/utils/shared-security-manager.js +30 -5
- package/dist_ts/proxies/http-proxy/request-handler.d.ts +4 -0
- package/dist_ts/proxies/http-proxy/request-handler.js +104 -21
- package/dist_ts/proxies/http-proxy/websocket-handler.d.ts +4 -0
- package/dist_ts/proxies/http-proxy/websocket-handler.js +78 -8
- package/dist_ts/proxies/smart-proxy/certificate-manager.d.ts +17 -1
- package/dist_ts/proxies/smart-proxy/certificate-manager.js +84 -10
- package/dist_ts/proxies/smart-proxy/models/interfaces.d.ts +5 -0
- package/dist_ts/proxies/smart-proxy/models/route-types.d.ts +19 -2
- package/dist_ts/proxies/smart-proxy/models/route-types.js +1 -1
- package/dist_ts/proxies/smart-proxy/nftables-manager.js +14 -11
- package/dist_ts/proxies/smart-proxy/route-connection-handler.d.ts +4 -0
- package/dist_ts/proxies/smart-proxy/route-connection-handler.js +112 -28
- package/dist_ts/proxies/smart-proxy/smart-proxy.js +9 -1
- package/dist_ts/proxies/smart-proxy/utils/route-helpers.js +23 -23
- package/dist_ts/proxies/smart-proxy/utils/route-patterns.js +13 -13
- package/dist_ts/proxies/smart-proxy/utils/route-utils.js +4 -7
- package/dist_ts/proxies/smart-proxy/utils/route-validators.js +41 -25
- package/package.json +1 -1
- package/readme.hints.md +51 -1
- package/readme.md +105 -2
- package/readme.plan.md +154 -53
- package/ts/core/utils/shared-security-manager.ts +33 -4
- package/ts/proxies/http-proxy/request-handler.ts +124 -21
- package/ts/proxies/http-proxy/websocket-handler.ts +96 -8
- package/ts/proxies/smart-proxy/certificate-manager.ts +98 -13
- package/ts/proxies/smart-proxy/models/interfaces.ts +6 -0
- package/ts/proxies/smart-proxy/models/route-types.ts +34 -8
- package/ts/proxies/smart-proxy/nftables-manager.ts +14 -10
- package/ts/proxies/smart-proxy/route-connection-handler.ts +132 -28
- package/ts/proxies/smart-proxy/smart-proxy.ts +10 -0
- package/ts/proxies/smart-proxy/utils/route-helpers.ts +14 -14
- package/ts/proxies/smart-proxy/utils/route-patterns.ts +6 -6
- package/ts/proxies/smart-proxy/utils/route-utils.ts +3 -6
- package/ts/proxies/smart-proxy/utils/route-validators.ts +38 -21
|
@@ -94,32 +94,45 @@ export function validateRouteAction(action) {
|
|
|
94
94
|
else if (!['forward', 'socket-handler'].includes(action.type)) {
|
|
95
95
|
errors.push(`Invalid action type: ${action.type}`);
|
|
96
96
|
}
|
|
97
|
-
// Validate
|
|
97
|
+
// Validate targets for 'forward' action
|
|
98
98
|
if (action.type === 'forward') {
|
|
99
|
-
if (!action.
|
|
100
|
-
errors.push('
|
|
99
|
+
if (!action.targets || !Array.isArray(action.targets) || action.targets.length === 0) {
|
|
100
|
+
errors.push('Targets array is required for forward action');
|
|
101
101
|
}
|
|
102
102
|
else {
|
|
103
|
-
// Validate target
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
typeof
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
103
|
+
// Validate each target
|
|
104
|
+
action.targets.forEach((target, index) => {
|
|
105
|
+
// Validate target host
|
|
106
|
+
if (!target.host) {
|
|
107
|
+
errors.push(`Target[${index}] host is required`);
|
|
108
|
+
}
|
|
109
|
+
else if (typeof target.host !== 'string' &&
|
|
110
|
+
!Array.isArray(target.host) &&
|
|
111
|
+
typeof target.host !== 'function') {
|
|
112
|
+
errors.push(`Target[${index}] host must be a string, array of strings, or function`);
|
|
113
|
+
}
|
|
114
|
+
// Validate target port
|
|
115
|
+
if (target.port === undefined) {
|
|
116
|
+
errors.push(`Target[${index}] port is required`);
|
|
117
|
+
}
|
|
118
|
+
else if (typeof target.port !== 'number' &&
|
|
119
|
+
typeof target.port !== 'function' &&
|
|
120
|
+
target.port !== 'preserve') {
|
|
121
|
+
errors.push(`Target[${index}] port must be a number, 'preserve', or a function`);
|
|
122
|
+
}
|
|
123
|
+
else if (typeof target.port === 'number' && !isValidPort(target.port)) {
|
|
124
|
+
errors.push(`Target[${index}] port must be between 1 and 65535`);
|
|
125
|
+
}
|
|
126
|
+
// Validate match criteria if present
|
|
127
|
+
if (target.match) {
|
|
128
|
+
if (target.match.ports && !Array.isArray(target.match.ports)) {
|
|
129
|
+
errors.push(`Target[${index}] match.ports must be an array`);
|
|
130
|
+
}
|
|
131
|
+
if (target.match.method && !Array.isArray(target.match.method)) {
|
|
132
|
+
errors.push(`Target[${index}] match.method must be an array`);
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
});
|
|
123
136
|
}
|
|
124
137
|
// Validate TLS options for forward actions
|
|
125
138
|
if (action.tls) {
|
|
@@ -219,7 +232,10 @@ export function hasRequiredPropertiesForAction(route, actionType) {
|
|
|
219
232
|
}
|
|
220
233
|
switch (actionType) {
|
|
221
234
|
case 'forward':
|
|
222
|
-
return !!route.action.
|
|
235
|
+
return !!route.action.targets &&
|
|
236
|
+
Array.isArray(route.action.targets) &&
|
|
237
|
+
route.action.targets.length > 0 &&
|
|
238
|
+
route.action.targets.every(t => t.host && t.port !== undefined);
|
|
223
239
|
case 'socket-handler':
|
|
224
240
|
return !!route.action.socketHandler && typeof route.action.socketHandler === 'function';
|
|
225
241
|
default:
|
|
@@ -240,4 +256,4 @@ export function assertValidRoute(route) {
|
|
|
240
256
|
}
|
|
241
257
|
return route;
|
|
242
258
|
}
|
|
243
|
-
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicm91dGUtdmFsaWRhdG9ycy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL3RzL3Byb3hpZXMvc21hcnQtcHJveHkvdXRpbHMvcm91dGUtdmFsaWRhdG9ycy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTs7Ozs7R0FLRztBQUlIOzs7O0dBSUc7QUFDSCxNQUFNLFVBQVUsV0FBVyxDQUFDLElBQVM7SUFDbkMsSUFBSSxPQUFPLElBQUksS0FBSyxRQUFRLEVBQUUsQ0FBQztRQUM3QixPQUFPLElBQUksR0FBRyxDQUFDLElBQUksSUFBSSxHQUFHLEtBQUssQ0FBQyxDQUFDLDhCQUE4QjtJQUNqRSxDQUFDO1NBQU0sSUFBSSxLQUFLLENBQUMsT0FBTyxDQUFDLElBQUksQ0FBQyxFQUFFLENBQUM7UUFDL0IsT0FBTyxJQUFJLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQ3BCLENBQUMsT0FBTyxDQUFDLEtBQUssUUFBUSxJQUFJLENBQUMsR0FBRyxDQUFDLElBQUksQ0FBQyxHQUFHLEtBQUssQ0FBQztZQUM3QyxDQUFDLE9BQU8sQ0FBQyxLQUFLLFFBQVEsSUFBSSxNQUFNLElBQUksQ0FBQyxJQUFJLElBQUksSUFBSSxDQUFDO2dCQUNqRCxDQUFDLENBQUMsSUFBSSxHQUFHLENBQUMsSUFBSSxDQUFDLENBQUMsSUFBSSxHQUFHLEtBQUssSUFBSSxDQUFDLENBQUMsRUFBRSxHQUFHLENBQUMsSUFBSSxDQUFDLENBQUMsRUFBRSxHQUFHLEtBQUssQ0FBQyxDQUMzRCxDQUFDO0lBQ0osQ0FBQztTQUFNLElBQUksT0FBTyxJQUFJLEtBQUssVUFBVSxFQUFFLENBQUM7UUFDdEMsd0VBQXdFO1FBQ3hFLHdDQUF3QztRQUN4QyxPQUFPLElBQUksQ0FBQztJQUNkLENBQUM7U0FBTSxJQUFJLE9BQU8sSUFBSSxLQUFLLFFBQVEsSUFBSSxNQUFNLElBQUksSUFBSSxJQUFJLElBQUksSUFBSSxJQUFJLEVBQUUsQ0FBQztRQUN0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
|
|
259
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicm91dGUtdmFsaWRhdG9ycy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL3RzL3Byb3hpZXMvc21hcnQtcHJveHkvdXRpbHMvcm91dGUtdmFsaWRhdG9ycy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTs7Ozs7R0FLRztBQUlIOzs7O0dBSUc7QUFDSCxNQUFNLFVBQVUsV0FBVyxDQUFDLElBQVM7SUFDbkMsSUFBSSxPQUFPLElBQUksS0FBSyxRQUFRLEVBQUUsQ0FBQztRQUM3QixPQUFPLElBQUksR0FBRyxDQUFDLElBQUksSUFBSSxHQUFHLEtBQUssQ0FBQyxDQUFDLDhCQUE4QjtJQUNqRSxDQUFDO1NBQU0sSUFBSSxLQUFLLENBQUMsT0FBTyxDQUFDLElBQUksQ0FBQyxFQUFFLENBQUM7UUFDL0IsT0FBTyxJQUFJLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQ3BCLENBQUMsT0FBTyxDQUFDLEtBQUssUUFBUSxJQUFJLENBQUMsR0FBRyxDQUFDLElBQUksQ0FBQyxHQUFHLEtBQUssQ0FBQztZQUM3QyxDQUFDLE9BQU8sQ0FBQyxLQUFLLFFBQVEsSUFBSSxNQUFNLElBQUksQ0FBQyxJQUFJLElBQUksSUFBSSxDQUFDO2dCQUNqRCxDQUFDLENBQUMsSUFBSSxHQUFHLENBQUMsSUFBSSxDQUFDLENBQUMsSUFBSSxHQUFHLEtBQUssSUFBSSxDQUFDLENBQUMsRUFBRSxHQUFHLENBQUMsSUFBSSxDQUFDLENBQUMsRUFBRSxHQUFHLEtBQUssQ0FBQyxDQUMzRCxDQUFDO0lBQ0osQ0FBQztTQUFNLElBQUksT0FBTyxJQUFJLEtBQUssVUFBVSxFQUFFLENBQUM7UUFDdEMsd0VBQXdFO1FBQ3hFLHdDQUF3QztRQUN4QyxPQUFPLElBQUksQ0FBQztJQUNkLENBQUM7U0FBTSxJQUFJLE9BQU8sSUFBSSxLQUFLLFFBQVEsSUFBSSxNQUFNLElBQUksSUFBSSxJQUFJLElBQUksSUFBSSxJQUFJLEVBQUUsQ0FBQztRQUN0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
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@push.rocks/smartproxy",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "20.0.0",
|
|
4
4
|
"private": false,
|
|
5
5
|
"description": "A powerful proxy package with unified route-based configuration for high traffic management. Features include SSL/TLS support, flexible routing patterns, WebSocket handling, advanced security options, and automatic ACME certificate management.",
|
|
6
6
|
"main": "dist_ts/index.js",
|
package/readme.hints.md
CHANGED
|
@@ -295,4 +295,54 @@ You'll see:
|
|
|
295
295
|
- During attacks or high-volume scenarios, logs are flushed more frequently
|
|
296
296
|
- If 50+ events occur within 1 second, immediate flush is triggered
|
|
297
297
|
- Prevents memory buildup during flooding attacks
|
|
298
|
-
- Maintains real-time visibility during incidents
|
|
298
|
+
- Maintains real-time visibility during incidents
|
|
299
|
+
|
|
300
|
+
## Custom Certificate Provision Function
|
|
301
|
+
|
|
302
|
+
The `certProvisionFunction` feature has been implemented to allow users to provide their own certificate generation logic.
|
|
303
|
+
|
|
304
|
+
### Implementation Details
|
|
305
|
+
|
|
306
|
+
1. **Type Definition**: The function must return `Promise<TSmartProxyCertProvisionObject>` where:
|
|
307
|
+
- `TSmartProxyCertProvisionObject = plugins.tsclass.network.ICert | 'http01'`
|
|
308
|
+
- Return `'http01'` to fallback to Let's Encrypt
|
|
309
|
+
- Return a certificate object for custom certificates
|
|
310
|
+
|
|
311
|
+
2. **Certificate Manager Changes**:
|
|
312
|
+
- Added `certProvisionFunction` property to CertificateManager
|
|
313
|
+
- Modified `provisionAcmeCertificate()` to check custom function first
|
|
314
|
+
- Custom certificates are stored with source type 'custom'
|
|
315
|
+
- Expiry date extraction currently defaults to 90 days
|
|
316
|
+
|
|
317
|
+
3. **Configuration Options**:
|
|
318
|
+
- `certProvisionFunction`: The custom provision function
|
|
319
|
+
- `certProvisionFallbackToAcme`: Whether to fallback to ACME on error (default: true)
|
|
320
|
+
|
|
321
|
+
4. **Usage Example**:
|
|
322
|
+
```typescript
|
|
323
|
+
new SmartProxy({
|
|
324
|
+
certProvisionFunction: async (domain: string) => {
|
|
325
|
+
if (domain === 'internal.example.com') {
|
|
326
|
+
return {
|
|
327
|
+
cert: customCert,
|
|
328
|
+
key: customKey,
|
|
329
|
+
ca: customCA
|
|
330
|
+
} as unknown as TSmartProxyCertProvisionObject;
|
|
331
|
+
}
|
|
332
|
+
return 'http01'; // Use Let's Encrypt
|
|
333
|
+
},
|
|
334
|
+
certProvisionFallbackToAcme: true
|
|
335
|
+
})
|
|
336
|
+
```
|
|
337
|
+
|
|
338
|
+
5. **Testing Notes**:
|
|
339
|
+
- Type assertions through `unknown` are needed in tests due to strict interface typing
|
|
340
|
+
- Mock certificate objects work for testing but need proper type casting
|
|
341
|
+
- The actual certificate parsing for expiry dates would need a proper X.509 parser
|
|
342
|
+
|
|
343
|
+
### Future Improvements
|
|
344
|
+
|
|
345
|
+
1. Implement proper certificate expiry date extraction using X.509 parsing
|
|
346
|
+
2. Add support for returning expiry date with custom certificates
|
|
347
|
+
3. Consider adding validation for custom certificate format
|
|
348
|
+
4. Add events/hooks for certificate provisioning lifecycle
|
package/readme.md
CHANGED
|
@@ -2336,14 +2336,117 @@ sequenceDiagram
|
|
|
2336
2336
|
• Efficient SNI extraction
|
|
2337
2337
|
• Minimal overhead routing
|
|
2338
2338
|
|
|
2339
|
-
## Certificate
|
|
2339
|
+
## Certificate Management
|
|
2340
|
+
|
|
2341
|
+
### Custom Certificate Provision Function
|
|
2342
|
+
|
|
2343
|
+
SmartProxy supports a custom certificate provision function that allows you to provide your own certificate generation logic while maintaining compatibility with Let's Encrypt:
|
|
2344
|
+
|
|
2345
|
+
```typescript
|
|
2346
|
+
const proxy = new SmartProxy({
|
|
2347
|
+
certProvisionFunction: async (domain: string): Promise<TSmartProxyCertProvisionObject> => {
|
|
2348
|
+
// Option 1: Return a custom certificate
|
|
2349
|
+
if (domain === 'internal.example.com') {
|
|
2350
|
+
return {
|
|
2351
|
+
cert: customCertPEM,
|
|
2352
|
+
key: customKeyPEM,
|
|
2353
|
+
ca: customCAPEM // Optional CA chain
|
|
2354
|
+
};
|
|
2355
|
+
}
|
|
2356
|
+
|
|
2357
|
+
// Option 2: Fallback to Let's Encrypt
|
|
2358
|
+
return 'http01';
|
|
2359
|
+
},
|
|
2360
|
+
|
|
2361
|
+
// Control fallback behavior when custom provision fails
|
|
2362
|
+
certProvisionFallbackToAcme: true, // Default: true
|
|
2363
|
+
|
|
2364
|
+
routes: [...]
|
|
2365
|
+
});
|
|
2366
|
+
```
|
|
2367
|
+
|
|
2368
|
+
**Key Features:**
|
|
2369
|
+
- Called for any route with `certificate: 'auto'`
|
|
2370
|
+
- Return custom certificate object or `'http01'` to use Let's Encrypt
|
|
2371
|
+
- Participates in automatic renewal cycle (checked every 12 hours)
|
|
2372
|
+
- Custom certificates stored with source type 'custom' for tracking
|
|
2373
|
+
|
|
2374
|
+
**Configuration Options:**
|
|
2375
|
+
- `certProvisionFunction`: Async function that receives domain and returns certificate or 'http01'
|
|
2376
|
+
- `certProvisionFallbackToAcme`: Whether to fallback to Let's Encrypt if custom provision fails (default: true)
|
|
2377
|
+
|
|
2378
|
+
**Advanced Example with Certificate Manager:**
|
|
2379
|
+
|
|
2380
|
+
```typescript
|
|
2381
|
+
const certManager = new MyCertificateManager();
|
|
2382
|
+
|
|
2383
|
+
const proxy = new SmartProxy({
|
|
2384
|
+
certProvisionFunction: async (domain: string) => {
|
|
2385
|
+
try {
|
|
2386
|
+
// Check if we have a custom certificate for this domain
|
|
2387
|
+
if (await certManager.hasCustomCert(domain)) {
|
|
2388
|
+
const cert = await certManager.getCertificate(domain);
|
|
2389
|
+
return {
|
|
2390
|
+
cert: cert.certificate,
|
|
2391
|
+
key: cert.privateKey,
|
|
2392
|
+
ca: cert.chain
|
|
2393
|
+
};
|
|
2394
|
+
}
|
|
2395
|
+
|
|
2396
|
+
// Use Let's Encrypt for public domains
|
|
2397
|
+
if (domain.endsWith('.example.com')) {
|
|
2398
|
+
return 'http01';
|
|
2399
|
+
}
|
|
2400
|
+
|
|
2401
|
+
// Generate self-signed for internal domains
|
|
2402
|
+
if (domain.endsWith('.internal')) {
|
|
2403
|
+
const selfSigned = await certManager.generateSelfSigned(domain);
|
|
2404
|
+
return {
|
|
2405
|
+
cert: selfSigned.cert,
|
|
2406
|
+
key: selfSigned.key,
|
|
2407
|
+
ca: ''
|
|
2408
|
+
};
|
|
2409
|
+
}
|
|
2410
|
+
|
|
2411
|
+
// Default to Let's Encrypt
|
|
2412
|
+
return 'http01';
|
|
2413
|
+
} catch (error) {
|
|
2414
|
+
console.error(`Certificate provision failed for ${domain}:`, error);
|
|
2415
|
+
// Will fallback to Let's Encrypt if certProvisionFallbackToAcme is true
|
|
2416
|
+
throw error;
|
|
2417
|
+
}
|
|
2418
|
+
},
|
|
2419
|
+
|
|
2420
|
+
certProvisionFallbackToAcme: true,
|
|
2421
|
+
|
|
2422
|
+
routes: [
|
|
2423
|
+
// Routes that use automatic certificates
|
|
2424
|
+
{
|
|
2425
|
+
match: { ports: 443, domains: ['app.example.com', '*.internal'] },
|
|
2426
|
+
action: {
|
|
2427
|
+
type: 'forward',
|
|
2428
|
+
target: { host: 'localhost', port: 8080 },
|
|
2429
|
+
tls: { mode: 'terminate', certificate: 'auto' }
|
|
2430
|
+
}
|
|
2431
|
+
}
|
|
2432
|
+
]
|
|
2433
|
+
});
|
|
2434
|
+
```
|
|
2435
|
+
|
|
2436
|
+
### Certificate Events
|
|
2340
2437
|
|
|
2341
2438
|
Listen for certificate events via EventEmitter:
|
|
2342
2439
|
- **SmartProxy**:
|
|
2343
2440
|
- `certificate` (domain, publicKey, privateKey, expiryDate, source, isRenewal)
|
|
2344
2441
|
- Events from CertManager are propagated
|
|
2345
2442
|
|
|
2346
|
-
|
|
2443
|
+
```typescript
|
|
2444
|
+
proxy.on('certificate', (domain, cert, key, expiryDate, source, isRenewal) => {
|
|
2445
|
+
console.log(`Certificate ${isRenewal ? 'renewed' : 'provisioned'} for ${domain}`);
|
|
2446
|
+
console.log(`Source: ${source}`); // 'acme', 'static', or 'custom'
|
|
2447
|
+
console.log(`Expires: ${expiryDate}`);
|
|
2448
|
+
});
|
|
2449
|
+
```
|
|
2347
2450
|
|
|
2348
2451
|
## SmartProxy: Common Use Cases
|
|
2349
2452
|
|
package/readme.plan.md
CHANGED
|
@@ -1,53 +1,154 @@
|
|
|
1
|
-
# SmartProxy
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
-
|
|
16
|
-
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
- [x] Update
|
|
22
|
-
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
- [x]
|
|
26
|
-
- [x]
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
- [x]
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
- [x]
|
|
38
|
-
- [x]
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
- [x]
|
|
44
|
-
- [
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
-
|
|
50
|
-
-
|
|
51
|
-
-
|
|
52
|
-
|
|
53
|
-
|
|
1
|
+
# SmartProxy Enhanced Routing Plan
|
|
2
|
+
|
|
3
|
+
## Goal
|
|
4
|
+
Implement enhanced routing structure with multiple targets per route, sub-matching capabilities, and target-specific overrides to enable more elegant and DRY configurations.
|
|
5
|
+
|
|
6
|
+
## Key Changes
|
|
7
|
+
|
|
8
|
+
### 1. Update Route Target Interface
|
|
9
|
+
- Add `match` property to `IRouteTarget` for sub-matching within routes
|
|
10
|
+
- Add target-specific override properties (tls, websocket, loadBalancing, etc.)
|
|
11
|
+
- Add priority field for controlling match order
|
|
12
|
+
|
|
13
|
+
### 2. Update Route Action Interface
|
|
14
|
+
- Remove singular `target` property
|
|
15
|
+
- Use only `targets` array (single target = array with one element)
|
|
16
|
+
- Maintain backwards compatibility during migration
|
|
17
|
+
|
|
18
|
+
### 3. Implementation Steps
|
|
19
|
+
|
|
20
|
+
#### Phase 1: Type Updates
|
|
21
|
+
- [x] Update `IRouteTarget` interface in `route-types.ts`
|
|
22
|
+
- Add `match?: ITargetMatch` property
|
|
23
|
+
- Add override properties (tls, websocket, etc.)
|
|
24
|
+
- Add `priority?: number` field
|
|
25
|
+
- [x] Create `ITargetMatch` interface for sub-matching criteria
|
|
26
|
+
- [x] Update `IRouteAction` to use only `targets: IRouteTarget[]`
|
|
27
|
+
|
|
28
|
+
#### Phase 2: Route Resolution Logic
|
|
29
|
+
- [x] Update route matching logic to handle multiple targets
|
|
30
|
+
- [x] Implement target sub-matching algorithm:
|
|
31
|
+
1. Sort targets by priority (highest first)
|
|
32
|
+
2. For each target with a match property, check if request matches
|
|
33
|
+
3. Use first matching target, or fallback to target without match
|
|
34
|
+
- [x] Ensure target-specific settings override route-level settings
|
|
35
|
+
|
|
36
|
+
#### Phase 3: Code Migration
|
|
37
|
+
- [x] Find all occurrences of `action.target` and update to use `action.targets`
|
|
38
|
+
- [x] Update route helpers and utilities
|
|
39
|
+
- [x] Update certificate manager to handle multiple targets
|
|
40
|
+
- [x] Update connection handlers
|
|
41
|
+
|
|
42
|
+
#### Phase 4: Testing
|
|
43
|
+
- [x] Update existing tests to use new format
|
|
44
|
+
- [ ] Add tests for multi-target scenarios
|
|
45
|
+
- [ ] Add tests for sub-matching logic
|
|
46
|
+
- [ ] Add tests for setting overrides
|
|
47
|
+
|
|
48
|
+
#### Phase 5: Documentation
|
|
49
|
+
- [ ] Update type documentation
|
|
50
|
+
- [ ] Add examples of new routing patterns
|
|
51
|
+
- [ ] Document migration path for existing configs
|
|
52
|
+
|
|
53
|
+
## Example Configurations
|
|
54
|
+
|
|
55
|
+
### Before (Current)
|
|
56
|
+
```typescript
|
|
57
|
+
// Need separate routes for different ports/paths
|
|
58
|
+
[
|
|
59
|
+
{
|
|
60
|
+
match: { domains: ['api.example.com'], ports: [80] },
|
|
61
|
+
action: {
|
|
62
|
+
type: 'forward',
|
|
63
|
+
target: { host: 'backend', port: 8080 },
|
|
64
|
+
tls: { mode: 'terminate' }
|
|
65
|
+
}
|
|
66
|
+
},
|
|
67
|
+
{
|
|
68
|
+
match: { domains: ['api.example.com'], ports: [443] },
|
|
69
|
+
action: {
|
|
70
|
+
type: 'forward',
|
|
71
|
+
target: { host: 'backend', port: 8081 },
|
|
72
|
+
tls: { mode: 'passthrough' }
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
]
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
### After (Enhanced)
|
|
79
|
+
```typescript
|
|
80
|
+
// Single route with multiple targets
|
|
81
|
+
{
|
|
82
|
+
match: { domains: ['api.example.com'], ports: [80, 443] },
|
|
83
|
+
action: {
|
|
84
|
+
type: 'forward',
|
|
85
|
+
targets: [
|
|
86
|
+
{
|
|
87
|
+
match: { ports: [80] },
|
|
88
|
+
host: 'backend',
|
|
89
|
+
port: 8080,
|
|
90
|
+
tls: { mode: 'terminate' }
|
|
91
|
+
},
|
|
92
|
+
{
|
|
93
|
+
match: { ports: [443] },
|
|
94
|
+
host: 'backend',
|
|
95
|
+
port: 8081,
|
|
96
|
+
tls: { mode: 'passthrough' }
|
|
97
|
+
}
|
|
98
|
+
]
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
### Advanced Example
|
|
104
|
+
```typescript
|
|
105
|
+
{
|
|
106
|
+
match: { domains: ['app.example.com'], ports: [443] },
|
|
107
|
+
action: {
|
|
108
|
+
type: 'forward',
|
|
109
|
+
tls: { mode: 'terminate', certificate: 'auto' }, // Route-level default
|
|
110
|
+
websocket: { enabled: true }, // Route-level default
|
|
111
|
+
targets: [
|
|
112
|
+
{
|
|
113
|
+
match: { path: '/api/v2/*' },
|
|
114
|
+
host: 'api-v2',
|
|
115
|
+
port: 8082,
|
|
116
|
+
priority: 10
|
|
117
|
+
},
|
|
118
|
+
{
|
|
119
|
+
match: { path: '/api/*', headers: { 'X-Version': 'v1' } },
|
|
120
|
+
host: 'api-v1',
|
|
121
|
+
port: 8081,
|
|
122
|
+
priority: 5
|
|
123
|
+
},
|
|
124
|
+
{
|
|
125
|
+
match: { path: '/ws/*' },
|
|
126
|
+
host: 'websocket-server',
|
|
127
|
+
port: 8090,
|
|
128
|
+
websocket: {
|
|
129
|
+
enabled: true,
|
|
130
|
+
rewritePath: '/' // Strip /ws prefix
|
|
131
|
+
}
|
|
132
|
+
},
|
|
133
|
+
{
|
|
134
|
+
// Default target (no match property)
|
|
135
|
+
host: 'web-backend',
|
|
136
|
+
port: 8080
|
|
137
|
+
}
|
|
138
|
+
]
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
## Benefits
|
|
144
|
+
1. **DRY Configuration**: No need to duplicate common settings across routes
|
|
145
|
+
2. **Flexibility**: Different backends for different ports/paths within same domain
|
|
146
|
+
3. **Clarity**: All routing for a domain in one place
|
|
147
|
+
4. **Performance**: Single route lookup instead of multiple
|
|
148
|
+
5. **Backwards Compatible**: Can migrate gradually
|
|
149
|
+
|
|
150
|
+
## Migration Strategy
|
|
151
|
+
1. Keep support for `target` temporarily with deprecation warning
|
|
152
|
+
2. Auto-convert `target` to `targets: [target]` internally
|
|
153
|
+
3. Update documentation with migration examples
|
|
154
|
+
4. Remove `target` support in next major version
|
|
@@ -13,7 +13,8 @@ import {
|
|
|
13
13
|
trackConnection,
|
|
14
14
|
removeConnection,
|
|
15
15
|
cleanupExpiredRateLimits,
|
|
16
|
-
parseBasicAuthHeader
|
|
16
|
+
parseBasicAuthHeader,
|
|
17
|
+
normalizeIP
|
|
17
18
|
} from './security-utils.js';
|
|
18
19
|
|
|
19
20
|
/**
|
|
@@ -78,7 +79,15 @@ export class SharedSecurityManager {
|
|
|
78
79
|
* @returns Number of connections from this IP
|
|
79
80
|
*/
|
|
80
81
|
public getConnectionCountByIP(ip: string): number {
|
|
81
|
-
|
|
82
|
+
// Check all normalized variants of the IP
|
|
83
|
+
const variants = normalizeIP(ip);
|
|
84
|
+
for (const variant of variants) {
|
|
85
|
+
const info = this.connectionsByIP.get(variant);
|
|
86
|
+
if (info) {
|
|
87
|
+
return info.connections.size;
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
return 0;
|
|
82
91
|
}
|
|
83
92
|
|
|
84
93
|
/**
|
|
@@ -88,7 +97,19 @@ export class SharedSecurityManager {
|
|
|
88
97
|
* @param connectionId - The connection ID to associate
|
|
89
98
|
*/
|
|
90
99
|
public trackConnectionByIP(ip: string, connectionId: string): void {
|
|
91
|
-
|
|
100
|
+
// Check if any variant already exists
|
|
101
|
+
const variants = normalizeIP(ip);
|
|
102
|
+
let existingKey: string | null = null;
|
|
103
|
+
|
|
104
|
+
for (const variant of variants) {
|
|
105
|
+
if (this.connectionsByIP.has(variant)) {
|
|
106
|
+
existingKey = variant;
|
|
107
|
+
break;
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
// Use existing key or the original IP
|
|
112
|
+
trackConnection(existingKey || ip, connectionId, this.connectionsByIP);
|
|
92
113
|
}
|
|
93
114
|
|
|
94
115
|
/**
|
|
@@ -98,7 +119,15 @@ export class SharedSecurityManager {
|
|
|
98
119
|
* @param connectionId - The connection ID to remove
|
|
99
120
|
*/
|
|
100
121
|
public removeConnectionByIP(ip: string, connectionId: string): void {
|
|
101
|
-
|
|
122
|
+
// Check all variants to find where the connection is tracked
|
|
123
|
+
const variants = normalizeIP(ip);
|
|
124
|
+
|
|
125
|
+
for (const variant of variants) {
|
|
126
|
+
if (this.connectionsByIP.has(variant)) {
|
|
127
|
+
removeConnection(variant, connectionId, this.connectionsByIP);
|
|
128
|
+
break;
|
|
129
|
+
}
|
|
130
|
+
}
|
|
102
131
|
}
|
|
103
132
|
|
|
104
133
|
/**
|