@push.rocks/smartproxy 3.34.0 → 3.37.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/classes.networkproxy.d.ts +85 -0
- package/dist_ts/classes.networkproxy.js +385 -6
- package/dist_ts/classes.portproxy.d.ts +31 -0
- package/dist_ts/classes.portproxy.js +183 -5
- package/package.json +5 -5
- package/ts/00_commitinfo_data.ts +2 -2
- package/ts/classes.networkproxy.ts +461 -6
- package/ts/classes.portproxy.ts +219 -5
package/ts/classes.portproxy.ts
CHANGED
|
@@ -56,9 +56,21 @@ export interface IPortProxySettings extends plugins.tls.TlsOptions {
|
|
|
56
56
|
keepAliveInactivityMultiplier?: number; // Multiplier for inactivity timeout for keep-alive connections
|
|
57
57
|
extendedKeepAliveLifetime?: number; // Extended lifetime for keep-alive connections (ms)
|
|
58
58
|
|
|
59
|
-
//
|
|
59
|
+
// NetworkProxy integration
|
|
60
60
|
useNetworkProxy?: number[]; // Array of ports to forward to NetworkProxy
|
|
61
61
|
networkProxyPort?: number; // Port where NetworkProxy is listening (default: 8443)
|
|
62
|
+
|
|
63
|
+
// ACME certificate management options
|
|
64
|
+
acme?: {
|
|
65
|
+
enabled?: boolean; // Whether to enable automatic certificate management
|
|
66
|
+
port?: number; // Port to listen on for ACME challenges (default: 80)
|
|
67
|
+
contactEmail?: string; // Email for Let's Encrypt account
|
|
68
|
+
useProduction?: boolean; // Whether to use Let's Encrypt production (default: false for staging)
|
|
69
|
+
renewThresholdDays?: number; // Days before expiry to renew certificates (default: 30)
|
|
70
|
+
autoRenew?: boolean; // Whether to automatically renew certificates (default: true)
|
|
71
|
+
certificateStore?: string; // Directory to store certificates (default: ./certs)
|
|
72
|
+
skipConfiguredCerts?: boolean; // Skip domains that already have certificates configured
|
|
73
|
+
};
|
|
62
74
|
}
|
|
63
75
|
|
|
64
76
|
/**
|
|
@@ -418,6 +430,18 @@ export class PortProxy {
|
|
|
418
430
|
|
|
419
431
|
// NetworkProxy settings
|
|
420
432
|
networkProxyPort: settingsArg.networkProxyPort || 8443, // Default NetworkProxy port
|
|
433
|
+
|
|
434
|
+
// ACME certificate settings with reasonable defaults
|
|
435
|
+
acme: settingsArg.acme || {
|
|
436
|
+
enabled: false,
|
|
437
|
+
port: 80,
|
|
438
|
+
contactEmail: 'admin@example.com',
|
|
439
|
+
useProduction: false,
|
|
440
|
+
renewThresholdDays: 30,
|
|
441
|
+
autoRenew: true,
|
|
442
|
+
certificateStore: './certs',
|
|
443
|
+
skipConfiguredCerts: false
|
|
444
|
+
}
|
|
421
445
|
};
|
|
422
446
|
|
|
423
447
|
// Initialize NetworkProxy if enabled
|
|
@@ -429,15 +453,182 @@ export class PortProxy {
|
|
|
429
453
|
/**
|
|
430
454
|
* Initialize NetworkProxy instance
|
|
431
455
|
*/
|
|
432
|
-
private initializeNetworkProxy(): void {
|
|
456
|
+
private async initializeNetworkProxy(): Promise<void> {
|
|
433
457
|
if (!this.networkProxy) {
|
|
434
|
-
|
|
458
|
+
// Configure NetworkProxy options based on PortProxy settings
|
|
459
|
+
const networkProxyOptions: any = {
|
|
435
460
|
port: this.settings.networkProxyPort!,
|
|
436
461
|
portProxyIntegration: true,
|
|
437
462
|
logLevel: this.settings.enableDetailedLogging ? 'debug' : 'info'
|
|
438
|
-
}
|
|
463
|
+
};
|
|
464
|
+
|
|
465
|
+
// Add ACME settings if configured
|
|
466
|
+
if (this.settings.acme) {
|
|
467
|
+
networkProxyOptions.acme = { ...this.settings.acme };
|
|
468
|
+
}
|
|
469
|
+
|
|
470
|
+
this.networkProxy = new NetworkProxy(networkProxyOptions);
|
|
439
471
|
|
|
440
472
|
console.log(`Initialized NetworkProxy on port ${this.settings.networkProxyPort}`);
|
|
473
|
+
|
|
474
|
+
// Convert and apply domain configurations to NetworkProxy
|
|
475
|
+
await this.syncDomainConfigsToNetworkProxy();
|
|
476
|
+
}
|
|
477
|
+
}
|
|
478
|
+
|
|
479
|
+
/**
|
|
480
|
+
* Updates the domain configurations for the proxy
|
|
481
|
+
* @param newDomainConfigs The new domain configurations
|
|
482
|
+
*/
|
|
483
|
+
public async updateDomainConfigs(newDomainConfigs: IDomainConfig[]): Promise<void> {
|
|
484
|
+
console.log(`Updating domain configurations (${newDomainConfigs.length} configs)`);
|
|
485
|
+
this.settings.domainConfigs = newDomainConfigs;
|
|
486
|
+
|
|
487
|
+
// If NetworkProxy is initialized, resync the configurations
|
|
488
|
+
if (this.networkProxy) {
|
|
489
|
+
await this.syncDomainConfigsToNetworkProxy();
|
|
490
|
+
}
|
|
491
|
+
}
|
|
492
|
+
|
|
493
|
+
/**
|
|
494
|
+
* Updates the ACME certificate settings
|
|
495
|
+
* @param acmeSettings New ACME settings
|
|
496
|
+
*/
|
|
497
|
+
public async updateAcmeSettings(acmeSettings: IPortProxySettings['acme']): Promise<void> {
|
|
498
|
+
console.log('Updating ACME certificate settings');
|
|
499
|
+
|
|
500
|
+
// Update settings
|
|
501
|
+
this.settings.acme = {
|
|
502
|
+
...this.settings.acme,
|
|
503
|
+
...acmeSettings
|
|
504
|
+
};
|
|
505
|
+
|
|
506
|
+
// If NetworkProxy is initialized, update its ACME settings
|
|
507
|
+
if (this.networkProxy) {
|
|
508
|
+
try {
|
|
509
|
+
// Recreate NetworkProxy with new settings if ACME enabled state has changed
|
|
510
|
+
if (this.settings.acme.enabled !== acmeSettings.enabled) {
|
|
511
|
+
console.log(`ACME enabled state changed to: ${acmeSettings.enabled}`);
|
|
512
|
+
|
|
513
|
+
// Stop the current NetworkProxy
|
|
514
|
+
await this.networkProxy.stop();
|
|
515
|
+
this.networkProxy = null;
|
|
516
|
+
|
|
517
|
+
// Reinitialize with new settings
|
|
518
|
+
await this.initializeNetworkProxy();
|
|
519
|
+
|
|
520
|
+
// Use start() to make sure ACME gets initialized if newly enabled
|
|
521
|
+
await this.networkProxy.start();
|
|
522
|
+
} else {
|
|
523
|
+
// Update existing NetworkProxy with new settings
|
|
524
|
+
// Note: Some settings may require a restart to take effect
|
|
525
|
+
console.log('Updating ACME settings in NetworkProxy');
|
|
526
|
+
|
|
527
|
+
// For certificate renewals, we might want to trigger checks with the new settings
|
|
528
|
+
if (acmeSettings.renewThresholdDays) {
|
|
529
|
+
console.log(`Setting new renewal threshold to ${acmeSettings.renewThresholdDays} days`);
|
|
530
|
+
// This is implementation-dependent but gives an example
|
|
531
|
+
if (this.networkProxy.options.acme) {
|
|
532
|
+
this.networkProxy.options.acme.renewThresholdDays = acmeSettings.renewThresholdDays;
|
|
533
|
+
}
|
|
534
|
+
}
|
|
535
|
+
}
|
|
536
|
+
} catch (err) {
|
|
537
|
+
console.log(`Error updating ACME settings: ${err}`);
|
|
538
|
+
}
|
|
539
|
+
}
|
|
540
|
+
}
|
|
541
|
+
|
|
542
|
+
/**
|
|
543
|
+
* Synchronizes PortProxy domain configurations to NetworkProxy
|
|
544
|
+
* This allows domains configured in PortProxy to be used by NetworkProxy
|
|
545
|
+
*/
|
|
546
|
+
private async syncDomainConfigsToNetworkProxy(): Promise<void> {
|
|
547
|
+
if (!this.networkProxy) {
|
|
548
|
+
console.log('Cannot sync configurations - NetworkProxy not initialized');
|
|
549
|
+
return;
|
|
550
|
+
}
|
|
551
|
+
|
|
552
|
+
try {
|
|
553
|
+
// Get SSL certificates from assets
|
|
554
|
+
// Import fs directly since it's not in plugins
|
|
555
|
+
const fs = await import('fs');
|
|
556
|
+
|
|
557
|
+
let certPair;
|
|
558
|
+
try {
|
|
559
|
+
certPair = {
|
|
560
|
+
key: fs.readFileSync('assets/certs/key.pem', 'utf8'),
|
|
561
|
+
cert: fs.readFileSync('assets/certs/cert.pem', 'utf8')
|
|
562
|
+
};
|
|
563
|
+
} catch (certError) {
|
|
564
|
+
console.log(`Warning: Could not read default certificates: ${certError}`);
|
|
565
|
+
console.log('Using empty certificate placeholders - ACME will generate proper certificates if enabled');
|
|
566
|
+
|
|
567
|
+
// Use empty placeholders - NetworkProxy will use its internal defaults
|
|
568
|
+
// or ACME will generate proper ones if enabled
|
|
569
|
+
certPair = {
|
|
570
|
+
key: '',
|
|
571
|
+
cert: ''
|
|
572
|
+
};
|
|
573
|
+
}
|
|
574
|
+
|
|
575
|
+
// Convert domain configs to NetworkProxy configs
|
|
576
|
+
const proxyConfigs = this.networkProxy.convertPortProxyConfigs(
|
|
577
|
+
this.settings.domainConfigs,
|
|
578
|
+
certPair
|
|
579
|
+
);
|
|
580
|
+
|
|
581
|
+
// Log ACME-eligible domains if ACME is enabled
|
|
582
|
+
if (this.settings.acme?.enabled) {
|
|
583
|
+
const acmeEligibleDomains = proxyConfigs
|
|
584
|
+
.filter(config => !config.hostName.includes('*')) // Exclude wildcards
|
|
585
|
+
.map(config => config.hostName);
|
|
586
|
+
|
|
587
|
+
if (acmeEligibleDomains.length > 0) {
|
|
588
|
+
console.log(`Domains eligible for ACME certificates: ${acmeEligibleDomains.join(', ')}`);
|
|
589
|
+
} else {
|
|
590
|
+
console.log('No domains eligible for ACME certificates found in configuration');
|
|
591
|
+
}
|
|
592
|
+
}
|
|
593
|
+
|
|
594
|
+
// Update NetworkProxy with the converted configs
|
|
595
|
+
this.networkProxy.updateProxyConfigs(proxyConfigs).then(() => {
|
|
596
|
+
console.log(`Successfully synchronized ${proxyConfigs.length} domain configurations to NetworkProxy`);
|
|
597
|
+
}).catch(err => {
|
|
598
|
+
console.log(`Error synchronizing configurations: ${err.message}`);
|
|
599
|
+
});
|
|
600
|
+
} catch (err) {
|
|
601
|
+
console.log(`Failed to sync configurations: ${err}`);
|
|
602
|
+
}
|
|
603
|
+
}
|
|
604
|
+
|
|
605
|
+
/**
|
|
606
|
+
* Requests a certificate for a specific domain
|
|
607
|
+
* @param domain The domain to request a certificate for
|
|
608
|
+
* @returns Promise that resolves to true if the request was successful, false otherwise
|
|
609
|
+
*/
|
|
610
|
+
public async requestCertificate(domain: string): Promise<boolean> {
|
|
611
|
+
if (!this.networkProxy) {
|
|
612
|
+
console.log('Cannot request certificate - NetworkProxy not initialized');
|
|
613
|
+
return false;
|
|
614
|
+
}
|
|
615
|
+
|
|
616
|
+
if (!this.settings.acme?.enabled) {
|
|
617
|
+
console.log('Cannot request certificate - ACME is not enabled');
|
|
618
|
+
return false;
|
|
619
|
+
}
|
|
620
|
+
|
|
621
|
+
try {
|
|
622
|
+
const result = await this.networkProxy.requestCertificate(domain);
|
|
623
|
+
if (result) {
|
|
624
|
+
console.log(`Certificate request for ${domain} submitted successfully`);
|
|
625
|
+
} else {
|
|
626
|
+
console.log(`Certificate request for ${domain} failed`);
|
|
627
|
+
}
|
|
628
|
+
return result;
|
|
629
|
+
} catch (err) {
|
|
630
|
+
console.log(`Error requesting certificate: ${err}`);
|
|
631
|
+
return false;
|
|
441
632
|
}
|
|
442
633
|
}
|
|
443
634
|
|
|
@@ -1278,10 +1469,27 @@ export class PortProxy {
|
|
|
1278
1469
|
return;
|
|
1279
1470
|
}
|
|
1280
1471
|
|
|
1472
|
+
// Initialize NetworkProxy if needed (useNetworkProxy is set but networkProxy isn't initialized)
|
|
1473
|
+
if (this.settings.useNetworkProxy && this.settings.useNetworkProxy.length > 0 && !this.networkProxy) {
|
|
1474
|
+
await this.initializeNetworkProxy();
|
|
1475
|
+
}
|
|
1476
|
+
|
|
1281
1477
|
// Start NetworkProxy if configured
|
|
1282
1478
|
if (this.networkProxy) {
|
|
1283
1479
|
await this.networkProxy.start();
|
|
1284
1480
|
console.log(`NetworkProxy started on port ${this.settings.networkProxyPort}`);
|
|
1481
|
+
|
|
1482
|
+
// Log ACME status
|
|
1483
|
+
if (this.settings.acme?.enabled) {
|
|
1484
|
+
console.log(`ACME certificate management is enabled (${this.settings.acme.useProduction ? 'Production' : 'Staging'} mode)`);
|
|
1485
|
+
console.log(`ACME HTTP challenge server on port ${this.settings.acme.port}`);
|
|
1486
|
+
|
|
1487
|
+
// Register domains for ACME certificates if enabled
|
|
1488
|
+
if (this.networkProxy.options.acme?.enabled) {
|
|
1489
|
+
console.log('Registering domains with ACME certificate manager...');
|
|
1490
|
+
// The NetworkProxy will handle this internally via registerDomainsWithAcmeManager()
|
|
1491
|
+
}
|
|
1492
|
+
}
|
|
1285
1493
|
}
|
|
1286
1494
|
|
|
1287
1495
|
// Define a unified connection handler for all listening ports.
|
|
@@ -2036,11 +2244,17 @@ export class PortProxy {
|
|
|
2036
2244
|
}
|
|
2037
2245
|
}
|
|
2038
2246
|
|
|
2039
|
-
// Stop NetworkProxy if it was started
|
|
2247
|
+
// Stop NetworkProxy if it was started (which also stops ACME manager)
|
|
2040
2248
|
if (this.networkProxy) {
|
|
2041
2249
|
try {
|
|
2250
|
+
console.log('Stopping NetworkProxy...');
|
|
2042
2251
|
await this.networkProxy.stop();
|
|
2043
2252
|
console.log('NetworkProxy stopped successfully');
|
|
2253
|
+
|
|
2254
|
+
// Log ACME shutdown if it was enabled
|
|
2255
|
+
if (this.settings.acme?.enabled) {
|
|
2256
|
+
console.log('ACME certificate manager stopped');
|
|
2257
|
+
}
|
|
2044
2258
|
} catch (err) {
|
|
2045
2259
|
console.log(`Error stopping NetworkProxy: ${err}`);
|
|
2046
2260
|
}
|