@vladmandic/piproxy
Version:
Reverse HTTP/HTTPS/HTTP2 Proxy in NodeJS with SSL Certificate Management, Compression, Security Enforcement and Rate Limiting
68 lines (55 loc) • 2.52 kB
text/typescript
import * as log from '@vladmandic/pilogger';
import * as acme from '@vladmandic/piacme';
import * as noip from './noip';
import * as geoip from './geoip';
import * as monitor from './monitor';
import * as server from './server';
import * as config from './config';
function exit(signal: string) {
log.warn('exit', { signal });
process.exit(0);
}
function error(err: Error) {
log.error('exception');
for (const line of (err.stack || '').split('\n')) log.error(line);
process.exit(1);
}
async function main() {
// register exit handler
process.on('SIGINT', () => exit('sigint'));
process.on('SIGHUP', () => exit('sighup'));
process.on('SIGTERM', () => exit('sigterm'));
process.on('uncaughtException', (err) => error(err));
// load use configuration
config.init();
const cfg = config.get();
// configure logging
log.configure({ logFile: cfg.logFile, inspect: { breakLength: 1024 } });
log.headerJson();
// update dynamic dns
await noip.update(cfg.noip);
// check and auto-update certificates
log.info('SSL', cfg.ssl);
if (cfg?.acme?.domains?.length > 0) {
await acme.setConfig(cfg.acme);
const reverseRouteOK = await acme.testConnection(cfg.acme.domains[0]);
const cert = await acme.parseCert();
if (cert.account.error) log.warn('SSL Account', { code: cert?.account?.error?.code, syscall: cert?.account?.error?.syscall, path: cert?.account?.error?.path });
else log.info('SSL Account', { contact: cert.account.contact, status: cert.account.status, type: cert.accountKey.type, crv: cert.accountKey.crv });
if (cert.fullChain.error) log.warn('SSL Server', { code: cert?.fullChain?.error?.code, syscall: cert?.fullChain?.error?.syscall, path: cert?.fullChain?.error?.path });
else log.info('SSL Server', { subject: cert.fullChain.subject, issuer: cert.fullChain.issuer, algorithm: cert.fullChain.algorithm, from: cert.fullChain.notBefore, until: cert.fullChain.notAfter, type: cert.serverKey.type, use: cert.serverKey.use });
if (reverseRouteOK) {
await acme.getCert(); // validate & auto-renew
await acme.monitorCert(server.restartServer); // start ssl certificate monitoring for expiration
} else {
log.warn('No reverse route to server, skipping certificate monitoring and auto-renewal');
}
}
// load geoip database
await geoip.init(cfg.geoIP.city, cfg.geoIP.asn);
// start proxy server
await server.init(cfg.ssl); // Start actual redirector
// start server monitoring
await monitor.start();
}
main();