@push.rocks/smartproxy 15.0.2 → 16.0.2
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/certificate/index.d.ts +10 -4
- package/dist_ts/certificate/index.js +5 -7
- package/dist_ts/certificate/models/certificate-types.d.ts +35 -15
- package/dist_ts/certificate/providers/cert-provisioner.d.ts +41 -15
- package/dist_ts/certificate/providers/cert-provisioner.js +201 -41
- package/dist_ts/forwarding/config/forwarding-types.d.ts +40 -76
- package/dist_ts/forwarding/config/forwarding-types.js +19 -18
- package/dist_ts/forwarding/config/index.d.ts +4 -2
- package/dist_ts/forwarding/config/index.js +5 -3
- package/dist_ts/forwarding/handlers/base-handler.js +3 -1
- package/dist_ts/forwarding/index.d.ts +5 -6
- package/dist_ts/forwarding/index.js +3 -3
- package/dist_ts/http/models/http-types.js +1 -1
- package/dist_ts/http/port80/acme-interfaces.d.ts +30 -0
- package/dist_ts/http/port80/acme-interfaces.js +46 -1
- package/dist_ts/http/port80/port80-handler.d.ts +17 -2
- package/dist_ts/http/port80/port80-handler.js +49 -11
- package/dist_ts/proxies/smart-proxy/models/interfaces.d.ts +2 -61
- package/dist_ts/proxies/smart-proxy/models/interfaces.js +5 -4
- package/dist_ts/proxies/smart-proxy/models/route-types.d.ts +118 -4
- package/dist_ts/proxies/smart-proxy/network-proxy-bridge.d.ts +70 -4
- package/dist_ts/proxies/smart-proxy/network-proxy-bridge.js +193 -43
- package/dist_ts/proxies/smart-proxy/route-connection-handler.d.ts +2 -5
- package/dist_ts/proxies/smart-proxy/route-connection-handler.js +25 -146
- package/dist_ts/proxies/smart-proxy/route-helpers/index.d.ts +7 -0
- package/dist_ts/proxies/smart-proxy/route-helpers/index.js +9 -0
- package/dist_ts/proxies/smart-proxy/route-helpers.d.ts +54 -1
- package/dist_ts/proxies/smart-proxy/route-helpers.js +102 -1
- package/dist_ts/proxies/smart-proxy/route-manager.d.ts +3 -9
- package/dist_ts/proxies/smart-proxy/route-manager.js +3 -115
- package/dist_ts/proxies/smart-proxy/smart-proxy.d.ts +72 -10
- package/dist_ts/proxies/smart-proxy/smart-proxy.js +135 -268
- package/dist_ts/proxies/smart-proxy/timeout-manager.js +3 -3
- package/dist_ts/proxies/smart-proxy/utils/index.d.ts +12 -0
- package/dist_ts/proxies/smart-proxy/utils/index.js +19 -0
- package/dist_ts/proxies/smart-proxy/utils/route-helpers.d.ts +174 -0
- package/dist_ts/proxies/smart-proxy/utils/route-helpers.js +332 -0
- package/dist_ts/proxies/smart-proxy/utils/route-migration-utils.d.ts +51 -0
- package/dist_ts/proxies/smart-proxy/utils/route-migration-utils.js +124 -0
- package/dist_ts/proxies/smart-proxy/utils/route-patterns.d.ts +131 -0
- package/dist_ts/proxies/smart-proxy/utils/route-patterns.js +217 -0
- package/dist_ts/proxies/smart-proxy/utils/route-utils.d.ts +79 -0
- package/dist_ts/proxies/smart-proxy/utils/route-utils.js +266 -0
- package/dist_ts/proxies/smart-proxy/utils/route-validators.d.ts +73 -0
- package/dist_ts/proxies/smart-proxy/utils/route-validators.js +242 -0
- package/package.json +1 -1
- package/readme.md +139 -111
- package/readme.plan.md +164 -312
- package/ts/00_commitinfo_data.ts +1 -1
- package/ts/certificate/index.ts +17 -9
- package/ts/certificate/models/certificate-types.ts +37 -16
- package/ts/certificate/providers/cert-provisioner.ts +247 -54
- package/ts/forwarding/config/forwarding-types.ts +79 -107
- package/ts/forwarding/config/index.ts +4 -2
- package/ts/forwarding/handlers/base-handler.ts +4 -2
- package/ts/forwarding/index.ts +3 -2
- package/ts/http/models/http-types.ts +0 -1
- package/ts/http/port80/acme-interfaces.ts +84 -0
- package/ts/http/port80/port80-handler.ts +61 -15
- package/ts/proxies/smart-proxy/models/interfaces.ts +7 -64
- package/ts/proxies/smart-proxy/models/route-types.ts +152 -22
- package/ts/proxies/smart-proxy/network-proxy-bridge.ts +226 -55
- package/ts/proxies/smart-proxy/route-connection-handler.ts +36 -205
- package/ts/proxies/smart-proxy/route-helpers/index.ts +9 -0
- package/ts/proxies/smart-proxy/route-helpers.ts +165 -11
- package/ts/proxies/smart-proxy/route-manager.ts +3 -130
- package/ts/proxies/smart-proxy/smart-proxy.ts +157 -329
- package/ts/proxies/smart-proxy/timeout-manager.ts +2 -2
- package/ts/proxies/smart-proxy/utils/index.ts +40 -0
- package/ts/proxies/smart-proxy/utils/route-helpers.ts +455 -0
- package/ts/proxies/smart-proxy/utils/route-migration-utils.ts +165 -0
- package/ts/proxies/smart-proxy/utils/route-patterns.ts +309 -0
- package/ts/proxies/smart-proxy/utils/route-utils.ts +330 -0
- package/ts/proxies/smart-proxy/utils/route-validators.ts +269 -0
- package/ts/forwarding/config/domain-config.ts +0 -28
- package/ts/forwarding/config/domain-manager.ts +0 -283
- package/ts/proxies/smart-proxy/connection-handler.ts +0 -1240
- package/ts/proxies/smart-proxy/port-range-manager.ts +0 -211
- /package/ts/proxies/smart-proxy/{domain-config-manager.ts → domain-config-manager.ts.bak} +0 -0
|
@@ -3,11 +3,10 @@ import * as plugins from '../../plugins.js';
|
|
|
3
3
|
// Importing required components
|
|
4
4
|
import { ConnectionManager } from './connection-manager.js';
|
|
5
5
|
import { SecurityManager } from './security-manager.js';
|
|
6
|
-
import { DomainConfigManager } from './domain-config-manager.js';
|
|
7
6
|
import { TlsManager } from './tls-manager.js';
|
|
8
7
|
import { NetworkProxyBridge } from './network-proxy-bridge.js';
|
|
9
8
|
import { TimeoutManager } from './timeout-manager.js';
|
|
10
|
-
import { PortRangeManager } from './port-range-manager.js';
|
|
9
|
+
// import { PortRangeManager } from './port-range-manager.js';
|
|
11
10
|
import { RouteManager } from './route-manager.js';
|
|
12
11
|
import { RouteConnectionHandler } from './route-connection-handler.js';
|
|
13
12
|
|
|
@@ -19,16 +18,25 @@ import { buildPort80Handler } from '../../certificate/acme/acme-factory.js';
|
|
|
19
18
|
import { createPort80HandlerOptions } from '../../common/port80-adapter.js';
|
|
20
19
|
|
|
21
20
|
// Import types and utilities
|
|
22
|
-
import type {
|
|
23
|
-
ISmartProxyOptions,
|
|
24
|
-
IRoutedSmartProxyOptions
|
|
25
|
-
IDomainConfig
|
|
21
|
+
import type {
|
|
22
|
+
ISmartProxyOptions,
|
|
23
|
+
IRoutedSmartProxyOptions
|
|
26
24
|
} from './models/interfaces.js';
|
|
27
25
|
import { isRoutedOptions, isLegacyOptions } from './models/interfaces.js';
|
|
28
26
|
import type { IRouteConfig } from './models/route-types.js';
|
|
29
27
|
|
|
30
28
|
/**
|
|
31
|
-
* SmartProxy -
|
|
29
|
+
* SmartProxy - Pure route-based API
|
|
30
|
+
*
|
|
31
|
+
* SmartProxy is a unified proxy system that works with routes to define connection handling behavior.
|
|
32
|
+
* Each route contains matching criteria (ports, domains, etc.) and an action to take (forward, redirect, block).
|
|
33
|
+
*
|
|
34
|
+
* Configuration is provided through a set of routes, with each route defining:
|
|
35
|
+
* - What to match (ports, domains, paths, client IPs)
|
|
36
|
+
* - What to do with matching traffic (forward, redirect, block)
|
|
37
|
+
* - How to handle TLS (passthrough, terminate, terminate-and-reencrypt)
|
|
38
|
+
* - Security settings (IP restrictions, connection limits)
|
|
39
|
+
* - Advanced options (timeout, headers, etc.)
|
|
32
40
|
*/
|
|
33
41
|
export class SmartProxy extends plugins.EventEmitter {
|
|
34
42
|
private netServers: plugins.net.Server[] = [];
|
|
@@ -38,11 +46,10 @@ export class SmartProxy extends plugins.EventEmitter {
|
|
|
38
46
|
// Component managers
|
|
39
47
|
private connectionManager: ConnectionManager;
|
|
40
48
|
private securityManager: SecurityManager;
|
|
41
|
-
private domainConfigManager: DomainConfigManager;
|
|
42
49
|
private tlsManager: TlsManager;
|
|
43
50
|
private networkProxyBridge: NetworkProxyBridge;
|
|
44
51
|
private timeoutManager: TimeoutManager;
|
|
45
|
-
private portRangeManager: PortRangeManager;
|
|
52
|
+
// private portRangeManager: PortRangeManager;
|
|
46
53
|
private routeManager: RouteManager;
|
|
47
54
|
private routeConnectionHandler: RouteConnectionHandler;
|
|
48
55
|
|
|
@@ -52,7 +59,35 @@ export class SmartProxy extends plugins.EventEmitter {
|
|
|
52
59
|
private certProvisioner?: CertProvisioner;
|
|
53
60
|
|
|
54
61
|
/**
|
|
55
|
-
* Constructor
|
|
62
|
+
* Constructor for SmartProxy
|
|
63
|
+
*
|
|
64
|
+
* @param settingsArg Configuration options containing routes and other settings
|
|
65
|
+
* Routes define how traffic is matched and handled, with each route having:
|
|
66
|
+
* - match: criteria for matching traffic (ports, domains, paths, IPs)
|
|
67
|
+
* - action: what to do with matched traffic (forward, redirect, block)
|
|
68
|
+
*
|
|
69
|
+
* Example:
|
|
70
|
+
* ```ts
|
|
71
|
+
* const proxy = new SmartProxy({
|
|
72
|
+
* routes: [
|
|
73
|
+
* {
|
|
74
|
+
* match: {
|
|
75
|
+
* ports: 443,
|
|
76
|
+
* domains: ['example.com', '*.example.com']
|
|
77
|
+
* },
|
|
78
|
+
* action: {
|
|
79
|
+
* type: 'forward',
|
|
80
|
+
* target: { host: '10.0.0.1', port: 8443 },
|
|
81
|
+
* tls: { mode: 'passthrough' }
|
|
82
|
+
* }
|
|
83
|
+
* }
|
|
84
|
+
* ],
|
|
85
|
+
* defaults: {
|
|
86
|
+
* target: { host: 'localhost', port: 8080 },
|
|
87
|
+
* security: { allowedIps: ['*'] }
|
|
88
|
+
* }
|
|
89
|
+
* });
|
|
90
|
+
* ```
|
|
56
91
|
*/
|
|
57
92
|
constructor(settingsArg: ISmartProxyOptions) {
|
|
58
93
|
super();
|
|
@@ -98,9 +133,9 @@ export class SmartProxy extends plugins.EventEmitter {
|
|
|
98
133
|
autoRenew: true,
|
|
99
134
|
certificateStore: './certs',
|
|
100
135
|
skipConfiguredCerts: false,
|
|
101
|
-
httpsRedirectPort:
|
|
136
|
+
httpsRedirectPort: 443,
|
|
102
137
|
renewCheckIntervalHours: 24,
|
|
103
|
-
|
|
138
|
+
routeForwards: []
|
|
104
139
|
};
|
|
105
140
|
}
|
|
106
141
|
|
|
@@ -113,18 +148,11 @@ export class SmartProxy extends plugins.EventEmitter {
|
|
|
113
148
|
this.timeoutManager
|
|
114
149
|
);
|
|
115
150
|
|
|
116
|
-
// Create the
|
|
151
|
+
// Create the route manager
|
|
117
152
|
this.routeManager = new RouteManager(this.settings);
|
|
118
153
|
|
|
119
|
-
// Create
|
|
120
|
-
this.
|
|
121
|
-
|
|
122
|
-
// Share the route manager with the domain config manager
|
|
123
|
-
if (typeof this.domainConfigManager.setRouteManager === 'function') {
|
|
124
|
-
this.domainConfigManager.setRouteManager(this.routeManager);
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
this.portRangeManager = new PortRangeManager(this.settings);
|
|
154
|
+
// Create port range manager
|
|
155
|
+
// this.portRangeManager = new PortRangeManager(this.settings);
|
|
128
156
|
|
|
129
157
|
// Create other required components
|
|
130
158
|
this.tlsManager = new TlsManager(this.settings);
|
|
@@ -135,7 +163,6 @@ export class SmartProxy extends plugins.EventEmitter {
|
|
|
135
163
|
this.settings,
|
|
136
164
|
this.connectionManager,
|
|
137
165
|
this.securityManager,
|
|
138
|
-
this.domainConfigManager,
|
|
139
166
|
this.tlsManager,
|
|
140
167
|
this.networkProxyBridge,
|
|
141
168
|
this.timeoutManager,
|
|
@@ -162,7 +189,7 @@ export class SmartProxy extends plugins.EventEmitter {
|
|
|
162
189
|
// Build and start the Port80Handler
|
|
163
190
|
this.port80Handler = buildPort80Handler({
|
|
164
191
|
...config,
|
|
165
|
-
httpsRedirectPort: config.httpsRedirectPort ||
|
|
192
|
+
httpsRedirectPort: config.httpsRedirectPort || 443
|
|
166
193
|
});
|
|
167
194
|
|
|
168
195
|
// Share Port80Handler with NetworkProxyBridge before start
|
|
@@ -184,17 +211,7 @@ export class SmartProxy extends plugins.EventEmitter {
|
|
|
184
211
|
return;
|
|
185
212
|
}
|
|
186
213
|
|
|
187
|
-
//
|
|
188
|
-
if (isLegacyOptions(this.settings)) {
|
|
189
|
-
// Initialize domain config manager with the legacy domain configs
|
|
190
|
-
this.domainConfigManager.updateDomainConfigs(this.settings.domainConfigs || []);
|
|
191
|
-
} else if (isRoutedOptions(this.settings)) {
|
|
192
|
-
// For pure route-based configuration, the domain config is already initialized
|
|
193
|
-
// in the constructor, but we might need to regenerate it
|
|
194
|
-
if (typeof this.domainConfigManager.generateDomainConfigsFromRoutes === 'function') {
|
|
195
|
-
this.domainConfigManager.generateDomainConfigsFromRoutes();
|
|
196
|
-
}
|
|
197
|
-
}
|
|
214
|
+
// Pure route-based configuration - no domain configs needed
|
|
198
215
|
|
|
199
216
|
// Initialize Port80Handler if enabled
|
|
200
217
|
await this.initializePort80Handler();
|
|
@@ -203,80 +220,22 @@ export class SmartProxy extends plugins.EventEmitter {
|
|
|
203
220
|
if (this.port80Handler) {
|
|
204
221
|
const acme = this.settings.acme!;
|
|
205
222
|
|
|
206
|
-
// Setup
|
|
207
|
-
const
|
|
208
|
-
if (isLegacyOptions(this.settings)) {
|
|
209
|
-
// If using legacy mode, check if domain config exists
|
|
210
|
-
const domainConfig = this.settings.domainConfigs.find(
|
|
211
|
-
dc => dc.domains.some(d => d === f.domain)
|
|
212
|
-
);
|
|
213
|
-
|
|
214
|
-
if (domainConfig?.forwarding) {
|
|
215
|
-
return {
|
|
216
|
-
domain: f.domain,
|
|
217
|
-
forwardConfig: f.forwardConfig,
|
|
218
|
-
acmeForwardConfig: f.acmeForwardConfig,
|
|
219
|
-
sslRedirect: f.sslRedirect || domainConfig.forwarding.http?.redirectToHttps || false
|
|
220
|
-
};
|
|
221
|
-
}
|
|
222
|
-
} else {
|
|
223
|
-
// In route mode, look for matching route
|
|
224
|
-
const route = this.routeManager.findMatchingRoute({
|
|
225
|
-
port: 443,
|
|
226
|
-
domain: f.domain,
|
|
227
|
-
clientIp: '127.0.0.1' // Dummy IP for finding routes
|
|
228
|
-
})?.route;
|
|
229
|
-
|
|
230
|
-
if (route && route.action.type === 'forward' && route.action.tls) {
|
|
231
|
-
// If we found a matching route with TLS settings
|
|
232
|
-
return {
|
|
233
|
-
domain: f.domain,
|
|
234
|
-
forwardConfig: f.forwardConfig,
|
|
235
|
-
acmeForwardConfig: f.acmeForwardConfig,
|
|
236
|
-
sslRedirect: f.sslRedirect || false
|
|
237
|
-
};
|
|
238
|
-
}
|
|
239
|
-
}
|
|
240
|
-
|
|
241
|
-
// Otherwise use the existing configuration
|
|
242
|
-
return {
|
|
243
|
-
domain: f.domain,
|
|
244
|
-
forwardConfig: f.forwardConfig,
|
|
245
|
-
acmeForwardConfig: f.acmeForwardConfig,
|
|
246
|
-
sslRedirect: f.sslRedirect || false
|
|
247
|
-
};
|
|
248
|
-
}) || [];
|
|
223
|
+
// Setup route forwards
|
|
224
|
+
const routeForwards = acme.routeForwards?.map(f => f) || [];
|
|
249
225
|
|
|
250
226
|
// Create CertProvisioner with appropriate parameters
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
// For route-based configuration, we need to adapt the interface
|
|
264
|
-
// Convert routes to domain configs for CertProvisioner
|
|
265
|
-
const domainConfigs: IDomainConfig[] = this.extractDomainConfigsFromRoutes(
|
|
266
|
-
(this.settings as IRoutedSmartProxyOptions).routes
|
|
267
|
-
);
|
|
268
|
-
|
|
269
|
-
this.certProvisioner = new CertProvisioner(
|
|
270
|
-
domainConfigs,
|
|
271
|
-
this.port80Handler,
|
|
272
|
-
this.networkProxyBridge,
|
|
273
|
-
this.settings.certProvisionFunction,
|
|
274
|
-
acme.renewThresholdDays!,
|
|
275
|
-
acme.renewCheckIntervalHours!,
|
|
276
|
-
acme.autoRenew!,
|
|
277
|
-
domainForwards
|
|
278
|
-
);
|
|
279
|
-
}
|
|
227
|
+
// No longer need to support multiple configuration types
|
|
228
|
+
// Just pass the routes directly
|
|
229
|
+
this.certProvisioner = new CertProvisioner(
|
|
230
|
+
this.settings.routes,
|
|
231
|
+
this.port80Handler,
|
|
232
|
+
this.networkProxyBridge,
|
|
233
|
+
this.settings.certProvisionFunction,
|
|
234
|
+
acme.renewThresholdDays!,
|
|
235
|
+
acme.renewCheckIntervalHours!,
|
|
236
|
+
acme.autoRenew!,
|
|
237
|
+
routeForwards
|
|
238
|
+
);
|
|
280
239
|
|
|
281
240
|
// Register certificate event handler
|
|
282
241
|
this.certProvisioner.on('certificate', (certData) => {
|
|
@@ -332,10 +291,8 @@ export class SmartProxy extends plugins.EventEmitter {
|
|
|
332
291
|
const isNetworkProxyPort = this.settings.useNetworkProxy?.includes(port);
|
|
333
292
|
console.log(
|
|
334
293
|
`SmartProxy -> OK: Now listening on port ${port}${
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
''
|
|
338
|
-
}${isNetworkProxyPort ? ' (NetworkProxy forwarding enabled)' : ''}`
|
|
294
|
+
isNetworkProxyPort ? ' (NetworkProxy forwarding enabled)' : ''
|
|
295
|
+
}`
|
|
339
296
|
);
|
|
340
297
|
});
|
|
341
298
|
|
|
@@ -416,60 +373,9 @@ export class SmartProxy extends plugins.EventEmitter {
|
|
|
416
373
|
|
|
417
374
|
/**
|
|
418
375
|
* Extract domain configurations from routes for certificate provisioning
|
|
376
|
+
*
|
|
377
|
+
* Note: This method has been removed as we now work directly with routes
|
|
419
378
|
*/
|
|
420
|
-
private extractDomainConfigsFromRoutes(routes: IRouteConfig[]): IDomainConfig[] {
|
|
421
|
-
const domainConfigs: IDomainConfig[] = [];
|
|
422
|
-
|
|
423
|
-
for (const route of routes) {
|
|
424
|
-
// Skip routes without domain specs
|
|
425
|
-
if (!route.match.domains) continue;
|
|
426
|
-
|
|
427
|
-
// Skip non-forward routes
|
|
428
|
-
if (route.action.type !== 'forward') continue;
|
|
429
|
-
|
|
430
|
-
// Only process routes that need TLS termination (those with certificates)
|
|
431
|
-
if (!route.action.tls ||
|
|
432
|
-
route.action.tls.mode === 'passthrough' ||
|
|
433
|
-
!route.action.target) continue;
|
|
434
|
-
|
|
435
|
-
const domains = Array.isArray(route.match.domains)
|
|
436
|
-
? route.match.domains
|
|
437
|
-
: [route.match.domains];
|
|
438
|
-
|
|
439
|
-
// Determine forwarding type based on TLS mode
|
|
440
|
-
const forwardingType = route.action.tls.mode === 'terminate'
|
|
441
|
-
? 'https-terminate-to-http'
|
|
442
|
-
: 'https-terminate-to-https';
|
|
443
|
-
|
|
444
|
-
// Create a forwarding config
|
|
445
|
-
const forwarding = {
|
|
446
|
-
type: forwardingType as any,
|
|
447
|
-
target: {
|
|
448
|
-
host: Array.isArray(route.action.target.host)
|
|
449
|
-
? route.action.target.host[0]
|
|
450
|
-
: route.action.target.host,
|
|
451
|
-
port: route.action.target.port
|
|
452
|
-
},
|
|
453
|
-
// Add TLS settings
|
|
454
|
-
https: {
|
|
455
|
-
customCert: route.action.tls.certificate !== 'auto'
|
|
456
|
-
? route.action.tls.certificate
|
|
457
|
-
: undefined
|
|
458
|
-
},
|
|
459
|
-
// Add security settings if present
|
|
460
|
-
security: route.action.security,
|
|
461
|
-
// Add advanced settings if present
|
|
462
|
-
advanced: route.action.advanced
|
|
463
|
-
};
|
|
464
|
-
|
|
465
|
-
domainConfigs.push({
|
|
466
|
-
domains,
|
|
467
|
-
forwarding
|
|
468
|
-
});
|
|
469
|
-
}
|
|
470
|
-
|
|
471
|
-
return domainConfigs;
|
|
472
|
-
}
|
|
473
379
|
|
|
474
380
|
/**
|
|
475
381
|
* Stop the proxy server
|
|
@@ -535,188 +441,119 @@ export class SmartProxy extends plugins.EventEmitter {
|
|
|
535
441
|
}
|
|
536
442
|
|
|
537
443
|
/**
|
|
538
|
-
* Updates the domain configurations for the proxy
|
|
444
|
+
* Updates the domain configurations for the proxy
|
|
445
|
+
*
|
|
446
|
+
* Note: This legacy method has been removed. Use updateRoutes instead.
|
|
539
447
|
*/
|
|
540
|
-
public async updateDomainConfigs(
|
|
541
|
-
console.
|
|
542
|
-
|
|
543
|
-
// Update domain configs in DomainConfigManager (legacy)
|
|
544
|
-
this.domainConfigManager.updateDomainConfigs(newDomainConfigs);
|
|
545
|
-
|
|
546
|
-
// Also update the RouteManager with these domain configs
|
|
547
|
-
this.routeManager.updateFromDomainConfigs(newDomainConfigs);
|
|
548
|
-
|
|
549
|
-
// If NetworkProxy is initialized, resync the configurations
|
|
550
|
-
if (this.networkProxyBridge.getNetworkProxy()) {
|
|
551
|
-
await this.networkProxyBridge.syncDomainConfigsToNetworkProxy();
|
|
552
|
-
}
|
|
553
|
-
|
|
554
|
-
// If Port80Handler is running, provision certificates based on forwarding type
|
|
555
|
-
if (this.port80Handler && this.settings.acme?.enabled) {
|
|
556
|
-
for (const domainConfig of newDomainConfigs) {
|
|
557
|
-
// Skip certificate provisioning for http-only or passthrough configs that don't need certs
|
|
558
|
-
const forwardingType = this.domainConfigManager.getForwardingType(domainConfig);
|
|
559
|
-
const needsCertificate =
|
|
560
|
-
forwardingType === 'https-terminate-to-http' ||
|
|
561
|
-
forwardingType === 'https-terminate-to-https';
|
|
562
|
-
|
|
563
|
-
// Skip certificate provisioning if ACME is explicitly disabled for this domain
|
|
564
|
-
const acmeDisabled = domainConfig.forwarding.acme?.enabled === false;
|
|
565
|
-
|
|
566
|
-
if (!needsCertificate || acmeDisabled) {
|
|
567
|
-
if (this.settings.enableDetailedLogging) {
|
|
568
|
-
console.log(`Skipping certificate provisioning for ${domainConfig.domains.join(', ')} (${forwardingType})`);
|
|
569
|
-
}
|
|
570
|
-
continue;
|
|
571
|
-
}
|
|
572
|
-
|
|
573
|
-
for (const domain of domainConfig.domains) {
|
|
574
|
-
const isWildcard = domain.includes('*');
|
|
575
|
-
let provision: string | plugins.tsclass.network.ICert = 'http01';
|
|
576
|
-
|
|
577
|
-
// Check for ACME forwarding configuration in the domain
|
|
578
|
-
const forwardAcmeChallenges = domainConfig.forwarding.acme?.forwardChallenges;
|
|
579
|
-
|
|
580
|
-
if (this.settings.certProvisionFunction) {
|
|
581
|
-
try {
|
|
582
|
-
provision = await this.settings.certProvisionFunction(domain);
|
|
583
|
-
} catch (err) {
|
|
584
|
-
console.log(`certProvider error for ${domain}: ${err}`);
|
|
585
|
-
}
|
|
586
|
-
} else if (isWildcard) {
|
|
587
|
-
console.warn(`Skipping wildcard domain without certProvisionFunction: ${domain}`);
|
|
588
|
-
continue;
|
|
589
|
-
}
|
|
590
|
-
|
|
591
|
-
if (provision === 'http01') {
|
|
592
|
-
if (isWildcard) {
|
|
593
|
-
console.warn(`Skipping HTTP-01 for wildcard domain: ${domain}`);
|
|
594
|
-
continue;
|
|
595
|
-
}
|
|
596
|
-
|
|
597
|
-
// Create Port80Handler options from the forwarding configuration
|
|
598
|
-
const port80Config = createPort80HandlerOptions(domain, domainConfig.forwarding);
|
|
599
|
-
|
|
600
|
-
this.port80Handler.addDomain(port80Config);
|
|
601
|
-
console.log(`Registered domain ${domain} with Port80Handler for HTTP-01`);
|
|
602
|
-
} else {
|
|
603
|
-
// Static certificate (e.g., DNS-01 provisioned) supports wildcards
|
|
604
|
-
const certObj = provision as plugins.tsclass.network.ICert;
|
|
605
|
-
const certData: ICertificateData = {
|
|
606
|
-
domain: certObj.domainName,
|
|
607
|
-
certificate: certObj.publicKey,
|
|
608
|
-
privateKey: certObj.privateKey,
|
|
609
|
-
expiryDate: new Date(certObj.validUntil)
|
|
610
|
-
};
|
|
611
|
-
this.networkProxyBridge.applyExternalCertificate(certData);
|
|
612
|
-
console.log(`Applied static certificate for ${domain} from certProvider`);
|
|
613
|
-
}
|
|
614
|
-
}
|
|
615
|
-
}
|
|
616
|
-
console.log('Provisioned certificates for new domains');
|
|
617
|
-
}
|
|
448
|
+
public async updateDomainConfigs(): Promise<void> {
|
|
449
|
+
console.warn('Method updateDomainConfigs() is deprecated. Use updateRoutes() instead.');
|
|
450
|
+
throw new Error('updateDomainConfigs() is deprecated - use updateRoutes() instead');
|
|
618
451
|
}
|
|
619
452
|
|
|
620
453
|
/**
|
|
621
|
-
* Update routes with new configuration
|
|
454
|
+
* Update routes with new configuration
|
|
455
|
+
*
|
|
456
|
+
* This method replaces the current route configuration with the provided routes.
|
|
457
|
+
* It also provisions certificates for routes that require TLS termination and have
|
|
458
|
+
* `certificate: 'auto'` set in their TLS configuration.
|
|
459
|
+
*
|
|
460
|
+
* @param newRoutes Array of route configurations to use
|
|
461
|
+
*
|
|
462
|
+
* Example:
|
|
463
|
+
* ```ts
|
|
464
|
+
* proxy.updateRoutes([
|
|
465
|
+
* {
|
|
466
|
+
* match: { ports: 443, domains: 'secure.example.com' },
|
|
467
|
+
* action: {
|
|
468
|
+
* type: 'forward',
|
|
469
|
+
* target: { host: '10.0.0.1', port: 8443 },
|
|
470
|
+
* tls: { mode: 'terminate', certificate: 'auto' }
|
|
471
|
+
* }
|
|
472
|
+
* }
|
|
473
|
+
* ]);
|
|
474
|
+
* ```
|
|
622
475
|
*/
|
|
623
476
|
public async updateRoutes(newRoutes: IRouteConfig[]): Promise<void> {
|
|
624
477
|
console.log(`Updating routes (${newRoutes.length} routes)`);
|
|
625
|
-
|
|
478
|
+
|
|
626
479
|
// Update routes in RouteManager
|
|
627
480
|
this.routeManager.updateRoutes(newRoutes);
|
|
628
|
-
|
|
481
|
+
|
|
629
482
|
// If NetworkProxy is initialized, resync the configurations
|
|
630
483
|
if (this.networkProxyBridge.getNetworkProxy()) {
|
|
631
|
-
|
|
632
|
-
const domainConfigs = this.extractDomainConfigsFromRoutes(newRoutes);
|
|
633
|
-
|
|
634
|
-
// Update domain configs in DomainConfigManager for sync
|
|
635
|
-
this.domainConfigManager.updateDomainConfigs(domainConfigs);
|
|
636
|
-
|
|
637
|
-
// Sync with NetworkProxy
|
|
638
|
-
await this.networkProxyBridge.syncDomainConfigsToNetworkProxy();
|
|
484
|
+
await this.networkProxyBridge.syncRoutesToNetworkProxy(newRoutes);
|
|
639
485
|
}
|
|
640
|
-
|
|
486
|
+
|
|
641
487
|
// If Port80Handler is running, provision certificates based on routes
|
|
642
488
|
if (this.port80Handler && this.settings.acme?.enabled) {
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
const
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
489
|
+
// Register all eligible domains from routes
|
|
490
|
+
this.port80Handler.addDomainsFromRoutes(newRoutes);
|
|
491
|
+
|
|
492
|
+
// Handle static certificates from certProvisionFunction if available
|
|
493
|
+
if (this.settings.certProvisionFunction) {
|
|
494
|
+
for (const route of newRoutes) {
|
|
495
|
+
// Skip routes without domains
|
|
496
|
+
if (!route.match.domains) continue;
|
|
497
|
+
|
|
498
|
+
// Skip non-forward routes
|
|
499
|
+
if (route.action.type !== 'forward') continue;
|
|
500
|
+
|
|
501
|
+
// Skip routes without TLS termination
|
|
502
|
+
if (!route.action.tls ||
|
|
503
|
+
route.action.tls.mode === 'passthrough' ||
|
|
504
|
+
!route.action.target) continue;
|
|
505
|
+
|
|
506
|
+
// Skip certificate provisioning if certificate is not auto
|
|
507
|
+
if (route.action.tls.certificate !== 'auto') continue;
|
|
508
|
+
|
|
509
|
+
const domains = Array.isArray(route.match.domains)
|
|
510
|
+
? route.match.domains
|
|
511
|
+
: [route.match.domains];
|
|
512
|
+
|
|
513
|
+
for (const domain of domains) {
|
|
667
514
|
try {
|
|
668
|
-
provision = await this.settings.certProvisionFunction(domain);
|
|
515
|
+
const provision = await this.settings.certProvisionFunction(domain);
|
|
516
|
+
|
|
517
|
+
// Skip http01 as those are handled by Port80Handler
|
|
518
|
+
if (provision !== 'http01') {
|
|
519
|
+
// Handle static certificate (e.g., DNS-01 provisioned)
|
|
520
|
+
const certObj = provision as plugins.tsclass.network.ICert;
|
|
521
|
+
const certData: ICertificateData = {
|
|
522
|
+
domain: certObj.domainName,
|
|
523
|
+
certificate: certObj.publicKey,
|
|
524
|
+
privateKey: certObj.privateKey,
|
|
525
|
+
expiryDate: new Date(certObj.validUntil),
|
|
526
|
+
routeReference: {
|
|
527
|
+
routeName: route.name
|
|
528
|
+
}
|
|
529
|
+
};
|
|
530
|
+
this.networkProxyBridge.applyExternalCertificate(certData);
|
|
531
|
+
console.log(`Applied static certificate for ${domain} from certProvider`);
|
|
532
|
+
}
|
|
669
533
|
} catch (err) {
|
|
670
534
|
console.log(`certProvider error for ${domain}: ${err}`);
|
|
671
535
|
}
|
|
672
|
-
} else if (isWildcard) {
|
|
673
|
-
console.warn(`Skipping wildcard domain without certProvisionFunction: ${domain}`);
|
|
674
|
-
continue;
|
|
675
|
-
}
|
|
676
|
-
|
|
677
|
-
if (provision === 'http01') {
|
|
678
|
-
if (isWildcard) {
|
|
679
|
-
console.warn(`Skipping HTTP-01 for wildcard domain: ${domain}`);
|
|
680
|
-
continue;
|
|
681
|
-
}
|
|
682
|
-
|
|
683
|
-
// Register domain with Port80Handler
|
|
684
|
-
this.port80Handler.addDomain({
|
|
685
|
-
domainName: domain,
|
|
686
|
-
sslRedirect: true,
|
|
687
|
-
acmeMaintenance: true
|
|
688
|
-
});
|
|
689
|
-
|
|
690
|
-
console.log(`Registered domain ${domain} with Port80Handler for HTTP-01`);
|
|
691
|
-
} else {
|
|
692
|
-
// Handle static certificate (e.g., DNS-01 provisioned)
|
|
693
|
-
const certObj = provision as plugins.tsclass.network.ICert;
|
|
694
|
-
const certData: ICertificateData = {
|
|
695
|
-
domain: certObj.domainName,
|
|
696
|
-
certificate: certObj.publicKey,
|
|
697
|
-
privateKey: certObj.privateKey,
|
|
698
|
-
expiryDate: new Date(certObj.validUntil)
|
|
699
|
-
};
|
|
700
|
-
this.networkProxyBridge.applyExternalCertificate(certData);
|
|
701
|
-
console.log(`Applied static certificate for ${domain} from certProvider`);
|
|
702
536
|
}
|
|
703
537
|
}
|
|
704
538
|
}
|
|
705
|
-
|
|
539
|
+
|
|
706
540
|
console.log('Provisioned certificates for new routes');
|
|
707
541
|
}
|
|
708
542
|
}
|
|
709
543
|
|
|
710
544
|
/**
|
|
711
545
|
* Request a certificate for a specific domain
|
|
546
|
+
*
|
|
547
|
+
* @param domain The domain to request a certificate for
|
|
548
|
+
* @param routeName Optional route name to associate with the certificate
|
|
712
549
|
*/
|
|
713
|
-
public async requestCertificate(domain: string): Promise<boolean> {
|
|
550
|
+
public async requestCertificate(domain: string, routeName?: string): Promise<boolean> {
|
|
714
551
|
// Validate domain format
|
|
715
552
|
if (!this.isValidDomain(domain)) {
|
|
716
553
|
console.log(`Invalid domain format: ${domain}`);
|
|
717
554
|
return false;
|
|
718
555
|
}
|
|
719
|
-
|
|
556
|
+
|
|
720
557
|
// Use Port80Handler if available
|
|
721
558
|
if (this.port80Handler) {
|
|
722
559
|
try {
|
|
@@ -726,15 +563,16 @@ export class SmartProxy extends plugins.EventEmitter {
|
|
|
726
563
|
console.log(`Certificate already exists for ${domain}, valid until ${cert.expiryDate.toISOString()}`);
|
|
727
564
|
return true;
|
|
728
565
|
}
|
|
729
|
-
|
|
566
|
+
|
|
730
567
|
// Register domain for certificate issuance
|
|
731
568
|
this.port80Handler.addDomain({
|
|
732
|
-
|
|
569
|
+
domain,
|
|
733
570
|
sslRedirect: true,
|
|
734
|
-
acmeMaintenance: true
|
|
571
|
+
acmeMaintenance: true,
|
|
572
|
+
routeReference: routeName ? { routeName } : undefined
|
|
735
573
|
});
|
|
736
|
-
|
|
737
|
-
console.log(`Domain ${domain} registered for certificate issuance`);
|
|
574
|
+
|
|
575
|
+
console.log(`Domain ${domain} registered for certificate issuance` + (routeName ? ` for route '${routeName}'` : ''));
|
|
738
576
|
return true;
|
|
739
577
|
} catch (err) {
|
|
740
578
|
console.log(`Error registering domain with Port80Handler: ${err}`);
|
|
@@ -834,17 +672,7 @@ export class SmartProxy extends plugins.EventEmitter {
|
|
|
834
672
|
domains.push(...eligibleDomains);
|
|
835
673
|
}
|
|
836
674
|
|
|
837
|
-
//
|
|
838
|
-
if (isLegacyOptions(this.settings)) {
|
|
839
|
-
for (const config of this.settings.domainConfigs) {
|
|
840
|
-
// Skip domains that can't be used with ACME
|
|
841
|
-
const eligibleDomains = config.domains.filter(domain =>
|
|
842
|
-
!domain.includes('*') && this.isValidDomain(domain)
|
|
843
|
-
);
|
|
844
|
-
|
|
845
|
-
domains.push(...eligibleDomains);
|
|
846
|
-
}
|
|
847
|
-
}
|
|
675
|
+
// Legacy mode is no longer supported
|
|
848
676
|
|
|
849
677
|
return domains;
|
|
850
678
|
}
|
|
@@ -61,8 +61,8 @@ export class TimeoutManager {
|
|
|
61
61
|
* Calculate effective max lifetime based on connection type
|
|
62
62
|
*/
|
|
63
63
|
public getEffectiveMaxLifetime(record: IConnectionRecord): number {
|
|
64
|
-
// Use
|
|
65
|
-
const baseTimeout = record.
|
|
64
|
+
// Use route-specific timeout if available from the routeConfig
|
|
65
|
+
const baseTimeout = record.routeConfig?.action.advanced?.timeout ||
|
|
66
66
|
this.settings.maxConnectionLifetime ||
|
|
67
67
|
86400000; // 24 hours default
|
|
68
68
|
|