@push.rocks/smartproxy 3.41.8 → 4.1.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.
Files changed (43) hide show
  1. package/dist_ts/00_commitinfo_data.js +2 -2
  2. package/dist_ts/classes.pp.acmemanager.d.ts +34 -0
  3. package/dist_ts/classes.pp.acmemanager.js +123 -0
  4. package/dist_ts/classes.pp.connectionhandler.d.ts +39 -0
  5. package/dist_ts/classes.pp.connectionhandler.js +693 -0
  6. package/dist_ts/classes.pp.connectionmanager.d.ts +78 -0
  7. package/dist_ts/classes.pp.connectionmanager.js +378 -0
  8. package/dist_ts/classes.pp.domainconfigmanager.d.ts +55 -0
  9. package/dist_ts/classes.pp.domainconfigmanager.js +103 -0
  10. package/dist_ts/classes.pp.interfaces.d.ts +109 -0
  11. package/dist_ts/classes.pp.interfaces.js +2 -0
  12. package/dist_ts/classes.pp.networkproxybridge.d.ts +43 -0
  13. package/dist_ts/classes.pp.networkproxybridge.js +211 -0
  14. package/dist_ts/classes.pp.portproxy.d.ts +48 -0
  15. package/dist_ts/classes.pp.portproxy.js +268 -0
  16. package/dist_ts/classes.pp.portrangemanager.d.ts +56 -0
  17. package/dist_ts/classes.pp.portrangemanager.js +179 -0
  18. package/dist_ts/classes.pp.securitymanager.d.ts +47 -0
  19. package/dist_ts/classes.pp.securitymanager.js +126 -0
  20. package/dist_ts/classes.pp.snihandler.d.ts +198 -0
  21. package/dist_ts/classes.pp.snihandler.js +1210 -0
  22. package/dist_ts/classes.pp.timeoutmanager.d.ts +47 -0
  23. package/dist_ts/classes.pp.timeoutmanager.js +154 -0
  24. package/dist_ts/classes.pp.tlsmanager.d.ts +57 -0
  25. package/dist_ts/classes.pp.tlsmanager.js +132 -0
  26. package/dist_ts/index.d.ts +2 -2
  27. package/dist_ts/index.js +3 -3
  28. package/package.json +1 -1
  29. package/ts/00_commitinfo_data.ts +1 -1
  30. package/ts/classes.pp.acmemanager.ts +149 -0
  31. package/ts/classes.pp.connectionhandler.ts +982 -0
  32. package/ts/classes.pp.connectionmanager.ts +446 -0
  33. package/ts/classes.pp.domainconfigmanager.ts +123 -0
  34. package/ts/classes.pp.interfaces.ts +136 -0
  35. package/ts/classes.pp.networkproxybridge.ts +258 -0
  36. package/ts/classes.pp.portproxy.ts +344 -0
  37. package/ts/classes.pp.portrangemanager.ts +214 -0
  38. package/ts/classes.pp.securitymanager.ts +147 -0
  39. package/ts/{classes.snihandler.ts → classes.pp.snihandler.ts} +1 -1
  40. package/ts/classes.pp.timeoutmanager.ts +190 -0
  41. package/ts/classes.pp.tlsmanager.ts +206 -0
  42. package/ts/index.ts +2 -2
  43. package/ts/classes.portproxy.ts +0 -2503
@@ -0,0 +1,258 @@
1
+ import * as plugins from './plugins.js';
2
+ import { NetworkProxy } from './classes.networkproxy.js';
3
+ import type { IConnectionRecord, IPortProxySettings, IDomainConfig } from './classes.pp.interfaces.js';
4
+
5
+ /**
6
+ * Manages NetworkProxy integration for TLS termination
7
+ */
8
+ export class NetworkProxyBridge {
9
+ private networkProxy: NetworkProxy | null = null;
10
+
11
+ constructor(private settings: IPortProxySettings) {}
12
+
13
+ /**
14
+ * Initialize NetworkProxy instance
15
+ */
16
+ public async initialize(): Promise<void> {
17
+ if (!this.networkProxy && this.settings.useNetworkProxy && this.settings.useNetworkProxy.length > 0) {
18
+ // Configure NetworkProxy options based on PortProxy settings
19
+ const networkProxyOptions: any = {
20
+ port: this.settings.networkProxyPort!,
21
+ portProxyIntegration: true,
22
+ logLevel: this.settings.enableDetailedLogging ? 'debug' : 'info',
23
+ };
24
+
25
+ // Add ACME settings if configured
26
+ if (this.settings.acme) {
27
+ networkProxyOptions.acme = { ...this.settings.acme };
28
+ }
29
+
30
+ this.networkProxy = new NetworkProxy(networkProxyOptions);
31
+
32
+ console.log(`Initialized NetworkProxy on port ${this.settings.networkProxyPort}`);
33
+
34
+ // Convert and apply domain configurations to NetworkProxy
35
+ await this.syncDomainConfigsToNetworkProxy();
36
+ }
37
+ }
38
+
39
+ /**
40
+ * Get the NetworkProxy instance
41
+ */
42
+ public getNetworkProxy(): NetworkProxy | null {
43
+ return this.networkProxy;
44
+ }
45
+
46
+ /**
47
+ * Get the NetworkProxy port
48
+ */
49
+ public getNetworkProxyPort(): number {
50
+ return this.networkProxy ? this.networkProxy.getListeningPort() : this.settings.networkProxyPort || 8443;
51
+ }
52
+
53
+ /**
54
+ * Start NetworkProxy
55
+ */
56
+ public async start(): Promise<void> {
57
+ if (this.networkProxy) {
58
+ await this.networkProxy.start();
59
+ console.log(`NetworkProxy started on port ${this.settings.networkProxyPort}`);
60
+
61
+ // Log ACME status
62
+ if (this.settings.acme?.enabled) {
63
+ console.log(
64
+ `ACME certificate management is enabled (${
65
+ this.settings.acme.useProduction ? 'Production' : 'Staging'
66
+ } mode)`
67
+ );
68
+ console.log(`ACME HTTP challenge server on port ${this.settings.acme.port}`);
69
+
70
+ // Register domains for ACME certificates if enabled
71
+ if (this.networkProxy.options.acme?.enabled) {
72
+ console.log('Registering domains with ACME certificate manager...');
73
+ // The NetworkProxy will handle this internally via registerDomainsWithAcmeManager()
74
+ }
75
+ }
76
+ }
77
+ }
78
+
79
+ /**
80
+ * Stop NetworkProxy
81
+ */
82
+ public async stop(): Promise<void> {
83
+ if (this.networkProxy) {
84
+ try {
85
+ console.log('Stopping NetworkProxy...');
86
+ await this.networkProxy.stop();
87
+ console.log('NetworkProxy stopped successfully');
88
+
89
+ // Log ACME shutdown if it was enabled
90
+ if (this.settings.acme?.enabled) {
91
+ console.log('ACME certificate manager stopped');
92
+ }
93
+ } catch (err) {
94
+ console.log(`Error stopping NetworkProxy: ${err}`);
95
+ }
96
+ }
97
+ }
98
+
99
+ /**
100
+ * Forwards a TLS connection to a NetworkProxy for handling
101
+ */
102
+ public forwardToNetworkProxy(
103
+ connectionId: string,
104
+ socket: plugins.net.Socket,
105
+ record: IConnectionRecord,
106
+ initialData: Buffer,
107
+ customProxyPort?: number,
108
+ onError?: (reason: string) => void
109
+ ): void {
110
+ // Ensure NetworkProxy is initialized
111
+ if (!this.networkProxy) {
112
+ console.log(
113
+ `[${connectionId}] NetworkProxy not initialized. Cannot forward connection.`
114
+ );
115
+ if (onError) {
116
+ onError('network_proxy_not_initialized');
117
+ }
118
+ return;
119
+ }
120
+
121
+ // Use the custom port if provided, otherwise use the default NetworkProxy port
122
+ const proxyPort = customProxyPort || this.networkProxy.getListeningPort();
123
+ const proxyHost = 'localhost'; // Assuming NetworkProxy runs locally
124
+
125
+ if (this.settings.enableDetailedLogging) {
126
+ console.log(
127
+ `[${connectionId}] Forwarding TLS connection to NetworkProxy at ${proxyHost}:${proxyPort}`
128
+ );
129
+ }
130
+
131
+ // Create a connection to the NetworkProxy
132
+ const proxySocket = plugins.net.connect({
133
+ host: proxyHost,
134
+ port: proxyPort,
135
+ });
136
+
137
+ // Store the outgoing socket in the record
138
+ record.outgoing = proxySocket;
139
+ record.outgoingStartTime = Date.now();
140
+ record.usingNetworkProxy = true;
141
+
142
+ // Set up error handlers
143
+ proxySocket.on('error', (err) => {
144
+ console.log(`[${connectionId}] Error connecting to NetworkProxy: ${err.message}`);
145
+ if (onError) {
146
+ onError('network_proxy_connect_error');
147
+ }
148
+ });
149
+
150
+ // Handle connection to NetworkProxy
151
+ proxySocket.on('connect', () => {
152
+ if (this.settings.enableDetailedLogging) {
153
+ console.log(`[${connectionId}] Connected to NetworkProxy at ${proxyHost}:${proxyPort}`);
154
+ }
155
+
156
+ // First send the initial data that contains the TLS ClientHello
157
+ proxySocket.write(initialData);
158
+
159
+ // Now set up bidirectional piping between client and NetworkProxy
160
+ socket.pipe(proxySocket);
161
+ proxySocket.pipe(socket);
162
+
163
+ // Update activity on data transfer (caller should handle this)
164
+ if (this.settings.enableDetailedLogging) {
165
+ console.log(`[${connectionId}] TLS connection successfully forwarded to NetworkProxy`);
166
+ }
167
+ });
168
+ }
169
+
170
+ /**
171
+ * Synchronizes domain configurations to NetworkProxy
172
+ */
173
+ public async syncDomainConfigsToNetworkProxy(): Promise<void> {
174
+ if (!this.networkProxy) {
175
+ console.log('Cannot sync configurations - NetworkProxy not initialized');
176
+ return;
177
+ }
178
+
179
+ try {
180
+ // Get SSL certificates from assets
181
+ // Import fs directly since it's not in plugins
182
+ const fs = await import('fs');
183
+
184
+ let certPair;
185
+ try {
186
+ certPair = {
187
+ key: fs.readFileSync('assets/certs/key.pem', 'utf8'),
188
+ cert: fs.readFileSync('assets/certs/cert.pem', 'utf8'),
189
+ };
190
+ } catch (certError) {
191
+ console.log(`Warning: Could not read default certificates: ${certError}`);
192
+ console.log(
193
+ 'Using empty certificate placeholders - ACME will generate proper certificates if enabled'
194
+ );
195
+
196
+ // Use empty placeholders - NetworkProxy will use its internal defaults
197
+ // or ACME will generate proper ones if enabled
198
+ certPair = {
199
+ key: '',
200
+ cert: '',
201
+ };
202
+ }
203
+
204
+ // Convert domain configs to NetworkProxy configs
205
+ const proxyConfigs = this.networkProxy.convertPortProxyConfigs(
206
+ this.settings.domainConfigs,
207
+ certPair
208
+ );
209
+
210
+ // Log ACME-eligible domains if ACME is enabled
211
+ if (this.settings.acme?.enabled) {
212
+ const acmeEligibleDomains = proxyConfigs
213
+ .filter((config) => !config.hostName.includes('*')) // Exclude wildcards
214
+ .map((config) => config.hostName);
215
+
216
+ if (acmeEligibleDomains.length > 0) {
217
+ console.log(`Domains eligible for ACME certificates: ${acmeEligibleDomains.join(', ')}`);
218
+ } else {
219
+ console.log('No domains eligible for ACME certificates found in configuration');
220
+ }
221
+ }
222
+
223
+ // Update NetworkProxy with the converted configs
224
+ await this.networkProxy.updateProxyConfigs(proxyConfigs);
225
+ console.log(`Successfully synchronized ${proxyConfigs.length} domain configurations to NetworkProxy`);
226
+ } catch (err) {
227
+ console.log(`Failed to sync configurations: ${err}`);
228
+ }
229
+ }
230
+
231
+ /**
232
+ * Request a certificate for a specific domain
233
+ */
234
+ public async requestCertificate(domain: string): Promise<boolean> {
235
+ if (!this.networkProxy) {
236
+ console.log('Cannot request certificate - NetworkProxy not initialized');
237
+ return false;
238
+ }
239
+
240
+ if (!this.settings.acme?.enabled) {
241
+ console.log('Cannot request certificate - ACME is not enabled');
242
+ return false;
243
+ }
244
+
245
+ try {
246
+ const result = await this.networkProxy.requestCertificate(domain);
247
+ if (result) {
248
+ console.log(`Certificate request for ${domain} submitted successfully`);
249
+ } else {
250
+ console.log(`Certificate request for ${domain} failed`);
251
+ }
252
+ return result;
253
+ } catch (err) {
254
+ console.log(`Error requesting certificate: ${err}`);
255
+ return false;
256
+ }
257
+ }
258
+ }
@@ -0,0 +1,344 @@
1
+ import * as plugins from './plugins.js';
2
+ import type { IPortProxySettings, IDomainConfig } from './classes.pp.interfaces.js';
3
+ import { ConnectionManager } from './classes.pp.connectionmanager.js';
4
+ import { SecurityManager } from './classes.pp.securitymanager.js';
5
+ import { DomainConfigManager } from './classes.pp.domainconfigmanager.js';
6
+ import { TlsManager } from './classes.pp.tlsmanager.js';
7
+ import { NetworkProxyBridge } from './classes.pp.networkproxybridge.js';
8
+ import { TimeoutManager } from './classes.pp.timeoutmanager.js';
9
+ import { AcmeManager } from './classes.pp.acmemanager.js';
10
+ import { PortRangeManager } from './classes.pp.portrangemanager.js';
11
+ import { ConnectionHandler } from './classes.pp.connectionhandler.js';
12
+
13
+ /**
14
+ * PortProxy - Main class that coordinates all components
15
+ */
16
+ export class PortProxy {
17
+ private netServers: plugins.net.Server[] = [];
18
+ private connectionLogger: NodeJS.Timeout | null = null;
19
+ private isShuttingDown: boolean = false;
20
+
21
+ // Component managers
22
+ private connectionManager: ConnectionManager;
23
+ private securityManager: SecurityManager;
24
+ public domainConfigManager: DomainConfigManager;
25
+ private tlsManager: TlsManager;
26
+ private networkProxyBridge: NetworkProxyBridge;
27
+ private timeoutManager: TimeoutManager;
28
+ private acmeManager: AcmeManager;
29
+ private portRangeManager: PortRangeManager;
30
+ private connectionHandler: ConnectionHandler;
31
+
32
+ constructor(settingsArg: IPortProxySettings) {
33
+ // Set reasonable defaults for all settings
34
+ this.settings = {
35
+ ...settingsArg,
36
+ targetIP: settingsArg.targetIP || 'localhost',
37
+ initialDataTimeout: settingsArg.initialDataTimeout || 120000,
38
+ socketTimeout: settingsArg.socketTimeout || 3600000,
39
+ inactivityCheckInterval: settingsArg.inactivityCheckInterval || 60000,
40
+ maxConnectionLifetime: settingsArg.maxConnectionLifetime || 86400000,
41
+ inactivityTimeout: settingsArg.inactivityTimeout || 14400000,
42
+ gracefulShutdownTimeout: settingsArg.gracefulShutdownTimeout || 30000,
43
+ noDelay: settingsArg.noDelay !== undefined ? settingsArg.noDelay : true,
44
+ keepAlive: settingsArg.keepAlive !== undefined ? settingsArg.keepAlive : true,
45
+ keepAliveInitialDelay: settingsArg.keepAliveInitialDelay || 10000,
46
+ maxPendingDataSize: settingsArg.maxPendingDataSize || 10 * 1024 * 1024,
47
+ disableInactivityCheck: settingsArg.disableInactivityCheck || false,
48
+ enableKeepAliveProbes:
49
+ settingsArg.enableKeepAliveProbes !== undefined ? settingsArg.enableKeepAliveProbes : true,
50
+ enableDetailedLogging: settingsArg.enableDetailedLogging || false,
51
+ enableTlsDebugLogging: settingsArg.enableTlsDebugLogging || false,
52
+ enableRandomizedTimeouts: settingsArg.enableRandomizedTimeouts || false,
53
+ allowSessionTicket:
54
+ settingsArg.allowSessionTicket !== undefined ? settingsArg.allowSessionTicket : true,
55
+ maxConnectionsPerIP: settingsArg.maxConnectionsPerIP || 100,
56
+ connectionRateLimitPerMinute: settingsArg.connectionRateLimitPerMinute || 300,
57
+ keepAliveTreatment: settingsArg.keepAliveTreatment || 'extended',
58
+ keepAliveInactivityMultiplier: settingsArg.keepAliveInactivityMultiplier || 6,
59
+ extendedKeepAliveLifetime: settingsArg.extendedKeepAliveLifetime || 7 * 24 * 60 * 60 * 1000,
60
+ networkProxyPort: settingsArg.networkProxyPort || 8443,
61
+ acme: settingsArg.acme || {
62
+ enabled: false,
63
+ port: 80,
64
+ contactEmail: 'admin@example.com',
65
+ useProduction: false,
66
+ renewThresholdDays: 30,
67
+ autoRenew: true,
68
+ certificateStore: './certs',
69
+ skipConfiguredCerts: false,
70
+ },
71
+ };
72
+
73
+ // Initialize component managers
74
+ this.timeoutManager = new TimeoutManager(this.settings);
75
+ this.securityManager = new SecurityManager(this.settings);
76
+ this.connectionManager = new ConnectionManager(
77
+ this.settings,
78
+ this.securityManager,
79
+ this.timeoutManager
80
+ );
81
+ this.domainConfigManager = new DomainConfigManager(this.settings);
82
+ this.tlsManager = new TlsManager(this.settings);
83
+ this.networkProxyBridge = new NetworkProxyBridge(this.settings);
84
+ this.portRangeManager = new PortRangeManager(this.settings);
85
+ this.acmeManager = new AcmeManager(this.settings, this.networkProxyBridge);
86
+
87
+ // Initialize connection handler
88
+ this.connectionHandler = new ConnectionHandler(
89
+ this.settings,
90
+ this.connectionManager,
91
+ this.securityManager,
92
+ this.domainConfigManager,
93
+ this.tlsManager,
94
+ this.networkProxyBridge,
95
+ this.timeoutManager,
96
+ this.portRangeManager
97
+ );
98
+ }
99
+
100
+ /**
101
+ * The settings for the port proxy
102
+ */
103
+ public settings: IPortProxySettings;
104
+
105
+ /**
106
+ * Start the proxy server
107
+ */
108
+ public async start() {
109
+ // Don't start if already shutting down
110
+ if (this.isShuttingDown) {
111
+ console.log("Cannot start PortProxy while it's shutting down");
112
+ return;
113
+ }
114
+
115
+ // Initialize and start NetworkProxy if needed
116
+ if (
117
+ this.settings.useNetworkProxy &&
118
+ this.settings.useNetworkProxy.length > 0
119
+ ) {
120
+ await this.networkProxyBridge.initialize();
121
+ await this.networkProxyBridge.start();
122
+ }
123
+
124
+ // Validate port configuration
125
+ const configWarnings = this.portRangeManager.validateConfiguration();
126
+ if (configWarnings.length > 0) {
127
+ console.log("Port configuration warnings:");
128
+ for (const warning of configWarnings) {
129
+ console.log(` - ${warning}`);
130
+ }
131
+ }
132
+
133
+ // Get listening ports from PortRangeManager
134
+ const listeningPorts = this.portRangeManager.getListeningPorts();
135
+
136
+ // Create servers for each port
137
+ for (const port of listeningPorts) {
138
+ const server = plugins.net.createServer((socket) => {
139
+ // Check if shutting down
140
+ if (this.isShuttingDown) {
141
+ socket.end();
142
+ socket.destroy();
143
+ return;
144
+ }
145
+
146
+ // Delegate to connection handler
147
+ this.connectionHandler.handleConnection(socket);
148
+ }).on('error', (err: Error) => {
149
+ console.log(`Server Error on port ${port}: ${err.message}`);
150
+ });
151
+
152
+ server.listen(port, () => {
153
+ const isNetworkProxyPort = this.settings.useNetworkProxy?.includes(port);
154
+ console.log(
155
+ `PortProxy -> OK: Now listening on port ${port}${
156
+ this.settings.sniEnabled && !isNetworkProxyPort ? ' (SNI passthrough enabled)' : ''
157
+ }${isNetworkProxyPort ? ' (NetworkProxy forwarding enabled)' : ''}`
158
+ );
159
+ });
160
+
161
+ this.netServers.push(server);
162
+ }
163
+
164
+ // Set up periodic connection logging and inactivity checks
165
+ this.connectionLogger = setInterval(() => {
166
+ // Immediately return if shutting down
167
+ if (this.isShuttingDown) return;
168
+
169
+ // Perform inactivity check
170
+ this.connectionManager.performInactivityCheck();
171
+
172
+ // Log connection statistics
173
+ const now = Date.now();
174
+ let maxIncoming = 0;
175
+ let maxOutgoing = 0;
176
+ let tlsConnections = 0;
177
+ let nonTlsConnections = 0;
178
+ let completedTlsHandshakes = 0;
179
+ let pendingTlsHandshakes = 0;
180
+ let keepAliveConnections = 0;
181
+ let networkProxyConnections = 0;
182
+
183
+ // Get connection records for analysis
184
+ const connectionRecords = this.connectionManager.getConnections();
185
+
186
+ // Analyze active connections
187
+ for (const record of connectionRecords.values()) {
188
+ // Track connection stats
189
+ if (record.isTLS) {
190
+ tlsConnections++;
191
+ if (record.tlsHandshakeComplete) {
192
+ completedTlsHandshakes++;
193
+ } else {
194
+ pendingTlsHandshakes++;
195
+ }
196
+ } else {
197
+ nonTlsConnections++;
198
+ }
199
+
200
+ if (record.hasKeepAlive) {
201
+ keepAliveConnections++;
202
+ }
203
+
204
+ if (record.usingNetworkProxy) {
205
+ networkProxyConnections++;
206
+ }
207
+
208
+ maxIncoming = Math.max(maxIncoming, now - record.incomingStartTime);
209
+ if (record.outgoingStartTime) {
210
+ maxOutgoing = Math.max(maxOutgoing, now - record.outgoingStartTime);
211
+ }
212
+ }
213
+
214
+ // Get termination stats
215
+ const terminationStats = this.connectionManager.getTerminationStats();
216
+
217
+ // Log detailed stats
218
+ console.log(
219
+ `Active connections: ${connectionRecords.size}. ` +
220
+ `Types: TLS=${tlsConnections} (Completed=${completedTlsHandshakes}, Pending=${pendingTlsHandshakes}), ` +
221
+ `Non-TLS=${nonTlsConnections}, KeepAlive=${keepAliveConnections}, NetworkProxy=${networkProxyConnections}. ` +
222
+ `Longest running: IN=${plugins.prettyMs(maxIncoming)}, OUT=${plugins.prettyMs(maxOutgoing)}. ` +
223
+ `Termination stats: ${JSON.stringify({
224
+ IN: terminationStats.incoming,
225
+ OUT: terminationStats.outgoing,
226
+ })}`
227
+ );
228
+ }, this.settings.inactivityCheckInterval || 60000);
229
+
230
+ // Make sure the interval doesn't keep the process alive
231
+ if (this.connectionLogger.unref) {
232
+ this.connectionLogger.unref();
233
+ }
234
+ }
235
+
236
+ /**
237
+ * Stop the proxy server
238
+ */
239
+ public async stop() {
240
+ console.log('PortProxy shutting down...');
241
+ this.isShuttingDown = true;
242
+
243
+ // Stop accepting new connections
244
+ const closeServerPromises: Promise<void>[] = this.netServers.map(
245
+ (server) =>
246
+ new Promise<void>((resolve) => {
247
+ if (!server.listening) {
248
+ resolve();
249
+ return;
250
+ }
251
+ server.close((err) => {
252
+ if (err) {
253
+ console.log(`Error closing server: ${err.message}`);
254
+ }
255
+ resolve();
256
+ });
257
+ })
258
+ );
259
+
260
+ // Stop the connection logger
261
+ if (this.connectionLogger) {
262
+ clearInterval(this.connectionLogger);
263
+ this.connectionLogger = null;
264
+ }
265
+
266
+ // Wait for servers to close
267
+ await Promise.all(closeServerPromises);
268
+ console.log('All servers closed. Cleaning up active connections...');
269
+
270
+ // Clean up all active connections
271
+ this.connectionManager.clearConnections();
272
+
273
+ // Stop NetworkProxy
274
+ await this.networkProxyBridge.stop();
275
+
276
+ // Clear all servers
277
+ this.netServers = [];
278
+
279
+ console.log('PortProxy shutdown complete.');
280
+ }
281
+
282
+ /**
283
+ * Updates the domain configurations for the proxy
284
+ */
285
+ public async updateDomainConfigs(newDomainConfigs: IDomainConfig[]): Promise<void> {
286
+ console.log(`Updating domain configurations (${newDomainConfigs.length} configs)`);
287
+
288
+ // Update domain configs in DomainConfigManager
289
+ this.domainConfigManager.updateDomainConfigs(newDomainConfigs);
290
+
291
+ // If NetworkProxy is initialized, resync the configurations
292
+ if (this.networkProxyBridge.getNetworkProxy()) {
293
+ await this.networkProxyBridge.syncDomainConfigsToNetworkProxy();
294
+ }
295
+ }
296
+
297
+ /**
298
+ * Updates the ACME certificate settings
299
+ */
300
+ public async updateAcmeSettings(acmeSettings: IPortProxySettings['acme']): Promise<void> {
301
+ console.log('Updating ACME certificate settings');
302
+
303
+ // Delegate to AcmeManager
304
+ await this.acmeManager.updateAcmeSettings(acmeSettings);
305
+ }
306
+
307
+ /**
308
+ * Requests a certificate for a specific domain
309
+ */
310
+ public async requestCertificate(domain: string): Promise<boolean> {
311
+ // Delegate to AcmeManager
312
+ return this.acmeManager.requestCertificate(domain);
313
+ }
314
+
315
+ /**
316
+ * Get statistics about current connections
317
+ */
318
+ public getStatistics(): any {
319
+ const connectionRecords = this.connectionManager.getConnections();
320
+ const terminationStats = this.connectionManager.getTerminationStats();
321
+
322
+ let tlsConnections = 0;
323
+ let nonTlsConnections = 0;
324
+ let keepAliveConnections = 0;
325
+ let networkProxyConnections = 0;
326
+
327
+ // Analyze active connections
328
+ for (const record of connectionRecords.values()) {
329
+ if (record.isTLS) tlsConnections++;
330
+ else nonTlsConnections++;
331
+ if (record.hasKeepAlive) keepAliveConnections++;
332
+ if (record.usingNetworkProxy) networkProxyConnections++;
333
+ }
334
+
335
+ return {
336
+ activeConnections: connectionRecords.size,
337
+ tlsConnections,
338
+ nonTlsConnections,
339
+ keepAliveConnections,
340
+ networkProxyConnections,
341
+ terminationStats
342
+ };
343
+ }
344
+ }