@push.rocks/smartproxy 21.1.3 → 21.1.5

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.
Files changed (38) hide show
  1. package/changelog.md +23 -0
  2. package/dist_ts/00_commitinfo_data.js +2 -2
  3. package/dist_ts/core/models/socket-augmentation.d.ts +3 -0
  4. package/dist_ts/core/models/socket-augmentation.js +1 -1
  5. package/dist_ts/core/utils/socket-tracker.d.ts +16 -0
  6. package/dist_ts/core/utils/socket-tracker.js +49 -0
  7. package/dist_ts/detection/detectors/http-detector.js +14 -2
  8. package/dist_ts/detection/protocol-detector.js +2 -1
  9. package/dist_ts/proxies/http-proxy/http-proxy.d.ts +5 -1
  10. package/dist_ts/proxies/http-proxy/http-proxy.js +63 -39
  11. package/dist_ts/proxies/smart-proxy/certificate-manager.d.ts +5 -0
  12. package/dist_ts/proxies/smart-proxy/certificate-manager.js +20 -6
  13. package/dist_ts/proxies/smart-proxy/index.d.ts +1 -0
  14. package/dist_ts/proxies/smart-proxy/index.js +2 -1
  15. package/dist_ts/proxies/smart-proxy/metrics-collector.d.ts +4 -0
  16. package/dist_ts/proxies/smart-proxy/metrics-collector.js +52 -7
  17. package/dist_ts/proxies/smart-proxy/route-orchestrator.d.ts +56 -0
  18. package/dist_ts/proxies/smart-proxy/route-orchestrator.js +204 -0
  19. package/dist_ts/proxies/smart-proxy/smart-proxy.d.ts +1 -11
  20. package/dist_ts/proxies/smart-proxy/smart-proxy.js +48 -237
  21. package/dist_ts/proxies/smart-proxy/utils/route-helpers.js +42 -7
  22. package/dist_ts/proxies/smart-proxy/utils/route-validator.d.ts +58 -0
  23. package/dist_ts/proxies/smart-proxy/utils/route-validator.js +405 -0
  24. package/package.json +3 -2
  25. package/readme.md +321 -828
  26. package/ts/00_commitinfo_data.ts +1 -1
  27. package/ts/core/models/socket-augmentation.ts +5 -0
  28. package/ts/core/utils/socket-tracker.ts +63 -0
  29. package/ts/detection/detectors/http-detector.ts +14 -1
  30. package/ts/detection/protocol-detector.ts +1 -0
  31. package/ts/proxies/http-proxy/http-proxy.ts +73 -48
  32. package/ts/proxies/smart-proxy/certificate-manager.ts +21 -5
  33. package/ts/proxies/smart-proxy/index.ts +1 -0
  34. package/ts/proxies/smart-proxy/metrics-collector.ts +58 -6
  35. package/ts/proxies/smart-proxy/route-orchestrator.ts +297 -0
  36. package/ts/proxies/smart-proxy/smart-proxy.ts +66 -270
  37. package/ts/proxies/smart-proxy/utils/route-helpers.ts +45 -6
  38. package/ts/proxies/smart-proxy/utils/route-validator.ts +453 -0
@@ -0,0 +1,204 @@
1
+ import { logger } from '../../core/utils/logger.js';
2
+ import { RouteValidator } from './utils/route-validator.js';
3
+ import { Mutex } from './utils/mutex.js';
4
+ /**
5
+ * Orchestrates route updates and coordination between components
6
+ * Extracted from SmartProxy to reduce class complexity
7
+ */
8
+ export class RouteOrchestrator {
9
+ constructor(portManager, routeManager, httpProxyBridge, nftablesManager, certManager, logger) {
10
+ this.certManager = null;
11
+ this.portManager = portManager;
12
+ this.routeManager = routeManager;
13
+ this.httpProxyBridge = httpProxyBridge;
14
+ this.nftablesManager = nftablesManager;
15
+ this.certManager = certManager;
16
+ this.logger = logger;
17
+ this.routeUpdateLock = new Mutex();
18
+ }
19
+ /**
20
+ * Set or update certificate manager reference
21
+ */
22
+ setCertManager(certManager) {
23
+ this.certManager = certManager;
24
+ }
25
+ /**
26
+ * Get certificate manager reference
27
+ */
28
+ getCertManager() {
29
+ return this.certManager;
30
+ }
31
+ /**
32
+ * Update routes with validation and coordination
33
+ */
34
+ async updateRoutes(oldRoutes, newRoutes, options = {}) {
35
+ return this.routeUpdateLock.runExclusive(async () => {
36
+ // Validate route configurations
37
+ const validation = RouteValidator.validateRoutes(newRoutes);
38
+ if (!validation.valid) {
39
+ RouteValidator.logValidationErrors(validation.errors);
40
+ throw new Error(`Route validation failed: ${validation.errors.size} route(s) have errors`);
41
+ }
42
+ // Track port usage before and after updates
43
+ const oldPortUsage = this.updatePortUsageMap(oldRoutes);
44
+ const newPortUsage = this.updatePortUsageMap(newRoutes);
45
+ // Get the lists of currently listening ports and new ports needed
46
+ const currentPorts = new Set(this.portManager.getListeningPorts());
47
+ const newPortsSet = new Set(newPortUsage.keys());
48
+ // Log the port usage for debugging
49
+ this.logger.debug(`Current listening ports: ${Array.from(currentPorts).join(', ')}`);
50
+ this.logger.debug(`Ports needed for new routes: ${Array.from(newPortsSet).join(', ')}`);
51
+ // Find orphaned ports - ports that no longer have any routes
52
+ const orphanedPorts = this.findOrphanedPorts(oldPortUsage, newPortUsage);
53
+ // Find new ports that need binding (only ports that we aren't already listening on)
54
+ const newBindingPorts = Array.from(newPortsSet).filter(p => !currentPorts.has(p));
55
+ // Check for ACME challenge port to give it special handling
56
+ const acmePort = options.acmePort || 80;
57
+ const acmePortNeeded = newPortsSet.has(acmePort);
58
+ const acmePortListed = newBindingPorts.includes(acmePort);
59
+ if (acmePortNeeded && acmePortListed) {
60
+ this.logger.info(`Adding ACME challenge port ${acmePort} to routes`);
61
+ }
62
+ // Update NFTables routes
63
+ await this.updateNfTablesRoutes(oldRoutes, newRoutes);
64
+ // Update routes in RouteManager
65
+ this.routeManager.updateRoutes(newRoutes);
66
+ // Release orphaned ports first to free resources
67
+ if (orphanedPorts.length > 0) {
68
+ this.logger.info(`Releasing ${orphanedPorts.length} orphaned ports: ${orphanedPorts.join(', ')}`);
69
+ await this.portManager.removePorts(orphanedPorts);
70
+ }
71
+ // Add new ports if needed
72
+ if (newBindingPorts.length > 0) {
73
+ this.logger.info(`Binding to ${newBindingPorts.length} new ports: ${newBindingPorts.join(', ')}`);
74
+ // Handle port binding with improved error recovery
75
+ try {
76
+ await this.portManager.addPorts(newBindingPorts);
77
+ }
78
+ catch (error) {
79
+ // Special handling for port binding errors
80
+ if (error.code === 'EADDRINUSE') {
81
+ const port = error.port || newBindingPorts[0];
82
+ const isAcmePort = port === acmePort;
83
+ if (isAcmePort) {
84
+ this.logger.warn(`Could not bind to ACME challenge port ${port}. It may be in use by another application.`);
85
+ // Re-throw with more helpful message
86
+ throw new Error(`ACME challenge port ${port} is already in use by another application. ` +
87
+ `Configure a different port in settings.acme.port (e.g., 8080) or free up port ${port}.`);
88
+ }
89
+ }
90
+ // Re-throw the original error for other cases
91
+ throw error;
92
+ }
93
+ }
94
+ // If HttpProxy is initialized, resync the configurations
95
+ if (this.httpProxyBridge.getHttpProxy()) {
96
+ await this.httpProxyBridge.syncRoutesToHttpProxy(newRoutes);
97
+ }
98
+ // Update certificate manager if needed
99
+ let newCertManager;
100
+ let newChallengeRouteActive = options.globalChallengeRouteActive || false;
101
+ if (this.certManager && options.createCertificateManager) {
102
+ const existingAcmeOptions = this.certManager.getAcmeOptions();
103
+ const existingState = this.certManager.getState();
104
+ // Store global state before stopping
105
+ newChallengeRouteActive = existingState.challengeRouteActive;
106
+ // Keep certificate manager routes in sync before stopping
107
+ this.certManager.setRoutes(newRoutes);
108
+ await this.certManager.stop();
109
+ // Verify the challenge route has been properly removed
110
+ if (options.verifyChallengeRouteRemoved) {
111
+ await options.verifyChallengeRouteRemoved();
112
+ }
113
+ // Create new certificate manager with preserved state
114
+ newCertManager = await options.createCertificateManager(newRoutes, './certs', existingAcmeOptions, { challengeRouteActive: newChallengeRouteActive });
115
+ this.certManager = newCertManager;
116
+ }
117
+ return {
118
+ portUsageMap: newPortUsage,
119
+ newChallengeRouteActive,
120
+ newCertManager
121
+ };
122
+ });
123
+ }
124
+ /**
125
+ * Update port usage map based on the provided routes
126
+ */
127
+ updatePortUsageMap(routes) {
128
+ const portUsage = new Map();
129
+ for (const route of routes) {
130
+ // Get the ports for this route
131
+ const portsConfig = Array.isArray(route.match.ports)
132
+ ? route.match.ports
133
+ : [route.match.ports];
134
+ // Expand port range objects to individual port numbers
135
+ const expandedPorts = [];
136
+ for (const portConfig of portsConfig) {
137
+ if (typeof portConfig === 'number') {
138
+ expandedPorts.push(portConfig);
139
+ }
140
+ else if (typeof portConfig === 'object' && 'from' in portConfig && 'to' in portConfig) {
141
+ // Expand the port range
142
+ for (let p = portConfig.from; p <= portConfig.to; p++) {
143
+ expandedPorts.push(p);
144
+ }
145
+ }
146
+ }
147
+ // Use route name if available, otherwise generate a unique ID
148
+ const routeName = route.name || `unnamed_${Math.random().toString(36).substring(2, 9)}`;
149
+ // Add each port to the usage map
150
+ for (const port of expandedPorts) {
151
+ if (!portUsage.has(port)) {
152
+ portUsage.set(port, new Set());
153
+ }
154
+ portUsage.get(port).add(routeName);
155
+ }
156
+ }
157
+ // Log port usage for debugging
158
+ for (const [port, routes] of portUsage.entries()) {
159
+ this.logger.debug(`Port ${port} is used by ${routes.size} routes: ${Array.from(routes).join(', ')}`);
160
+ }
161
+ return portUsage;
162
+ }
163
+ /**
164
+ * Find ports that have no routes in the new configuration
165
+ */
166
+ findOrphanedPorts(oldUsage, newUsage) {
167
+ const orphanedPorts = [];
168
+ for (const [port, routes] of oldUsage.entries()) {
169
+ if (!newUsage.has(port) || newUsage.get(port).size === 0) {
170
+ orphanedPorts.push(port);
171
+ }
172
+ }
173
+ return orphanedPorts;
174
+ }
175
+ /**
176
+ * Update NFTables routes
177
+ */
178
+ async updateNfTablesRoutes(oldRoutes, newRoutes) {
179
+ // Get existing routes that use NFTables and update them
180
+ const oldNfTablesRoutes = oldRoutes.filter(r => r.action.forwardingEngine === 'nftables');
181
+ const newNfTablesRoutes = newRoutes.filter(r => r.action.forwardingEngine === 'nftables');
182
+ // Update existing NFTables routes
183
+ for (const oldRoute of oldNfTablesRoutes) {
184
+ const newRoute = newNfTablesRoutes.find(r => r.name === oldRoute.name);
185
+ if (!newRoute) {
186
+ // Route was removed
187
+ await this.nftablesManager.deprovisionRoute(oldRoute);
188
+ }
189
+ else {
190
+ // Route was updated
191
+ await this.nftablesManager.updateRoute(oldRoute, newRoute);
192
+ }
193
+ }
194
+ // Add new NFTables routes
195
+ for (const newRoute of newNfTablesRoutes) {
196
+ const oldRoute = oldNfTablesRoutes.find(r => r.name === newRoute.name);
197
+ if (!oldRoute) {
198
+ // New route
199
+ await this.nftablesManager.provisionRoute(newRoute);
200
+ }
201
+ }
202
+ }
203
+ }
204
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicm91dGUtb3JjaGVzdHJhdG9yLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vdHMvcHJveGllcy9zbWFydC1wcm94eS9yb3V0ZS1vcmNoZXN0cmF0b3IudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLE1BQU0sRUFBRSxNQUFNLDRCQUE0QixDQUFDO0FBR3BELE9BQU8sRUFBRSxjQUFjLEVBQUUsTUFBTSw0QkFBNEIsQ0FBQztBQUM1RCxPQUFPLEVBQUUsS0FBSyxFQUFFLE1BQU0sa0JBQWtCLENBQUM7QUFPekM7OztHQUdHO0FBQ0gsTUFBTSxPQUFPLGlCQUFpQjtJQVM1QixZQUNFLFdBQXdCLEVBQ3hCLFlBQTBCLEVBQzFCLGVBQWdDLEVBQ2hDLGVBQWdDLEVBQ2hDLFdBQW9DLEVBQ3BDLE1BQWU7UUFUVCxnQkFBVyxHQUE0QixJQUFJLENBQUM7UUFXbEQsSUFBSSxDQUFDLFdBQVcsR0FBRyxXQUFXLENBQUM7UUFDL0IsSUFBSSxDQUFDLFlBQVksR0FBRyxZQUFZLENBQUM7UUFDakMsSUFBSSxDQUFDLGVBQWUsR0FBRyxlQUFlLENBQUM7UUFDdkMsSUFBSSxDQUFDLGVBQWUsR0FBRyxlQUFlLENBQUM7UUFDdkMsSUFBSSxDQUFDLFdBQVcsR0FBRyxXQUFXLENBQUM7UUFDL0IsSUFBSSxDQUFDLE1BQU0sR0FBRyxNQUFNLENBQUM7UUFDckIsSUFBSSxDQUFDLGVBQWUsR0FBRyxJQUFJLEtBQUssRUFBRSxDQUFDO0lBQ3JDLENBQUM7SUFFRDs7T0FFRztJQUNJLGNBQWMsQ0FBQyxXQUFvQztRQUN4RCxJQUFJLENBQUMsV0FBVyxHQUFHLFdBQVcsQ0FBQztJQUNqQyxDQUFDO0lBRUQ7O09BRUc7SUFDSSxjQUFjO1FBQ25CLE9BQU8sSUFBSSxDQUFDLFdBQVcsQ0FBQztJQUMxQixDQUFDO0lBRUQ7O09BRUc7SUFDSSxLQUFLLENBQUMsWUFBWSxDQUN2QixTQUF5QixFQUN6QixTQUF5QixFQUN6QixVQVlJLEVB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
@@ -43,6 +43,7 @@ export declare class SmartProxy extends plugins.EventEmitter {
43
43
  private routeUpdateLock;
44
44
  acmeStateManager: AcmeStateManager;
45
45
  metricsCollector: MetricsCollector;
46
+ private routeOrchestrator;
46
47
  private portUsageMap;
47
48
  /**
48
49
  * Constructor for SmartProxy
@@ -144,17 +145,6 @@ export declare class SmartProxy extends plugins.EventEmitter {
144
145
  * Manually provision a certificate for a route
145
146
  */
146
147
  provisionCertificate(routeName: string): Promise<void>;
147
- /**
148
- * Update the port usage map based on the provided routes
149
- *
150
- * This tracks which ports are used by which routes, allowing us to
151
- * detect when a port is no longer needed and can be released.
152
- */
153
- private updatePortUsageMap;
154
- /**
155
- * Find ports that have no routes in the new configuration
156
- */
157
- private findOrphanedPorts;
158
148
  /**
159
149
  * Force renewal of a certificate
160
150
  */