@push.rocks/smartproxy 19.3.9 → 19.3.11
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 +2 -2
- 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/http-proxy/handlers/static-handler.d.ts +1 -1
- package/dist_ts/proxies/http-proxy/handlers/static-handler.js +11 -3
- package/dist_ts/proxies/smart-proxy/certificate-manager.d.ts +1 -1
- package/dist_ts/proxies/smart-proxy/certificate-manager.js +28 -26
- package/dist_ts/proxies/smart-proxy/connection-manager.js +90 -27
- package/dist_ts/proxies/smart-proxy/route-connection-handler.js +272 -70
- package/dist_ts/proxies/smart-proxy/smart-proxy.js +46 -26
- package/package.json +2 -1
- package/readme.hints.md +24 -1
- package/readme.md +8 -2
- 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/http-proxy/handlers/static-handler.ts +12 -2
- package/ts/proxies/smart-proxy/certificate-manager.ts +28 -26
- package/ts/proxies/smart-proxy/connection-manager.ts +95 -48
- package/ts/proxies/smart-proxy/route-connection-handler.ts +290 -142
- package/ts/proxies/smart-proxy/smart-proxy.ts +46 -27
|
@@ -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
|
|
|
@@ -350,6 +351,12 @@ export class SmartProxy extends plugins.EventEmitter {
|
|
|
350
351
|
|
|
351
352
|
// Start port listeners using the PortManager
|
|
352
353
|
await this.portManager.addPorts(listeningPorts);
|
|
354
|
+
|
|
355
|
+
// Now that ports are listening, provision any required certificates
|
|
356
|
+
if (this.certManager) {
|
|
357
|
+
logger.log('info', 'Starting certificate provisioning now that ports are ready', { component: 'certificate-manager' });
|
|
358
|
+
await this.certManager.provisionAllCertificates();
|
|
359
|
+
}
|
|
353
360
|
|
|
354
361
|
// Set up periodic connection logging and inactivity checks
|
|
355
362
|
this.connectionLogger = setInterval(() => {
|
|
@@ -405,16 +412,26 @@ export class SmartProxy extends plugins.EventEmitter {
|
|
|
405
412
|
const terminationStats = this.connectionManager.getTerminationStats();
|
|
406
413
|
|
|
407
414
|
// Log detailed stats
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
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
|
+
});
|
|
418
435
|
}, this.settings.inactivityCheckInterval || 60000);
|
|
419
436
|
|
|
420
437
|
// Make sure the interval doesn't keep the process alive
|
|
@@ -433,19 +450,19 @@ export class SmartProxy extends plugins.EventEmitter {
|
|
|
433
450
|
* Stop the proxy server
|
|
434
451
|
*/
|
|
435
452
|
public async stop() {
|
|
436
|
-
|
|
453
|
+
logger.log('info', 'SmartProxy shutting down...');
|
|
437
454
|
this.isShuttingDown = true;
|
|
438
455
|
this.portManager.setShuttingDown(true);
|
|
439
456
|
|
|
440
457
|
// Stop certificate manager
|
|
441
458
|
if (this.certManager) {
|
|
442
459
|
await this.certManager.stop();
|
|
443
|
-
|
|
460
|
+
logger.log('info', 'Certificate manager stopped');
|
|
444
461
|
}
|
|
445
462
|
|
|
446
463
|
// Stop NFTablesManager
|
|
447
464
|
await this.nftablesManager.stop();
|
|
448
|
-
|
|
465
|
+
logger.log('info', 'NFTablesManager stopped');
|
|
449
466
|
|
|
450
467
|
// Stop the connection logger
|
|
451
468
|
if (this.connectionLogger) {
|
|
@@ -455,7 +472,7 @@ export class SmartProxy extends plugins.EventEmitter {
|
|
|
455
472
|
|
|
456
473
|
// Stop all port listeners
|
|
457
474
|
await this.portManager.closeAll();
|
|
458
|
-
|
|
475
|
+
logger.log('info', 'All servers closed. Cleaning up active connections...');
|
|
459
476
|
|
|
460
477
|
// Clean up all active connections
|
|
461
478
|
this.connectionManager.clearConnections();
|
|
@@ -466,7 +483,7 @@ export class SmartProxy extends plugins.EventEmitter {
|
|
|
466
483
|
// Clear ACME state manager
|
|
467
484
|
this.acmeStateManager.clear();
|
|
468
485
|
|
|
469
|
-
|
|
486
|
+
logger.log('info', 'SmartProxy shutdown complete.');
|
|
470
487
|
}
|
|
471
488
|
|
|
472
489
|
/**
|
|
@@ -475,7 +492,7 @@ export class SmartProxy extends plugins.EventEmitter {
|
|
|
475
492
|
* Note: This legacy method has been removed. Use updateRoutes instead.
|
|
476
493
|
*/
|
|
477
494
|
public async updateDomainConfigs(): Promise<void> {
|
|
478
|
-
|
|
495
|
+
logger.log('warn', 'Method updateDomainConfigs() is deprecated. Use updateRoutes() instead.');
|
|
479
496
|
throw new Error('updateDomainConfigs() is deprecated - use updateRoutes() instead');
|
|
480
497
|
}
|
|
481
498
|
|
|
@@ -491,7 +508,7 @@ export class SmartProxy extends plugins.EventEmitter {
|
|
|
491
508
|
const challengeRouteExists = this.settings.routes.some(r => r.name === 'acme-challenge');
|
|
492
509
|
|
|
493
510
|
if (!challengeRouteExists) {
|
|
494
|
-
|
|
511
|
+
logger.log('info', 'Challenge route successfully removed from routes');
|
|
495
512
|
return;
|
|
496
513
|
}
|
|
497
514
|
|
|
@@ -499,7 +516,9 @@ export class SmartProxy extends plugins.EventEmitter {
|
|
|
499
516
|
await plugins.smartdelay.delayFor(retryDelay);
|
|
500
517
|
}
|
|
501
518
|
|
|
502
|
-
|
|
519
|
+
const error = `Failed to verify challenge route removal after ${maxRetries} attempts`;
|
|
520
|
+
logger.log('error', error);
|
|
521
|
+
throw new Error(error);
|
|
503
522
|
}
|
|
504
523
|
|
|
505
524
|
/**
|
|
@@ -527,7 +546,7 @@ export class SmartProxy extends plugins.EventEmitter {
|
|
|
527
546
|
*/
|
|
528
547
|
public async updateRoutes(newRoutes: IRouteConfig[]): Promise<void> {
|
|
529
548
|
return this.routeUpdateLock.runExclusive(async () => {
|
|
530
|
-
|
|
549
|
+
logger.log('info', `Updating routes (${newRoutes.length} routes)`, { routeCount: newRoutes.length, component: 'route-manager' });
|
|
531
550
|
|
|
532
551
|
// Get existing routes that use NFTables
|
|
533
552
|
const oldNfTablesRoutes = this.settings.routes.filter(
|
|
@@ -652,14 +671,14 @@ export class SmartProxy extends plugins.EventEmitter {
|
|
|
652
671
|
|
|
653
672
|
// Check for wildcard domains (they can't get ACME certs)
|
|
654
673
|
if (domain.includes('*')) {
|
|
655
|
-
|
|
674
|
+
logger.log('warn', `Wildcard domains like "${domain}" are not supported for automatic ACME certificates`, { domain, component: 'certificate-manager' });
|
|
656
675
|
return false;
|
|
657
676
|
}
|
|
658
677
|
|
|
659
678
|
// Check if domain has at least one dot and no invalid characters
|
|
660
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])?)*$/;
|
|
661
680
|
if (!validDomainRegex.test(domain)) {
|
|
662
|
-
|
|
681
|
+
logger.log('warn', `Domain "${domain}" has invalid format for certificate issuance`, { domain, component: 'certificate-manager' });
|
|
663
682
|
return false;
|
|
664
683
|
}
|
|
665
684
|
|