@push.rocks/smartproxy 13.1.2 → 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 +863 -423
- 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
|
@@ -0,0 +1,483 @@
|
|
|
1
|
+
import * as plugins from '../../plugins.js';
|
|
2
|
+
import { isRoutedOptions, isLegacyOptions } from './models/interfaces.js';
|
|
3
|
+
/**
|
|
4
|
+
* The RouteManager handles all routing decisions based on connections and attributes
|
|
5
|
+
*/
|
|
6
|
+
export class RouteManager extends plugins.EventEmitter {
|
|
7
|
+
constructor(options) {
|
|
8
|
+
super();
|
|
9
|
+
this.routes = [];
|
|
10
|
+
this.portMap = new Map();
|
|
11
|
+
// We no longer support legacy options, always use provided options
|
|
12
|
+
this.options = options;
|
|
13
|
+
// Initialize routes from either source
|
|
14
|
+
this.updateRoutes(this.options.routes);
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Update routes with new configuration
|
|
18
|
+
*/
|
|
19
|
+
updateRoutes(routes = []) {
|
|
20
|
+
// Sort routes by priority (higher first)
|
|
21
|
+
this.routes = [...(routes || [])].sort((a, b) => {
|
|
22
|
+
const priorityA = a.priority ?? 0;
|
|
23
|
+
const priorityB = b.priority ?? 0;
|
|
24
|
+
return priorityB - priorityA;
|
|
25
|
+
});
|
|
26
|
+
// Rebuild port mapping for fast lookups
|
|
27
|
+
this.rebuildPortMap();
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Rebuild the port mapping for fast lookups
|
|
31
|
+
*/
|
|
32
|
+
rebuildPortMap() {
|
|
33
|
+
this.portMap.clear();
|
|
34
|
+
for (const route of this.routes) {
|
|
35
|
+
const ports = this.expandPortRange(route.match.ports);
|
|
36
|
+
for (const port of ports) {
|
|
37
|
+
if (!this.portMap.has(port)) {
|
|
38
|
+
this.portMap.set(port, []);
|
|
39
|
+
}
|
|
40
|
+
this.portMap.get(port).push(route);
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Expand a port range specification into an array of individual ports
|
|
46
|
+
*/
|
|
47
|
+
expandPortRange(portRange) {
|
|
48
|
+
if (typeof portRange === 'number') {
|
|
49
|
+
return [portRange];
|
|
50
|
+
}
|
|
51
|
+
if (Array.isArray(portRange)) {
|
|
52
|
+
// Handle array of port objects or numbers
|
|
53
|
+
return portRange.flatMap(item => {
|
|
54
|
+
if (typeof item === 'number') {
|
|
55
|
+
return [item];
|
|
56
|
+
}
|
|
57
|
+
else if (typeof item === 'object' && 'from' in item && 'to' in item) {
|
|
58
|
+
// Handle port range object
|
|
59
|
+
const ports = [];
|
|
60
|
+
for (let p = item.from; p <= item.to; p++) {
|
|
61
|
+
ports.push(p);
|
|
62
|
+
}
|
|
63
|
+
return ports;
|
|
64
|
+
}
|
|
65
|
+
return [];
|
|
66
|
+
});
|
|
67
|
+
}
|
|
68
|
+
return [];
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* Get all ports that should be listened on
|
|
72
|
+
*/
|
|
73
|
+
getListeningPorts() {
|
|
74
|
+
return Array.from(this.portMap.keys());
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* Get all routes for a given port
|
|
78
|
+
*/
|
|
79
|
+
getRoutesForPort(port) {
|
|
80
|
+
return this.portMap.get(port) || [];
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* Test if a pattern matches a domain using glob matching
|
|
84
|
+
*/
|
|
85
|
+
matchDomain(pattern, domain) {
|
|
86
|
+
// Convert glob pattern to regex
|
|
87
|
+
const regexPattern = pattern
|
|
88
|
+
.replace(/\./g, '\\.') // Escape dots
|
|
89
|
+
.replace(/\*/g, '.*'); // Convert * to .*
|
|
90
|
+
const regex = new RegExp(`^${regexPattern}$`, 'i');
|
|
91
|
+
return regex.test(domain);
|
|
92
|
+
}
|
|
93
|
+
/**
|
|
94
|
+
* Match a domain against all patterns in a route
|
|
95
|
+
*/
|
|
96
|
+
matchRouteDomain(route, domain) {
|
|
97
|
+
if (!route.match.domains) {
|
|
98
|
+
// If no domains specified, match all domains
|
|
99
|
+
return true;
|
|
100
|
+
}
|
|
101
|
+
const patterns = Array.isArray(route.match.domains)
|
|
102
|
+
? route.match.domains
|
|
103
|
+
: [route.match.domains];
|
|
104
|
+
return patterns.some(pattern => this.matchDomain(pattern, domain));
|
|
105
|
+
}
|
|
106
|
+
/**
|
|
107
|
+
* Check if a client IP is allowed by a route's security settings
|
|
108
|
+
*/
|
|
109
|
+
isClientIpAllowed(route, clientIp) {
|
|
110
|
+
const security = route.action.security;
|
|
111
|
+
if (!security) {
|
|
112
|
+
return true; // No security settings means allowed
|
|
113
|
+
}
|
|
114
|
+
// Check blocked IPs first
|
|
115
|
+
if (security.blockedIps && security.blockedIps.length > 0) {
|
|
116
|
+
for (const pattern of security.blockedIps) {
|
|
117
|
+
if (this.matchIpPattern(pattern, clientIp)) {
|
|
118
|
+
return false; // IP is blocked
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
// If there are allowed IPs, check them
|
|
123
|
+
if (security.allowedIps && security.allowedIps.length > 0) {
|
|
124
|
+
for (const pattern of security.allowedIps) {
|
|
125
|
+
if (this.matchIpPattern(pattern, clientIp)) {
|
|
126
|
+
return true; // IP is allowed
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
return false; // IP not in allowed list
|
|
130
|
+
}
|
|
131
|
+
// No allowed IPs specified, so IP is allowed
|
|
132
|
+
return true;
|
|
133
|
+
}
|
|
134
|
+
/**
|
|
135
|
+
* Match an IP against a pattern
|
|
136
|
+
*/
|
|
137
|
+
matchIpPattern(pattern, ip) {
|
|
138
|
+
// Handle exact match
|
|
139
|
+
if (pattern === ip) {
|
|
140
|
+
return true;
|
|
141
|
+
}
|
|
142
|
+
// Handle CIDR notation (e.g., 192.168.1.0/24)
|
|
143
|
+
if (pattern.includes('/')) {
|
|
144
|
+
return this.matchIpCidr(pattern, ip);
|
|
145
|
+
}
|
|
146
|
+
// Handle glob pattern (e.g., 192.168.1.*)
|
|
147
|
+
if (pattern.includes('*')) {
|
|
148
|
+
const regexPattern = pattern.replace(/\./g, '\\.').replace(/\*/g, '.*');
|
|
149
|
+
const regex = new RegExp(`^${regexPattern}$`);
|
|
150
|
+
return regex.test(ip);
|
|
151
|
+
}
|
|
152
|
+
return false;
|
|
153
|
+
}
|
|
154
|
+
/**
|
|
155
|
+
* Match an IP against a CIDR pattern
|
|
156
|
+
*/
|
|
157
|
+
matchIpCidr(cidr, ip) {
|
|
158
|
+
try {
|
|
159
|
+
// In a real implementation, you'd use a proper IP library
|
|
160
|
+
// This is a simplified implementation
|
|
161
|
+
const [subnet, bits] = cidr.split('/');
|
|
162
|
+
const mask = parseInt(bits, 10);
|
|
163
|
+
// Convert IP addresses to numeric values
|
|
164
|
+
const ipNum = this.ipToNumber(ip);
|
|
165
|
+
const subnetNum = this.ipToNumber(subnet);
|
|
166
|
+
// Calculate subnet mask
|
|
167
|
+
const maskNum = ~(2 ** (32 - mask) - 1);
|
|
168
|
+
// Check if IP is in subnet
|
|
169
|
+
return (ipNum & maskNum) === (subnetNum & maskNum);
|
|
170
|
+
}
|
|
171
|
+
catch (e) {
|
|
172
|
+
console.error(`Error matching IP ${ip} against CIDR ${cidr}:`, e);
|
|
173
|
+
return false;
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
/**
|
|
177
|
+
* Convert an IP address to a numeric value
|
|
178
|
+
*/
|
|
179
|
+
ipToNumber(ip) {
|
|
180
|
+
const parts = ip.split('.').map(part => parseInt(part, 10));
|
|
181
|
+
return (parts[0] << 24) | (parts[1] << 16) | (parts[2] << 8) | parts[3];
|
|
182
|
+
}
|
|
183
|
+
/**
|
|
184
|
+
* Find the matching route for a connection
|
|
185
|
+
*/
|
|
186
|
+
findMatchingRoute(options) {
|
|
187
|
+
const { port, domain, clientIp, path, tlsVersion } = options;
|
|
188
|
+
// Get all routes for this port
|
|
189
|
+
const routesForPort = this.getRoutesForPort(port);
|
|
190
|
+
// Find the first matching route based on priority order
|
|
191
|
+
for (const route of routesForPort) {
|
|
192
|
+
// Check domain match if specified
|
|
193
|
+
if (domain && !this.matchRouteDomain(route, domain)) {
|
|
194
|
+
continue;
|
|
195
|
+
}
|
|
196
|
+
// Check path match if specified in both route and request
|
|
197
|
+
if (path && route.match.path) {
|
|
198
|
+
if (!this.matchPath(route.match.path, path)) {
|
|
199
|
+
continue;
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
// Check client IP match
|
|
203
|
+
if (route.match.clientIp && !route.match.clientIp.some(pattern => this.matchIpPattern(pattern, clientIp))) {
|
|
204
|
+
continue;
|
|
205
|
+
}
|
|
206
|
+
// Check TLS version match
|
|
207
|
+
if (tlsVersion && route.match.tlsVersion &&
|
|
208
|
+
!route.match.tlsVersion.includes(tlsVersion)) {
|
|
209
|
+
continue;
|
|
210
|
+
}
|
|
211
|
+
// Check security settings
|
|
212
|
+
if (!this.isClientIpAllowed(route, clientIp)) {
|
|
213
|
+
continue;
|
|
214
|
+
}
|
|
215
|
+
// All checks passed, this route matches
|
|
216
|
+
return { route };
|
|
217
|
+
}
|
|
218
|
+
return null;
|
|
219
|
+
}
|
|
220
|
+
/**
|
|
221
|
+
* Match a path against a pattern
|
|
222
|
+
*/
|
|
223
|
+
matchPath(pattern, path) {
|
|
224
|
+
// Convert the glob pattern to a regex
|
|
225
|
+
const regexPattern = pattern
|
|
226
|
+
.replace(/\./g, '\\.') // Escape dots
|
|
227
|
+
.replace(/\*/g, '.*') // Convert * to .*
|
|
228
|
+
.replace(/\//g, '\\/'); // Escape slashes
|
|
229
|
+
const regex = new RegExp(`^${regexPattern}$`);
|
|
230
|
+
return regex.test(path);
|
|
231
|
+
}
|
|
232
|
+
/**
|
|
233
|
+
* Convert a domain config to routes
|
|
234
|
+
* (For backward compatibility with code that still uses domainConfigs)
|
|
235
|
+
*/
|
|
236
|
+
domainConfigToRoutes(domainConfig) {
|
|
237
|
+
const routes = [];
|
|
238
|
+
const { domains, forwarding } = domainConfig;
|
|
239
|
+
// Determine the action based on forwarding type
|
|
240
|
+
let action = {
|
|
241
|
+
type: 'forward',
|
|
242
|
+
target: {
|
|
243
|
+
host: forwarding.target.host,
|
|
244
|
+
port: forwarding.target.port
|
|
245
|
+
}
|
|
246
|
+
};
|
|
247
|
+
// Set TLS mode based on forwarding type
|
|
248
|
+
switch (forwarding.type) {
|
|
249
|
+
case 'http-only':
|
|
250
|
+
// No TLS settings needed
|
|
251
|
+
break;
|
|
252
|
+
case 'https-passthrough':
|
|
253
|
+
action.tls = { mode: 'passthrough' };
|
|
254
|
+
break;
|
|
255
|
+
case 'https-terminate-to-http':
|
|
256
|
+
action.tls = {
|
|
257
|
+
mode: 'terminate',
|
|
258
|
+
certificate: forwarding.https?.customCert ? {
|
|
259
|
+
key: forwarding.https.customCert.key,
|
|
260
|
+
cert: forwarding.https.customCert.cert
|
|
261
|
+
} : 'auto'
|
|
262
|
+
};
|
|
263
|
+
break;
|
|
264
|
+
case 'https-terminate-to-https':
|
|
265
|
+
action.tls = {
|
|
266
|
+
mode: 'terminate-and-reencrypt',
|
|
267
|
+
certificate: forwarding.https?.customCert ? {
|
|
268
|
+
key: forwarding.https.customCert.key,
|
|
269
|
+
cert: forwarding.https.customCert.cert
|
|
270
|
+
} : 'auto'
|
|
271
|
+
};
|
|
272
|
+
break;
|
|
273
|
+
}
|
|
274
|
+
// Add security settings if present
|
|
275
|
+
if (forwarding.security) {
|
|
276
|
+
action.security = {
|
|
277
|
+
allowedIps: forwarding.security.allowedIps,
|
|
278
|
+
blockedIps: forwarding.security.blockedIps,
|
|
279
|
+
maxConnections: forwarding.security.maxConnections
|
|
280
|
+
};
|
|
281
|
+
}
|
|
282
|
+
// Add advanced settings if present
|
|
283
|
+
if (forwarding.advanced) {
|
|
284
|
+
action.advanced = {
|
|
285
|
+
timeout: forwarding.advanced.timeout,
|
|
286
|
+
headers: forwarding.advanced.headers,
|
|
287
|
+
keepAlive: forwarding.advanced.keepAlive
|
|
288
|
+
};
|
|
289
|
+
}
|
|
290
|
+
// Determine which port to use based on forwarding type
|
|
291
|
+
const defaultPort = forwarding.type.startsWith('https') ? 443 : 80;
|
|
292
|
+
// Add the main route
|
|
293
|
+
routes.push({
|
|
294
|
+
match: {
|
|
295
|
+
ports: defaultPort,
|
|
296
|
+
domains
|
|
297
|
+
},
|
|
298
|
+
action,
|
|
299
|
+
name: `Route for ${domains.join(', ')}`
|
|
300
|
+
});
|
|
301
|
+
// Add HTTP redirect if needed
|
|
302
|
+
if (forwarding.http?.redirectToHttps) {
|
|
303
|
+
routes.push({
|
|
304
|
+
match: {
|
|
305
|
+
ports: 80,
|
|
306
|
+
domains
|
|
307
|
+
},
|
|
308
|
+
action: {
|
|
309
|
+
type: 'redirect',
|
|
310
|
+
redirect: {
|
|
311
|
+
to: 'https://{domain}{path}',
|
|
312
|
+
status: 301
|
|
313
|
+
}
|
|
314
|
+
},
|
|
315
|
+
name: `HTTP Redirect for ${domains.join(', ')}`,
|
|
316
|
+
priority: 100 // Higher priority for redirects
|
|
317
|
+
});
|
|
318
|
+
}
|
|
319
|
+
// Add port ranges if specified
|
|
320
|
+
if (forwarding.advanced?.portRanges) {
|
|
321
|
+
for (const range of forwarding.advanced.portRanges) {
|
|
322
|
+
routes.push({
|
|
323
|
+
match: {
|
|
324
|
+
ports: [{ from: range.from, to: range.to }],
|
|
325
|
+
domains
|
|
326
|
+
},
|
|
327
|
+
action,
|
|
328
|
+
name: `Port Range ${range.from}-${range.to} for ${domains.join(', ')}`
|
|
329
|
+
});
|
|
330
|
+
}
|
|
331
|
+
}
|
|
332
|
+
return routes;
|
|
333
|
+
}
|
|
334
|
+
/**
|
|
335
|
+
* Update routes based on domain configs
|
|
336
|
+
* (For backward compatibility with code that still uses domainConfigs)
|
|
337
|
+
*/
|
|
338
|
+
updateFromDomainConfigs(domainConfigs) {
|
|
339
|
+
const routes = [];
|
|
340
|
+
// Convert each domain config to routes
|
|
341
|
+
for (const config of domainConfigs) {
|
|
342
|
+
routes.push(...this.domainConfigToRoutes(config));
|
|
343
|
+
}
|
|
344
|
+
// Merge with existing routes that aren't derived from domain configs
|
|
345
|
+
const nonDomainRoutes = this.routes.filter(r => !r.name || !r.name.includes('for '));
|
|
346
|
+
this.updateRoutes([...nonDomainRoutes, ...routes]);
|
|
347
|
+
}
|
|
348
|
+
/**
|
|
349
|
+
* Validate the route configuration and return any warnings
|
|
350
|
+
*/
|
|
351
|
+
validateConfiguration() {
|
|
352
|
+
const warnings = [];
|
|
353
|
+
const duplicatePorts = new Map();
|
|
354
|
+
// Check for routes with the same exact match criteria
|
|
355
|
+
for (let i = 0; i < this.routes.length; i++) {
|
|
356
|
+
for (let j = i + 1; j < this.routes.length; j++) {
|
|
357
|
+
const route1 = this.routes[i];
|
|
358
|
+
const route2 = this.routes[j];
|
|
359
|
+
// Check if route match criteria are the same
|
|
360
|
+
if (this.areMatchesSimilar(route1.match, route2.match)) {
|
|
361
|
+
warnings.push(`Routes "${route1.name || i}" and "${route2.name || j}" have similar match criteria. ` +
|
|
362
|
+
`The route with higher priority (${Math.max(route1.priority || 0, route2.priority || 0)}) will be used.`);
|
|
363
|
+
}
|
|
364
|
+
}
|
|
365
|
+
}
|
|
366
|
+
// Check for routes that may never be matched due to priority
|
|
367
|
+
for (let i = 0; i < this.routes.length; i++) {
|
|
368
|
+
const route = this.routes[i];
|
|
369
|
+
const higherPriorityRoutes = this.routes.filter(r => (r.priority || 0) > (route.priority || 0));
|
|
370
|
+
for (const higherRoute of higherPriorityRoutes) {
|
|
371
|
+
if (this.isRouteShadowed(route, higherRoute)) {
|
|
372
|
+
warnings.push(`Route "${route.name || i}" may never be matched because it is shadowed by ` +
|
|
373
|
+
`higher priority route "${higherRoute.name || 'unnamed'}"`);
|
|
374
|
+
break;
|
|
375
|
+
}
|
|
376
|
+
}
|
|
377
|
+
}
|
|
378
|
+
return warnings;
|
|
379
|
+
}
|
|
380
|
+
/**
|
|
381
|
+
* Check if two route matches are similar (potential conflict)
|
|
382
|
+
*/
|
|
383
|
+
areMatchesSimilar(match1, match2) {
|
|
384
|
+
// Check port overlap
|
|
385
|
+
const ports1 = new Set(this.expandPortRange(match1.ports));
|
|
386
|
+
const ports2 = new Set(this.expandPortRange(match2.ports));
|
|
387
|
+
let havePortOverlap = false;
|
|
388
|
+
for (const port of ports1) {
|
|
389
|
+
if (ports2.has(port)) {
|
|
390
|
+
havePortOverlap = true;
|
|
391
|
+
break;
|
|
392
|
+
}
|
|
393
|
+
}
|
|
394
|
+
if (!havePortOverlap) {
|
|
395
|
+
return false;
|
|
396
|
+
}
|
|
397
|
+
// Check domain overlap
|
|
398
|
+
if (match1.domains && match2.domains) {
|
|
399
|
+
const domains1 = Array.isArray(match1.domains) ? match1.domains : [match1.domains];
|
|
400
|
+
const domains2 = Array.isArray(match2.domains) ? match2.domains : [match2.domains];
|
|
401
|
+
// Check if any domain pattern from match1 could match any from match2
|
|
402
|
+
let haveDomainOverlap = false;
|
|
403
|
+
for (const domain1 of domains1) {
|
|
404
|
+
for (const domain2 of domains2) {
|
|
405
|
+
if (domain1 === domain2 ||
|
|
406
|
+
(domain1.includes('*') || domain2.includes('*'))) {
|
|
407
|
+
haveDomainOverlap = true;
|
|
408
|
+
break;
|
|
409
|
+
}
|
|
410
|
+
}
|
|
411
|
+
if (haveDomainOverlap)
|
|
412
|
+
break;
|
|
413
|
+
}
|
|
414
|
+
if (!haveDomainOverlap) {
|
|
415
|
+
return false;
|
|
416
|
+
}
|
|
417
|
+
}
|
|
418
|
+
else if (match1.domains || match2.domains) {
|
|
419
|
+
// One has domains, the other doesn't - they could overlap
|
|
420
|
+
// The one with domains is more specific, so it's not exactly a conflict
|
|
421
|
+
return false;
|
|
422
|
+
}
|
|
423
|
+
// Check path overlap
|
|
424
|
+
if (match1.path && match2.path) {
|
|
425
|
+
// This is a simplified check - in a real implementation,
|
|
426
|
+
// you'd need to check if the path patterns could match the same paths
|
|
427
|
+
return match1.path === match2.path ||
|
|
428
|
+
match1.path.includes('*') ||
|
|
429
|
+
match2.path.includes('*');
|
|
430
|
+
}
|
|
431
|
+
else if (match1.path || match2.path) {
|
|
432
|
+
// One has a path, the other doesn't
|
|
433
|
+
return false;
|
|
434
|
+
}
|
|
435
|
+
// If we get here, the matches have significant overlap
|
|
436
|
+
return true;
|
|
437
|
+
}
|
|
438
|
+
/**
|
|
439
|
+
* Check if a route is completely shadowed by a higher priority route
|
|
440
|
+
*/
|
|
441
|
+
isRouteShadowed(route, higherPriorityRoute) {
|
|
442
|
+
// If they don't have similar match criteria, no shadowing occurs
|
|
443
|
+
if (!this.areMatchesSimilar(route.match, higherPriorityRoute.match)) {
|
|
444
|
+
return false;
|
|
445
|
+
}
|
|
446
|
+
// If higher priority route has more specific criteria, no shadowing
|
|
447
|
+
if (this.isRouteMoreSpecific(higherPriorityRoute.match, route.match)) {
|
|
448
|
+
return false;
|
|
449
|
+
}
|
|
450
|
+
// If higher priority route is equally or less specific but has higher priority,
|
|
451
|
+
// it shadows the lower priority route
|
|
452
|
+
return true;
|
|
453
|
+
}
|
|
454
|
+
/**
|
|
455
|
+
* Check if route1 is more specific than route2
|
|
456
|
+
*/
|
|
457
|
+
isRouteMoreSpecific(match1, match2) {
|
|
458
|
+
// Check if match1 has more specific criteria
|
|
459
|
+
let match1Points = 0;
|
|
460
|
+
let match2Points = 0;
|
|
461
|
+
// Path is the most specific
|
|
462
|
+
if (match1.path)
|
|
463
|
+
match1Points += 3;
|
|
464
|
+
if (match2.path)
|
|
465
|
+
match2Points += 3;
|
|
466
|
+
// Domain is next most specific
|
|
467
|
+
if (match1.domains)
|
|
468
|
+
match1Points += 2;
|
|
469
|
+
if (match2.domains)
|
|
470
|
+
match2Points += 2;
|
|
471
|
+
// Client IP and TLS version are least specific
|
|
472
|
+
if (match1.clientIp)
|
|
473
|
+
match1Points += 1;
|
|
474
|
+
if (match2.clientIp)
|
|
475
|
+
match2Points += 1;
|
|
476
|
+
if (match1.tlsVersion)
|
|
477
|
+
match1Points += 1;
|
|
478
|
+
if (match2.tlsVersion)
|
|
479
|
+
match2Points += 1;
|
|
480
|
+
return match1Points > match2Points;
|
|
481
|
+
}
|
|
482
|
+
}
|
|
483
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicm91dGUtbWFuYWdlci5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3RzL3Byb3hpZXMvc21hcnQtcHJveHkvcm91dGUtbWFuYWdlci50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEtBQUssT0FBTyxNQUFNLGtCQUFrQixDQUFDO0FBWTVDLE9BQU8sRUFDTCxlQUFlLEVBQ2YsZUFBZSxFQUNoQixNQUFNLHdCQUF3QixDQUFDO0FBV2hDOztHQUVHO0FBQ0gsTUFBTSxPQUFPLFlBQWEsU0FBUSxPQUFPLENBQUMsWUFBWTtJQUtwRCxZQUFZLE9BQTJCO1FBQ3JDLEtBQUssRUFBRSxDQUFDO1FBTEYsV0FBTSxHQUFtQixFQUFFLENBQUM7UUFDNUIsWUFBTyxHQUFnQyxJQUFJLEdBQUcsRUFBRSxDQUFDO1FBTXZELG1FQUFtRTtRQUNuRSxJQUFJLENBQUMsT0FBTyxHQUFHLE9BQU8sQ0FBQztRQUV2Qix1Q0FBdUM7UUFDdkMsSUFBSSxDQUFDLFlBQVksQ0FBQyxJQUFJLENBQUMsT0FBTyxDQUFDLE1BQU0sQ0FBQyxDQUFDO0lBQ3pDLENBQUM7SUFFRDs7T0FFRztJQUNJLFlBQVksQ0FBQyxTQUF5QixFQUFFO1FBQzdDLHlDQUF5QztRQUN6QyxJQUFJLENBQUMsTUFBTSxHQUFHLENBQUMsR0FBRyxDQUFDLE1BQU0sSUFBSSxFQUFFLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLEVBQUUsRUFBRTtZQUM5QyxNQUFNLFNBQVMsR0FBRyxDQUFDLENBQUMsUUFBUSxJQUFJLENBQUMsQ0FBQztZQUNsQyxNQUFNLFNBQVMsR0FBRyxDQUFDLENBQUMsUUFBUSxJQUFJLENBQUMsQ0FBQztZQUNsQyxPQUFPLFNBQVMsR0FBRyxTQUFTLENBQUM7UUFDL0IsQ0FBQyxDQUFDLENBQUM7UUFFSCx3Q0FBd0M7UUFDeEMsSUFBSSxDQUFDLGNBQWMsRUFBRSxDQUFDO0lBQ3hCLENBQUM7SUFFRDs7T0FFRztJ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
|
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
import * as plugins from '../../plugins.js';
|
|
2
|
-
import { DomainConfigManager } from './domain-config-manager.js';
|
|
3
2
|
import type { ISmartProxyOptions, IDomainConfig } from './models/interfaces.js';
|
|
4
|
-
|
|
3
|
+
import type { IRouteConfig } from './models/route-types.js';
|
|
5
4
|
/**
|
|
6
|
-
* SmartProxy -
|
|
5
|
+
* SmartProxy - Unified route-based API
|
|
7
6
|
*/
|
|
8
7
|
export declare class SmartProxy extends plugins.EventEmitter {
|
|
9
8
|
private netServers;
|
|
@@ -11,17 +10,21 @@ export declare class SmartProxy extends plugins.EventEmitter {
|
|
|
11
10
|
private isShuttingDown;
|
|
12
11
|
private connectionManager;
|
|
13
12
|
private securityManager;
|
|
14
|
-
domainConfigManager
|
|
13
|
+
private domainConfigManager;
|
|
15
14
|
private tlsManager;
|
|
16
15
|
private networkProxyBridge;
|
|
17
16
|
private timeoutManager;
|
|
18
17
|
private portRangeManager;
|
|
19
|
-
private
|
|
18
|
+
private routeManager;
|
|
19
|
+
private routeConnectionHandler;
|
|
20
20
|
private port80Handler;
|
|
21
21
|
private certProvisioner?;
|
|
22
|
+
/**
|
|
23
|
+
* Constructor that supports both legacy and route-based configuration
|
|
24
|
+
*/
|
|
22
25
|
constructor(settingsArg: ISmartProxyOptions);
|
|
23
26
|
/**
|
|
24
|
-
* The settings for the
|
|
27
|
+
* The settings for the SmartProxy
|
|
25
28
|
*/
|
|
26
29
|
settings: ISmartProxyOptions;
|
|
27
30
|
/**
|
|
@@ -29,17 +32,25 @@ export declare class SmartProxy extends plugins.EventEmitter {
|
|
|
29
32
|
*/
|
|
30
33
|
private initializePort80Handler;
|
|
31
34
|
/**
|
|
32
|
-
* Start the proxy server
|
|
35
|
+
* Start the proxy server with support for both configuration types
|
|
33
36
|
*/
|
|
34
37
|
start(): Promise<void>;
|
|
38
|
+
/**
|
|
39
|
+
* Extract domain configurations from routes for certificate provisioning
|
|
40
|
+
*/
|
|
41
|
+
private extractDomainConfigsFromRoutes;
|
|
35
42
|
/**
|
|
36
43
|
* Stop the proxy server
|
|
37
44
|
*/
|
|
38
45
|
stop(): Promise<void>;
|
|
39
46
|
/**
|
|
40
|
-
* Updates the domain configurations for the proxy
|
|
47
|
+
* Updates the domain configurations for the proxy (legacy support)
|
|
41
48
|
*/
|
|
42
49
|
updateDomainConfigs(newDomainConfigs: IDomainConfig[]): Promise<void>;
|
|
50
|
+
/**
|
|
51
|
+
* Update routes with new configuration (new API)
|
|
52
|
+
*/
|
|
53
|
+
updateRoutes(newRoutes: IRouteConfig[]): Promise<void>;
|
|
43
54
|
/**
|
|
44
55
|
* Request a certificate for a specific domain
|
|
45
56
|
*/
|