@push.rocks/smartproxy 7.2.0 → 10.0.1
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/classes.router.d.ts +9 -10
- package/dist_ts/classes.router.js +3 -5
- package/dist_ts/common/acmeFactory.d.ts +9 -0
- package/dist_ts/common/acmeFactory.js +20 -0
- package/dist_ts/common/eventUtils.d.ts +15 -0
- package/dist_ts/common/eventUtils.js +19 -0
- package/dist_ts/common/types.d.ts +82 -0
- package/dist_ts/common/types.js +17 -0
- package/dist_ts/networkproxy/classes.np.certificatemanager.js +23 -19
- package/dist_ts/networkproxy/classes.np.types.d.ts +5 -10
- package/dist_ts/networkproxy/classes.np.types.js +1 -1
- package/dist_ts/plugins.d.ts +2 -1
- package/dist_ts/plugins.js +3 -2
- package/dist_ts/port80handler/classes.port80handler.d.ts +8 -91
- package/dist_ts/port80handler/classes.port80handler.js +34 -222
- package/dist_ts/smartproxy/classes.pp.certprovisioner.d.ts +54 -0
- package/dist_ts/smartproxy/classes.pp.certprovisioner.js +166 -0
- package/dist_ts/smartproxy/classes.pp.interfaces.d.ts +2 -33
- package/dist_ts/smartproxy/classes.pp.networkproxybridge.d.ts +2 -1
- package/dist_ts/smartproxy/classes.pp.networkproxybridge.js +11 -11
- package/dist_ts/smartproxy/classes.pp.portrangemanager.js +1 -11
- package/dist_ts/smartproxy/classes.smartproxy.d.ts +1 -4
- package/dist_ts/smartproxy/classes.smartproxy.js +62 -213
- package/package.json +2 -1
- package/readme.md +254 -453
- package/readme.plan.md +27 -29
- package/ts/00_commitinfo_data.ts +1 -1
- package/ts/classes.router.ts +13 -15
- package/ts/common/acmeFactory.ts +23 -0
- package/ts/common/eventUtils.ts +34 -0
- package/ts/common/types.ts +89 -0
- package/ts/networkproxy/classes.np.certificatemanager.ts +23 -19
- package/ts/networkproxy/classes.np.types.ts +6 -10
- package/ts/plugins.ts +13 -2
- package/ts/port80handler/classes.port80handler.ts +44 -310
- package/ts/smartproxy/classes.pp.certprovisioner.ts +188 -0
- package/ts/smartproxy/classes.pp.interfaces.ts +3 -36
- package/ts/smartproxy/classes.pp.networkproxybridge.ts +11 -10
- package/ts/smartproxy/classes.pp.portrangemanager.ts +0 -10
- package/ts/smartproxy/classes.smartproxy.ts +73 -222
|
@@ -21,6 +21,7 @@ export interface IDomainConfig {
|
|
|
21
21
|
}
|
|
22
22
|
|
|
23
23
|
/** Port proxy settings including global allowed port ranges */
|
|
24
|
+
import type { IAcmeOptions } from '../common/types.js';
|
|
24
25
|
export interface IPortProxySettings {
|
|
25
26
|
fromPort: number;
|
|
26
27
|
toPort: number;
|
|
@@ -83,43 +84,9 @@ export interface IPortProxySettings {
|
|
|
83
84
|
useNetworkProxy?: number[]; // Array of ports to forward to NetworkProxy
|
|
84
85
|
networkProxyPort?: number; // Port where NetworkProxy is listening (default: 8443)
|
|
85
86
|
|
|
86
|
-
//
|
|
87
|
-
|
|
88
|
-
enabled?: boolean; // Whether to enable automatic certificate management
|
|
89
|
-
port?: number; // Port to listen on for ACME challenges (default: 80)
|
|
90
|
-
contactEmail?: string; // Email for Let's Encrypt account
|
|
91
|
-
useProduction?: boolean; // Whether to use Let's Encrypt production (default: false for staging)
|
|
92
|
-
renewThresholdDays?: number; // Days before expiry to renew certificates (default: 30)
|
|
93
|
-
autoRenew?: boolean; // Whether to automatically renew certificates (default: true)
|
|
94
|
-
certificateStore?: string; // Directory to store certificates (default: ./certs)
|
|
95
|
-
skipConfiguredCerts?: boolean; // Skip domains that already have certificates
|
|
96
|
-
httpsRedirectPort?: number; // Port to redirect HTTP requests to HTTPS (default: 443)
|
|
97
|
-
renewCheckIntervalHours?: number; // How often to check for renewals (default: 24)
|
|
98
|
-
// Domain-specific forwarding configurations
|
|
99
|
-
domainForwards?: Array<{
|
|
100
|
-
domain: string;
|
|
101
|
-
forwardConfig?: {
|
|
102
|
-
ip: string;
|
|
103
|
-
port: number;
|
|
104
|
-
};
|
|
105
|
-
acmeForwardConfig?: {
|
|
106
|
-
ip: string;
|
|
107
|
-
port: number;
|
|
108
|
-
};
|
|
109
|
-
}>;
|
|
110
|
-
};
|
|
87
|
+
// ACME configuration options for SmartProxy
|
|
88
|
+
acme?: IAcmeOptions;
|
|
111
89
|
|
|
112
|
-
// Legacy ACME configuration (deprecated, use port80HandlerConfig instead)
|
|
113
|
-
acme?: {
|
|
114
|
-
enabled?: boolean;
|
|
115
|
-
port?: number;
|
|
116
|
-
contactEmail?: string;
|
|
117
|
-
useProduction?: boolean;
|
|
118
|
-
renewThresholdDays?: number;
|
|
119
|
-
autoRenew?: boolean;
|
|
120
|
-
certificateStore?: string;
|
|
121
|
-
skipConfiguredCerts?: boolean;
|
|
122
|
-
};
|
|
123
90
|
/**
|
|
124
91
|
* Optional certificate provider callback. Return 'http01' to use HTTP-01 challenges,
|
|
125
92
|
* or a static certificate object for immediate provisioning.
|
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
import * as plugins from '../plugins.js';
|
|
2
2
|
import { NetworkProxy } from '../networkproxy/classes.np.networkproxy.js';
|
|
3
|
-
import { Port80Handler
|
|
3
|
+
import { Port80Handler } from '../port80handler/classes.port80handler.js';
|
|
4
|
+
import { Port80HandlerEvents } from '../common/types.js';
|
|
5
|
+
import { subscribeToPort80Handler } from '../common/eventUtils.js';
|
|
6
|
+
import type { ICertificateData } from '../common/types.js';
|
|
4
7
|
import type { IConnectionRecord, IPortProxySettings, IDomainConfig } from './classes.pp.interfaces.js';
|
|
5
8
|
|
|
6
9
|
/**
|
|
@@ -18,9 +21,11 @@ export class NetworkProxyBridge {
|
|
|
18
21
|
public setPort80Handler(handler: Port80Handler): void {
|
|
19
22
|
this.port80Handler = handler;
|
|
20
23
|
|
|
21
|
-
//
|
|
22
|
-
handler
|
|
23
|
-
|
|
24
|
+
// Subscribe to certificate events
|
|
25
|
+
subscribeToPort80Handler(handler, {
|
|
26
|
+
onCertificateIssued: this.handleCertificateEvent.bind(this),
|
|
27
|
+
onCertificateRenewed: this.handleCertificateEvent.bind(this)
|
|
28
|
+
});
|
|
24
29
|
|
|
25
30
|
// If NetworkProxy is already initialized, connect it with Port80Handler
|
|
26
31
|
if (this.networkProxy) {
|
|
@@ -43,10 +48,6 @@ export class NetworkProxyBridge {
|
|
|
43
48
|
useExternalPort80Handler: !!this.port80Handler // Use Port80Handler if available
|
|
44
49
|
};
|
|
45
50
|
|
|
46
|
-
// Copy ACME settings for backward compatibility (if port80HandlerConfig not set)
|
|
47
|
-
if (!this.settings.port80HandlerConfig && this.settings.acme) {
|
|
48
|
-
networkProxyOptions.acme = { ...this.settings.acme };
|
|
49
|
-
}
|
|
50
51
|
|
|
51
52
|
this.networkProxy = new NetworkProxy(networkProxyOptions);
|
|
52
53
|
|
|
@@ -288,7 +289,7 @@ export class NetworkProxyBridge {
|
|
|
288
289
|
);
|
|
289
290
|
|
|
290
291
|
// Log ACME-eligible domains
|
|
291
|
-
const acmeEnabled = this.settings.
|
|
292
|
+
const acmeEnabled = !!this.settings.acme?.enabled;
|
|
292
293
|
if (acmeEnabled) {
|
|
293
294
|
const acmeEligibleDomains = proxyConfigs
|
|
294
295
|
.filter((config) => !config.hostName.includes('*')) // Exclude wildcards
|
|
@@ -349,7 +350,7 @@ export class NetworkProxyBridge {
|
|
|
349
350
|
return false;
|
|
350
351
|
}
|
|
351
352
|
|
|
352
|
-
if (!this.settings.
|
|
353
|
+
if (!this.settings.acme?.enabled) {
|
|
353
354
|
console.log('Cannot request certificate - ACME is not enabled');
|
|
354
355
|
return false;
|
|
355
356
|
}
|
|
@@ -117,10 +117,6 @@ export class PortRangeManager {
|
|
|
117
117
|
}
|
|
118
118
|
}
|
|
119
119
|
|
|
120
|
-
// Add ACME HTTP challenge port if enabled
|
|
121
|
-
if (this.settings.acme?.enabled && this.settings.acme.port) {
|
|
122
|
-
ports.add(this.settings.acme.port);
|
|
123
|
-
}
|
|
124
120
|
|
|
125
121
|
// Add global port ranges
|
|
126
122
|
if (this.settings.globalPortRanges) {
|
|
@@ -202,12 +198,6 @@ export class PortRangeManager {
|
|
|
202
198
|
warnings.push(`NetworkProxy port ${this.settings.networkProxyPort} is also used in port ranges`);
|
|
203
199
|
}
|
|
204
200
|
|
|
205
|
-
// Check ACME port
|
|
206
|
-
if (this.settings.acme?.enabled && this.settings.acme.port) {
|
|
207
|
-
if (portMappings.has(this.settings.acme.port)) {
|
|
208
|
-
warnings.push(`ACME HTTP challenge port ${this.settings.acme.port} is also used in port ranges`);
|
|
209
|
-
}
|
|
210
|
-
}
|
|
211
201
|
|
|
212
202
|
return warnings;
|
|
213
203
|
}
|
|
@@ -8,9 +8,10 @@ import { NetworkProxyBridge } from './classes.pp.networkproxybridge.js';
|
|
|
8
8
|
import { TimeoutManager } from './classes.pp.timeoutmanager.js';
|
|
9
9
|
import { PortRangeManager } from './classes.pp.portrangemanager.js';
|
|
10
10
|
import { ConnectionHandler } from './classes.pp.connectionhandler.js';
|
|
11
|
-
import { Port80Handler
|
|
12
|
-
import
|
|
13
|
-
import
|
|
11
|
+
import { Port80Handler } from '../port80handler/classes.port80handler.js';
|
|
12
|
+
import { CertProvisioner } from './classes.pp.certprovisioner.js';
|
|
13
|
+
import type { ICertificateData } from '../common/types.js';
|
|
14
|
+
import { buildPort80Handler } from '../common/acmeFactory.js';
|
|
14
15
|
|
|
15
16
|
/**
|
|
16
17
|
* SmartProxy - Main class that coordinates all components
|
|
@@ -32,6 +33,8 @@ export class SmartProxy extends plugins.EventEmitter {
|
|
|
32
33
|
|
|
33
34
|
// Port80Handler for ACME certificate management
|
|
34
35
|
private port80Handler: Port80Handler | null = null;
|
|
36
|
+
// CertProvisioner for unified certificate workflows
|
|
37
|
+
private certProvisioner?: CertProvisioner;
|
|
35
38
|
|
|
36
39
|
constructor(settingsArg: IPortProxySettings) {
|
|
37
40
|
super();
|
|
@@ -63,41 +66,25 @@ export class SmartProxy extends plugins.EventEmitter {
|
|
|
63
66
|
keepAliveInactivityMultiplier: settingsArg.keepAliveInactivityMultiplier || 6,
|
|
64
67
|
extendedKeepAliveLifetime: settingsArg.extendedKeepAliveLifetime || 7 * 24 * 60 * 60 * 1000,
|
|
65
68
|
networkProxyPort: settingsArg.networkProxyPort || 8443,
|
|
66
|
-
|
|
69
|
+
acme: settingsArg.acme || {},
|
|
67
70
|
globalPortRanges: settingsArg.globalPortRanges || [],
|
|
68
71
|
};
|
|
69
72
|
|
|
70
|
-
// Set
|
|
71
|
-
if (!this.settings.
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
};
|
|
86
|
-
} else {
|
|
87
|
-
// Set defaults if no config provided
|
|
88
|
-
this.settings.port80HandlerConfig = {
|
|
89
|
-
enabled: false,
|
|
90
|
-
port: 80,
|
|
91
|
-
contactEmail: 'admin@example.com',
|
|
92
|
-
useProduction: false,
|
|
93
|
-
renewThresholdDays: 30,
|
|
94
|
-
autoRenew: true,
|
|
95
|
-
certificateStore: './certs',
|
|
96
|
-
skipConfiguredCerts: false,
|
|
97
|
-
httpsRedirectPort: this.settings.fromPort,
|
|
98
|
-
renewCheckIntervalHours: 24
|
|
99
|
-
};
|
|
100
|
-
}
|
|
73
|
+
// Set default ACME options if not provided
|
|
74
|
+
if (!this.settings.acme || Object.keys(this.settings.acme).length === 0) {
|
|
75
|
+
this.settings.acme = {
|
|
76
|
+
enabled: false,
|
|
77
|
+
port: 80,
|
|
78
|
+
contactEmail: 'admin@example.com',
|
|
79
|
+
useProduction: false,
|
|
80
|
+
renewThresholdDays: 30,
|
|
81
|
+
autoRenew: true,
|
|
82
|
+
certificateStore: './certs',
|
|
83
|
+
skipConfiguredCerts: false,
|
|
84
|
+
httpsRedirectPort: this.settings.fromPort,
|
|
85
|
+
renewCheckIntervalHours: 24,
|
|
86
|
+
domainForwards: []
|
|
87
|
+
};
|
|
101
88
|
}
|
|
102
89
|
|
|
103
90
|
// Initialize component managers
|
|
@@ -135,127 +122,20 @@ export class SmartProxy extends plugins.EventEmitter {
|
|
|
135
122
|
* Initialize the Port80Handler for ACME certificate management
|
|
136
123
|
*/
|
|
137
124
|
private async initializePort80Handler(): Promise<void> {
|
|
138
|
-
const config = this.settings.
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
console.log('Port80Handler is disabled in configuration');
|
|
125
|
+
const config = this.settings.acme!;
|
|
126
|
+
if (!config.enabled) {
|
|
127
|
+
console.log('ACME is disabled in configuration');
|
|
142
128
|
return;
|
|
143
129
|
}
|
|
144
130
|
|
|
145
131
|
try {
|
|
146
|
-
//
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
fs.mkdirSync(certStorePath, { recursive: true });
|
|
151
|
-
console.log(`Created certificate store directory: ${certStorePath}`);
|
|
152
|
-
}
|
|
153
|
-
}
|
|
154
|
-
|
|
155
|
-
// Create Port80Handler with options from config
|
|
156
|
-
this.port80Handler = new Port80Handler({
|
|
157
|
-
port: config.port,
|
|
158
|
-
contactEmail: config.contactEmail,
|
|
159
|
-
useProduction: config.useProduction,
|
|
160
|
-
renewThresholdDays: config.renewThresholdDays,
|
|
161
|
-
httpsRedirectPort: config.httpsRedirectPort || this.settings.fromPort,
|
|
162
|
-
renewCheckIntervalHours: config.renewCheckIntervalHours,
|
|
163
|
-
enabled: config.enabled,
|
|
164
|
-
autoRenew: config.autoRenew,
|
|
165
|
-
certificateStore: config.certificateStore,
|
|
166
|
-
skipConfiguredCerts: config.skipConfiguredCerts
|
|
167
|
-
});
|
|
168
|
-
|
|
169
|
-
// Register domain forwarding configurations
|
|
170
|
-
if (config.domainForwards) {
|
|
171
|
-
for (const forward of config.domainForwards) {
|
|
172
|
-
this.port80Handler.addDomain({
|
|
173
|
-
domainName: forward.domain,
|
|
174
|
-
sslRedirect: true,
|
|
175
|
-
acmeMaintenance: true,
|
|
176
|
-
forward: forward.forwardConfig,
|
|
177
|
-
acmeForward: forward.acmeForwardConfig
|
|
178
|
-
});
|
|
179
|
-
|
|
180
|
-
console.log(`Registered domain forwarding for ${forward.domain}`);
|
|
181
|
-
}
|
|
182
|
-
}
|
|
183
|
-
|
|
184
|
-
// Provision certificates per domain via certProvider or HTTP-01
|
|
185
|
-
for (const domainConfig of this.settings.domainConfigs) {
|
|
186
|
-
for (const domain of domainConfig.domains) {
|
|
187
|
-
// Skip wildcard domains
|
|
188
|
-
if (domain.includes('*')) continue;
|
|
189
|
-
// Determine provisioning method
|
|
190
|
-
let provision = 'http01' as string | plugins.tsclass.network.ICert;
|
|
191
|
-
if (this.settings.certProvider) {
|
|
192
|
-
try {
|
|
193
|
-
provision = await this.settings.certProvider(domain);
|
|
194
|
-
} catch (err) {
|
|
195
|
-
console.log(`certProvider error for ${domain}: ${err}`);
|
|
196
|
-
}
|
|
197
|
-
}
|
|
198
|
-
if (provision === 'http01') {
|
|
199
|
-
this.port80Handler.addDomain({
|
|
200
|
-
domainName: domain,
|
|
201
|
-
sslRedirect: true,
|
|
202
|
-
acmeMaintenance: true
|
|
203
|
-
});
|
|
204
|
-
console.log(`Registered domain ${domain} with Port80Handler for HTTP-01`);
|
|
205
|
-
} else {
|
|
206
|
-
// Static certificate provided
|
|
207
|
-
const certObj = provision as plugins.tsclass.network.ICert;
|
|
208
|
-
const certData: ICertificateData = {
|
|
209
|
-
domain: certObj.domainName,
|
|
210
|
-
certificate: certObj.publicKey,
|
|
211
|
-
privateKey: certObj.privateKey,
|
|
212
|
-
expiryDate: new Date(certObj.validUntil)
|
|
213
|
-
};
|
|
214
|
-
this.networkProxyBridge.applyExternalCertificate(certData);
|
|
215
|
-
console.log(`Applied static certificate for ${domain} from certProvider`);
|
|
216
|
-
}
|
|
217
|
-
}
|
|
218
|
-
}
|
|
219
|
-
|
|
220
|
-
// Set up event listeners
|
|
221
|
-
this.port80Handler.on(Port80HandlerEvents.CERTIFICATE_ISSUED, (certData) => {
|
|
222
|
-
console.log(`Certificate issued for ${certData.domain}, valid until ${certData.expiryDate.toISOString()}`);
|
|
223
|
-
// Re-emit on SmartProxy
|
|
224
|
-
this.emit('certificate', {
|
|
225
|
-
domain: certData.domain,
|
|
226
|
-
publicKey: certData.certificate,
|
|
227
|
-
privateKey: certData.privateKey,
|
|
228
|
-
expiryDate: certData.expiryDate,
|
|
229
|
-
source: 'http01',
|
|
230
|
-
isRenewal: false
|
|
231
|
-
});
|
|
232
|
-
});
|
|
233
|
-
|
|
234
|
-
this.port80Handler.on(Port80HandlerEvents.CERTIFICATE_RENEWED, (certData) => {
|
|
235
|
-
console.log(`Certificate renewed for ${certData.domain}, valid until ${certData.expiryDate.toISOString()}`);
|
|
236
|
-
// Re-emit on SmartProxy
|
|
237
|
-
this.emit('certificate', {
|
|
238
|
-
domain: certData.domain,
|
|
239
|
-
publicKey: certData.certificate,
|
|
240
|
-
privateKey: certData.privateKey,
|
|
241
|
-
expiryDate: certData.expiryDate,
|
|
242
|
-
source: 'http01',
|
|
243
|
-
isRenewal: true
|
|
244
|
-
});
|
|
245
|
-
});
|
|
246
|
-
|
|
247
|
-
this.port80Handler.on(Port80HandlerEvents.CERTIFICATE_FAILED, (failureData) => {
|
|
248
|
-
console.log(`Certificate ${failureData.isRenewal ? 'renewal' : 'issuance'} failed for ${failureData.domain}: ${failureData.error}`);
|
|
132
|
+
// Build and start the Port80Handler
|
|
133
|
+
this.port80Handler = buildPort80Handler({
|
|
134
|
+
...config,
|
|
135
|
+
httpsRedirectPort: config.httpsRedirectPort || this.settings.fromPort
|
|
249
136
|
});
|
|
250
|
-
|
|
251
|
-
this.port80Handler.on(Port80HandlerEvents.CERTIFICATE_EXPIRING, (expiryData) => {
|
|
252
|
-
console.log(`Certificate for ${expiryData.domain} is expiring in ${expiryData.daysRemaining} days`);
|
|
253
|
-
});
|
|
254
|
-
|
|
255
|
-
// Share Port80Handler with NetworkProxyBridge
|
|
137
|
+
// Share Port80Handler with NetworkProxyBridge before start
|
|
256
138
|
this.networkProxyBridge.setPort80Handler(this.port80Handler);
|
|
257
|
-
|
|
258
|
-
// Start Port80Handler
|
|
259
139
|
await this.port80Handler.start();
|
|
260
140
|
console.log(`Port80Handler started on port ${config.port}`);
|
|
261
141
|
} catch (err) {
|
|
@@ -275,6 +155,37 @@ export class SmartProxy extends plugins.EventEmitter {
|
|
|
275
155
|
|
|
276
156
|
// Initialize Port80Handler if enabled
|
|
277
157
|
await this.initializePort80Handler();
|
|
158
|
+
// Initialize CertProvisioner for unified certificate workflows
|
|
159
|
+
if (this.port80Handler) {
|
|
160
|
+
const acme = this.settings.acme!;
|
|
161
|
+
this.certProvisioner = new CertProvisioner(
|
|
162
|
+
this.settings.domainConfigs,
|
|
163
|
+
this.port80Handler,
|
|
164
|
+
this.networkProxyBridge,
|
|
165
|
+
this.settings.certProvider,
|
|
166
|
+
acme.renewThresholdDays!,
|
|
167
|
+
acme.renewCheckIntervalHours!,
|
|
168
|
+
acme.autoRenew!,
|
|
169
|
+
acme.domainForwards?.map(f => ({
|
|
170
|
+
domain: f.domain,
|
|
171
|
+
forwardConfig: f.forwardConfig,
|
|
172
|
+
acmeForwardConfig: f.acmeForwardConfig,
|
|
173
|
+
sslRedirect: f.sslRedirect || false
|
|
174
|
+
})) || []
|
|
175
|
+
);
|
|
176
|
+
this.certProvisioner.on('certificate', (certData) => {
|
|
177
|
+
this.emit('certificate', {
|
|
178
|
+
domain: certData.domain,
|
|
179
|
+
publicKey: certData.certificate,
|
|
180
|
+
privateKey: certData.privateKey,
|
|
181
|
+
expiryDate: certData.expiryDate,
|
|
182
|
+
source: certData.source,
|
|
183
|
+
isRenewal: certData.isRenewal
|
|
184
|
+
});
|
|
185
|
+
});
|
|
186
|
+
await this.certProvisioner.start();
|
|
187
|
+
console.log('CertProvisioner started');
|
|
188
|
+
}
|
|
278
189
|
|
|
279
190
|
// Initialize and start NetworkProxy if needed
|
|
280
191
|
if (
|
|
@@ -403,6 +314,11 @@ export class SmartProxy extends plugins.EventEmitter {
|
|
|
403
314
|
public async stop() {
|
|
404
315
|
console.log('PortProxy shutting down...');
|
|
405
316
|
this.isShuttingDown = true;
|
|
317
|
+
// Stop CertProvisioner if active
|
|
318
|
+
if (this.certProvisioner) {
|
|
319
|
+
await this.certProvisioner.stop();
|
|
320
|
+
console.log('CertProvisioner stopped');
|
|
321
|
+
}
|
|
406
322
|
|
|
407
323
|
// Stop the Port80Handler if running
|
|
408
324
|
if (this.port80Handler) {
|
|
@@ -469,7 +385,7 @@ export class SmartProxy extends plugins.EventEmitter {
|
|
|
469
385
|
}
|
|
470
386
|
|
|
471
387
|
// If Port80Handler is running, provision certificates per new domain
|
|
472
|
-
if (this.port80Handler && this.settings.
|
|
388
|
+
if (this.port80Handler && this.settings.acme?.enabled) {
|
|
473
389
|
for (const domainConfig of newDomainConfigs) {
|
|
474
390
|
for (const domain of domainConfig.domains) {
|
|
475
391
|
if (domain.includes('*')) continue;
|
|
@@ -505,72 +421,6 @@ export class SmartProxy extends plugins.EventEmitter {
|
|
|
505
421
|
}
|
|
506
422
|
}
|
|
507
423
|
|
|
508
|
-
/**
|
|
509
|
-
* Updates the Port80Handler configuration
|
|
510
|
-
*/
|
|
511
|
-
public async updatePort80HandlerConfig(config: IPortProxySettings['port80HandlerConfig']): Promise<void> {
|
|
512
|
-
if (!config) return;
|
|
513
|
-
|
|
514
|
-
console.log('Updating Port80Handler configuration');
|
|
515
|
-
|
|
516
|
-
// Update the settings
|
|
517
|
-
this.settings.port80HandlerConfig = {
|
|
518
|
-
...this.settings.port80HandlerConfig,
|
|
519
|
-
...config
|
|
520
|
-
};
|
|
521
|
-
|
|
522
|
-
// Check if we need to restart Port80Handler
|
|
523
|
-
let needsRestart = false;
|
|
524
|
-
|
|
525
|
-
// Restart if enabled state changed
|
|
526
|
-
if (this.port80Handler && config.enabled === false) {
|
|
527
|
-
needsRestart = true;
|
|
528
|
-
} else if (!this.port80Handler && config.enabled === true) {
|
|
529
|
-
needsRestart = true;
|
|
530
|
-
} else if (this.port80Handler && (
|
|
531
|
-
config.port !== undefined ||
|
|
532
|
-
config.contactEmail !== undefined ||
|
|
533
|
-
config.useProduction !== undefined ||
|
|
534
|
-
config.renewThresholdDays !== undefined ||
|
|
535
|
-
config.renewCheckIntervalHours !== undefined
|
|
536
|
-
)) {
|
|
537
|
-
// Restart if critical settings changed
|
|
538
|
-
needsRestart = true;
|
|
539
|
-
}
|
|
540
|
-
|
|
541
|
-
if (needsRestart) {
|
|
542
|
-
// Stop if running
|
|
543
|
-
if (this.port80Handler) {
|
|
544
|
-
try {
|
|
545
|
-
await this.port80Handler.stop();
|
|
546
|
-
this.port80Handler = null;
|
|
547
|
-
console.log('Stopped Port80Handler for configuration update');
|
|
548
|
-
} catch (err) {
|
|
549
|
-
console.log(`Error stopping Port80Handler: ${err}`);
|
|
550
|
-
}
|
|
551
|
-
}
|
|
552
|
-
|
|
553
|
-
// Start with new config if enabled
|
|
554
|
-
if (this.settings.port80HandlerConfig.enabled) {
|
|
555
|
-
await this.initializePort80Handler();
|
|
556
|
-
console.log('Restarted Port80Handler with new configuration');
|
|
557
|
-
}
|
|
558
|
-
} else if (this.port80Handler) {
|
|
559
|
-
// Just update domain forwards if they changed
|
|
560
|
-
if (config.domainForwards) {
|
|
561
|
-
for (const forward of config.domainForwards) {
|
|
562
|
-
this.port80Handler.addDomain({
|
|
563
|
-
domainName: forward.domain,
|
|
564
|
-
sslRedirect: true,
|
|
565
|
-
acmeMaintenance: true,
|
|
566
|
-
forward: forward.forwardConfig,
|
|
567
|
-
acmeForward: forward.acmeForwardConfig
|
|
568
|
-
});
|
|
569
|
-
}
|
|
570
|
-
console.log('Updated domain forwards in Port80Handler');
|
|
571
|
-
}
|
|
572
|
-
}
|
|
573
|
-
}
|
|
574
424
|
|
|
575
425
|
/**
|
|
576
426
|
* Request a certificate for a specific domain
|
|
@@ -664,7 +514,7 @@ export class SmartProxy extends plugins.EventEmitter {
|
|
|
664
514
|
networkProxyConnections,
|
|
665
515
|
terminationStats,
|
|
666
516
|
acmeEnabled: !!this.port80Handler,
|
|
667
|
-
port80HandlerPort: this.port80Handler ? this.settings.
|
|
517
|
+
port80HandlerPort: this.port80Handler ? this.settings.acme?.port : null
|
|
668
518
|
};
|
|
669
519
|
}
|
|
670
520
|
|
|
@@ -715,7 +565,7 @@ export class SmartProxy extends plugins.EventEmitter {
|
|
|
715
565
|
status: 'valid',
|
|
716
566
|
expiryDate: expiryDate.toISOString(),
|
|
717
567
|
daysRemaining,
|
|
718
|
-
renewalNeeded: daysRemaining <= this.settings.
|
|
568
|
+
renewalNeeded: daysRemaining <= (this.settings.acme?.renewThresholdDays ?? 0)
|
|
719
569
|
};
|
|
720
570
|
} else {
|
|
721
571
|
certificateStatus[domain] = {
|
|
@@ -725,11 +575,12 @@ export class SmartProxy extends plugins.EventEmitter {
|
|
|
725
575
|
}
|
|
726
576
|
}
|
|
727
577
|
|
|
578
|
+
const acme = this.settings.acme!;
|
|
728
579
|
return {
|
|
729
580
|
enabled: true,
|
|
730
|
-
port:
|
|
731
|
-
useProduction:
|
|
732
|
-
autoRenew:
|
|
581
|
+
port: acme.port!,
|
|
582
|
+
useProduction: acme.useProduction!,
|
|
583
|
+
autoRenew: acme.autoRenew!,
|
|
733
584
|
certificates: certificateStatus
|
|
734
585
|
};
|
|
735
586
|
}
|