@push.rocks/smartproxy 19.3.10 → 19.3.12
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/core/utils/index.d.ts +1 -0
- package/dist_ts/core/utils/index.js +2 -1
- package/dist_ts/core/utils/logger.d.ts +2 -0
- package/dist_ts/core/utils/logger.js +8 -0
- package/dist_ts/plugins.d.ts +3 -1
- package/dist_ts/plugins.js +4 -2
- package/dist_ts/proxies/smart-proxy/certificate-manager.js +26 -25
- package/dist_ts/proxies/smart-proxy/connection-manager.js +90 -27
- package/dist_ts/proxies/smart-proxy/route-connection-handler.js +269 -67
- package/dist_ts/proxies/smart-proxy/smart-proxy.js +42 -27
- package/package.json +2 -1
- package/ts/00_commitinfo_data.ts +1 -1
- package/ts/core/utils/index.ts +1 -0
- package/ts/core/utils/logger.ts +10 -0
- package/ts/plugins.ts +4 -0
- package/ts/proxies/smart-proxy/certificate-manager.ts +25 -24
- package/ts/proxies/smart-proxy/connection-manager.ts +95 -48
- package/ts/proxies/smart-proxy/route-connection-handler.ts +286 -139
- package/ts/proxies/smart-proxy/smart-proxy.ts +41 -28
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import * as plugins from '../../plugins.js';
|
|
2
|
+
import { logger } from '../../core/utils/logger.js';
|
|
2
3
|
|
|
3
4
|
// Importing required components
|
|
4
5
|
import { ConnectionManager } from './connection-manager.js';
|
|
@@ -239,7 +240,7 @@ export class SmartProxy extends plugins.EventEmitter {
|
|
|
239
240
|
);
|
|
240
241
|
|
|
241
242
|
if (autoRoutes.length === 0 && !this.hasStaticCertRoutes()) {
|
|
242
|
-
|
|
243
|
+
logger.log('info', 'No routes require certificate management', { component: 'certificate-manager' });
|
|
243
244
|
return;
|
|
244
245
|
}
|
|
245
246
|
|
|
@@ -256,7 +257,7 @@ export class SmartProxy extends plugins.EventEmitter {
|
|
|
256
257
|
useProduction: this.settings.acme.useProduction || false,
|
|
257
258
|
port: this.settings.acme.port || 80
|
|
258
259
|
};
|
|
259
|
-
|
|
260
|
+
logger.log('info', `Using top-level ACME configuration with email: ${acmeOptions.email}`, { component: 'certificate-manager' });
|
|
260
261
|
} else if (autoRoutes.length > 0) {
|
|
261
262
|
// Check for route-level ACME config
|
|
262
263
|
const routeWithAcme = autoRoutes.find(r => r.action.tls?.acme?.email);
|
|
@@ -267,7 +268,7 @@ export class SmartProxy extends plugins.EventEmitter {
|
|
|
267
268
|
useProduction: routeAcme.useProduction || false,
|
|
268
269
|
port: routeAcme.challengePort || 80
|
|
269
270
|
};
|
|
270
|
-
|
|
271
|
+
logger.log('info', `Using route-level ACME configuration from route '${routeWithAcme.name}' with email: ${acmeOptions.email}`, { component: 'certificate-manager' });
|
|
271
272
|
}
|
|
272
273
|
}
|
|
273
274
|
|
|
@@ -305,7 +306,7 @@ export class SmartProxy extends plugins.EventEmitter {
|
|
|
305
306
|
public async start() {
|
|
306
307
|
// Don't start if already shutting down
|
|
307
308
|
if (this.isShuttingDown) {
|
|
308
|
-
|
|
309
|
+
logger.log('warn', "Cannot start SmartProxy while it's in the shutdown process");
|
|
309
310
|
return;
|
|
310
311
|
}
|
|
311
312
|
|
|
@@ -332,9 +333,9 @@ export class SmartProxy extends plugins.EventEmitter {
|
|
|
332
333
|
const allWarnings = [...configWarnings, ...acmeWarnings];
|
|
333
334
|
|
|
334
335
|
if (allWarnings.length > 0) {
|
|
335
|
-
|
|
336
|
+
logger.log('warn', `${allWarnings.length} configuration warnings found`, { count: allWarnings.length });
|
|
336
337
|
for (const warning of allWarnings) {
|
|
337
|
-
|
|
338
|
+
logger.log('warn', `${warning}`);
|
|
338
339
|
}
|
|
339
340
|
}
|
|
340
341
|
|
|
@@ -353,7 +354,7 @@ export class SmartProxy extends plugins.EventEmitter {
|
|
|
353
354
|
|
|
354
355
|
// Now that ports are listening, provision any required certificates
|
|
355
356
|
if (this.certManager) {
|
|
356
|
-
|
|
357
|
+
logger.log('info', 'Starting certificate provisioning now that ports are ready', { component: 'certificate-manager' });
|
|
357
358
|
await this.certManager.provisionAllCertificates();
|
|
358
359
|
}
|
|
359
360
|
|
|
@@ -411,16 +412,26 @@ export class SmartProxy extends plugins.EventEmitter {
|
|
|
411
412
|
const terminationStats = this.connectionManager.getTerminationStats();
|
|
412
413
|
|
|
413
414
|
// Log detailed stats
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
415
|
+
logger.log('info', 'Connection statistics', {
|
|
416
|
+
activeConnections: connectionRecords.size,
|
|
417
|
+
tls: {
|
|
418
|
+
total: tlsConnections,
|
|
419
|
+
completed: completedTlsHandshakes,
|
|
420
|
+
pending: pendingTlsHandshakes
|
|
421
|
+
},
|
|
422
|
+
nonTls: nonTlsConnections,
|
|
423
|
+
keepAlive: keepAliveConnections,
|
|
424
|
+
httpProxy: httpProxyConnections,
|
|
425
|
+
longestRunning: {
|
|
426
|
+
incoming: plugins.prettyMs(maxIncoming),
|
|
427
|
+
outgoing: plugins.prettyMs(maxOutgoing)
|
|
428
|
+
},
|
|
429
|
+
terminationStats: {
|
|
430
|
+
incoming: terminationStats.incoming,
|
|
431
|
+
outgoing: terminationStats.outgoing
|
|
432
|
+
},
|
|
433
|
+
component: 'connection-manager'
|
|
434
|
+
});
|
|
424
435
|
}, this.settings.inactivityCheckInterval || 60000);
|
|
425
436
|
|
|
426
437
|
// Make sure the interval doesn't keep the process alive
|
|
@@ -439,19 +450,19 @@ export class SmartProxy extends plugins.EventEmitter {
|
|
|
439
450
|
* Stop the proxy server
|
|
440
451
|
*/
|
|
441
452
|
public async stop() {
|
|
442
|
-
|
|
453
|
+
logger.log('info', 'SmartProxy shutting down...');
|
|
443
454
|
this.isShuttingDown = true;
|
|
444
455
|
this.portManager.setShuttingDown(true);
|
|
445
456
|
|
|
446
457
|
// Stop certificate manager
|
|
447
458
|
if (this.certManager) {
|
|
448
459
|
await this.certManager.stop();
|
|
449
|
-
|
|
460
|
+
logger.log('info', 'Certificate manager stopped');
|
|
450
461
|
}
|
|
451
462
|
|
|
452
463
|
// Stop NFTablesManager
|
|
453
464
|
await this.nftablesManager.stop();
|
|
454
|
-
|
|
465
|
+
logger.log('info', 'NFTablesManager stopped');
|
|
455
466
|
|
|
456
467
|
// Stop the connection logger
|
|
457
468
|
if (this.connectionLogger) {
|
|
@@ -461,7 +472,7 @@ export class SmartProxy extends plugins.EventEmitter {
|
|
|
461
472
|
|
|
462
473
|
// Stop all port listeners
|
|
463
474
|
await this.portManager.closeAll();
|
|
464
|
-
|
|
475
|
+
logger.log('info', 'All servers closed. Cleaning up active connections...');
|
|
465
476
|
|
|
466
477
|
// Clean up all active connections
|
|
467
478
|
this.connectionManager.clearConnections();
|
|
@@ -472,7 +483,7 @@ export class SmartProxy extends plugins.EventEmitter {
|
|
|
472
483
|
// Clear ACME state manager
|
|
473
484
|
this.acmeStateManager.clear();
|
|
474
485
|
|
|
475
|
-
|
|
486
|
+
logger.log('info', 'SmartProxy shutdown complete.');
|
|
476
487
|
}
|
|
477
488
|
|
|
478
489
|
/**
|
|
@@ -481,7 +492,7 @@ export class SmartProxy extends plugins.EventEmitter {
|
|
|
481
492
|
* Note: This legacy method has been removed. Use updateRoutes instead.
|
|
482
493
|
*/
|
|
483
494
|
public async updateDomainConfigs(): Promise<void> {
|
|
484
|
-
|
|
495
|
+
logger.log('warn', 'Method updateDomainConfigs() is deprecated. Use updateRoutes() instead.');
|
|
485
496
|
throw new Error('updateDomainConfigs() is deprecated - use updateRoutes() instead');
|
|
486
497
|
}
|
|
487
498
|
|
|
@@ -497,7 +508,7 @@ export class SmartProxy extends plugins.EventEmitter {
|
|
|
497
508
|
const challengeRouteExists = this.settings.routes.some(r => r.name === 'acme-challenge');
|
|
498
509
|
|
|
499
510
|
if (!challengeRouteExists) {
|
|
500
|
-
|
|
511
|
+
logger.log('info', 'Challenge route successfully removed from routes');
|
|
501
512
|
return;
|
|
502
513
|
}
|
|
503
514
|
|
|
@@ -505,7 +516,9 @@ export class SmartProxy extends plugins.EventEmitter {
|
|
|
505
516
|
await plugins.smartdelay.delayFor(retryDelay);
|
|
506
517
|
}
|
|
507
518
|
|
|
508
|
-
|
|
519
|
+
const error = `Failed to verify challenge route removal after ${maxRetries} attempts`;
|
|
520
|
+
logger.log('error', error);
|
|
521
|
+
throw new Error(error);
|
|
509
522
|
}
|
|
510
523
|
|
|
511
524
|
/**
|
|
@@ -533,7 +546,7 @@ export class SmartProxy extends plugins.EventEmitter {
|
|
|
533
546
|
*/
|
|
534
547
|
public async updateRoutes(newRoutes: IRouteConfig[]): Promise<void> {
|
|
535
548
|
return this.routeUpdateLock.runExclusive(async () => {
|
|
536
|
-
|
|
549
|
+
logger.log('info', `Updating routes (${newRoutes.length} routes)`, { routeCount: newRoutes.length, component: 'route-manager' });
|
|
537
550
|
|
|
538
551
|
// Get existing routes that use NFTables
|
|
539
552
|
const oldNfTablesRoutes = this.settings.routes.filter(
|
|
@@ -658,14 +671,14 @@ export class SmartProxy extends plugins.EventEmitter {
|
|
|
658
671
|
|
|
659
672
|
// Check for wildcard domains (they can't get ACME certs)
|
|
660
673
|
if (domain.includes('*')) {
|
|
661
|
-
|
|
674
|
+
logger.log('warn', `Wildcard domains like "${domain}" are not supported for automatic ACME certificates`, { domain, component: 'certificate-manager' });
|
|
662
675
|
return false;
|
|
663
676
|
}
|
|
664
677
|
|
|
665
678
|
// Check if domain has at least one dot and no invalid characters
|
|
666
679
|
const validDomainRegex = /^[a-zA-Z0-9]([a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(\.[a-zA-Z0-9]([a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$/;
|
|
667
680
|
if (!validDomainRegex.test(domain)) {
|
|
668
|
-
|
|
681
|
+
logger.log('warn', `Domain "${domain}" has invalid format for certificate issuance`, { domain, component: 'certificate-manager' });
|
|
669
682
|
return false;
|
|
670
683
|
}
|
|
671
684
|
|