import * as plugins from '../plugins.js'; import * as paths from '../paths.js'; import { SzDcRouterConnector } from './classes.dcr.sz.connector.js'; import type { SzPlatformService } from '../platformservice.js'; import { type IMtaConfig, MtaService } from '../mta/classes.mta.js'; // Types are referenced via plugins.smartproxy.* export interface IDcRouterOptions { platformServiceInstance?: SzPlatformService; /** SmartProxy (TCP/SNI) configuration */ smartProxyOptions?: plugins.smartproxy.ISmartProxyOptions; /** Reverse proxy host configurations for HTTP(S) layer */ reverseProxyConfigs?: plugins.smartproxy.IReverseProxyConfig[]; /** MTA (SMTP) service configuration */ mtaConfig?: IMtaConfig; /** DNS server configuration */ dnsServerConfig?: plugins.smartdns.IDnsServerOptions; } /** * DcRouter can be run on ingress and egress to and from a datacenter site. */ /** * Context passed to HTTP routing rules */ /** * Context passed to port proxy (SmartProxy) routing rules */ export interface PortProxyRuleContext { proxy: plugins.smartproxy.SmartProxy; configs: plugins.smartproxy.IPortProxySettings['domainConfigs']; } export class DcRouter { public szDcRouterConnector = new SzDcRouterConnector(this); public options: IDcRouterOptions; public smartProxy?: plugins.smartproxy.SmartProxy; public mta?: MtaService; public dnsServer?: plugins.smartdns.DnsServer; /** SMTP rule engine */ public smtpRuleEngine?: plugins.smartrule.SmartRule; constructor(optionsArg: IDcRouterOptions) { this.options = optionsArg; } public async start() { // TCP/SNI proxy (SmartProxy) if (this.options.smartProxyOptions) { // Lets setup smartacme let certProvisionFunction: plugins.smartproxy.ISmartProxyOptions['certProvisionFunction']; if (true) { const smartAcmeInstance = new plugins.smartacme.SmartAcme({ accountEmail: this.options.smartProxyOptions.acme.accountEmail, certManager: new plugins.smartacme.certmanagers.MongoCertManager({ mongoDbUrl: await this.szDcRouterConnector.getEnvVarOnDemand('MONGO_DB_URL'), mongoDbUser: await this.szDcRouterConnector.getEnvVarOnDemand('MONGO_DB_USER'), mongoDbPass: await this.szDcRouterConnector.getEnvVarOnDemand('MONGO_DB_PASS'), mongoDbName: await this.szDcRouterConnector.getEnvVarOnDemand('MONGO_DB_NAME'), }), environment: 'production', accountPrivateKey: await this.szDcRouterConnector.getEnvVarOnDemand('ACME_ACCOUNT_PRIVATE_KEY'), challengeHandlers: [ new plugins.smartacme.handlers.Dns01Handler(new plugins.cloudflare.CloudflareAccount('')) // TODO ], }); certProvisionFunction = async (domainArg) => { const domainSupported = await smartAcmeInstance.challengeHandlers[0].checkWetherDomainIsSupported(domainArg); if (!domainSupported) { return 'http01'; } return smartAcmeInstance.getCertificateForDomain(domainArg); }; } this.smartProxy = new plugins.smartproxy.SmartProxy(this.options.smartProxyOptions); // Initialize SMTP rule engine from MTA service if available if (this.mta) { this.smtpRuleEngine = this.mta.smtpRuleEngine; } } // MTA service if (this.options.mtaConfig) { this.mta = new MtaService(null, this.options.mtaConfig); } // DNS server if (this.options.dnsServerConfig) { this.dnsServer = new plugins.smartdns.DnsServer(this.options.dnsServerConfig); } // Start SmartProxy if configured if (this.smartProxy) { await this.smartProxy.start(); } // Start MTA service if configured if (this.mta) { await this.mta.start(); } // Start DNS server if configured if (this.dnsServer) { await this.dnsServer.start(); } } public async stop() { // Stop SmartProxy if (this.smartProxy) { await this.smartProxy.stop(); } // Stop MTA service if (this.mta) { await this.mta.stop(); } // Stop DNS server if (this.dnsServer) { await this.dnsServer.stop(); } } /** * Register an SMTP routing rule */ public addSmtpRule( priority: number, check: (email: any) => Promise, action: (email: any) => Promise ): void { this.smtpRuleEngine?.createRule(priority, check, action); } } export default DcRouter;