@push.rocks/smartproxy
Version:
A powerful proxy package with unified route-based configuration for high traffic management. Features include SSL/TLS support, flexible routing patterns, WebSocket handling, advanced security options, and automatic ACME certificate management.
271 lines (270 loc) • 9.02 kB
TypeScript
import * as plugins from '../../../plugins.js';
import type { WrappedSocket } from '../../../core/models/wrapped-socket.js';
export interface IAcmeOptions {
enabled?: boolean;
email?: string;
environment?: 'production' | 'staging';
accountEmail?: string;
port?: number;
useProduction?: boolean;
renewThresholdDays?: number;
autoRenew?: boolean;
skipConfiguredCerts?: boolean;
renewCheckIntervalHours?: number;
routeForwards?: any[];
}
/**
* Consumer-provided certificate storage.
* SmartProxy never writes certs to disk — the consumer owns all persistence.
*/
export interface ISmartProxyCertStore {
/** Load all stored certs on startup (called once before cert provisioning) */
loadAll: () => Promise<Array<{
domain: string;
publicKey: string;
privateKey: string;
ca?: string;
}>>;
/** Save a cert after successful provisioning */
save: (domain: string, publicKey: string, privateKey: string, ca?: string) => Promise<void>;
/** Remove a cert (optional) */
remove?: (domain: string) => Promise<void>;
}
import type { IRouteConfig } from './route-types.js';
export interface ISmartProxySecurityPolicy {
blockedIps?: string[];
blockedCidrs?: string[];
}
export interface ISmartProxyChallengeOptions {
/** Runtime-only cookie signing key. If omitted, SmartProxy generates an ephemeral key. */
cookieSigningKey?: string;
pendingCookieName?: string;
clearanceCookieName?: string;
reservedPathPrefix?: string;
relaySocketPath?: string;
relayTimeoutMs?: number;
pendingTtlSeconds?: number;
}
/**
* Provision object for static or HTTP-01 certificate
*/
export interface ISmartProxyCertProvisionCertificate extends plugins.tsclass.network.ICert {
ca?: string;
}
export type TSmartProxyCertProvisionObject = ISmartProxyCertProvisionCertificate | 'http01';
/**
* Communication channel passed as second argument to certProvisionFunction.
* Allows the callback to report metadata back to SmartProxy for event emission.
*/
export interface ICertProvisionEventComms {
/** Informational log */
log: (message: string) => void;
/** Warning (non-fatal) */
warn: (message: string) => void;
/** Error */
error: (message: string) => void;
/** Set the certificate expiry date (for the issued event) */
setExpiryDate: (date: Date) => void;
/** Set the source/method used for provisioning (e.g. 'smartacme-dns-01') */
setSource: (source: string) => void;
}
/** Payload for 'certificate-issued' and 'certificate-renewed' events */
export interface ICertificateIssuedEvent {
domain: string;
expiryDate?: string;
source: string;
isRenewal?: boolean;
}
/** Payload for 'certificate-failed' event */
export interface ICertificateFailedEvent {
domain: string;
error: string;
source: string;
}
export interface IActiveConnectionSnapshotOptions {
/** Maximum number of snapshots to return. Defaults to 1000, capped by Rust at 10000. */
limit?: number;
/** Optional route id filter. */
routeId?: string;
}
export interface IActiveConnectionSnapshot {
id: number;
sourceIp: string;
sourcePort: number | null;
localPort: number;
domain: string | null;
routeId: string | null;
targetHost: string | null;
targetPort: number | null;
protocol: string | null;
state: string;
startedAtMs: number;
ageMs: number;
bytesIn: number;
bytesOut: number;
}
/**
* SmartProxy configuration options
*/
export interface ISmartProxyOptions {
routes: IRouteConfig[];
preserveSourceIP?: boolean;
trustedProxyIPs?: string[];
sendProxyProtocol?: boolean;
defaults?: {
target?: {
host: string;
port: number;
};
security?: {
ipAllowList?: string[];
ipBlockList?: string[];
maxConnections?: number;
};
preserveSourceIP?: boolean;
};
pfx?: Buffer;
key?: string | Buffer | Array<Buffer | string>;
passphrase?: string;
cert?: string | Buffer | Array<string | Buffer>;
ca?: string | Buffer | Array<string | Buffer>;
ciphers?: string;
honorCipherOrder?: boolean;
rejectUnauthorized?: boolean;
secureProtocol?: string;
servername?: string;
minVersion?: string;
maxVersion?: string;
connectionTimeout?: number;
initialDataTimeout?: number;
socketTimeout?: number;
inactivityCheckInterval?: number;
maxConnectionLifetime?: number;
inactivityTimeout?: number;
gracefulShutdownTimeout?: number;
noDelay?: boolean;
keepAlive?: boolean;
keepAliveInitialDelay?: number;
maxPendingDataSize?: number;
disableInactivityCheck?: boolean;
enableKeepAliveProbes?: boolean;
enableDetailedLogging?: boolean;
enableTlsDebugLogging?: boolean;
enableRandomizedTimeouts?: boolean;
maxConnectionsPerIP?: number;
connectionRateLimitPerMinute?: number;
securityPolicy?: ISmartProxySecurityPolicy;
/** Runtime-only challenge enforcement settings. Never store this in route configs. */
challenge?: ISmartProxyChallengeOptions;
keepAliveTreatment?: 'standard' | 'extended' | 'immortal';
keepAliveInactivityMultiplier?: number;
extendedKeepAliveLifetime?: number;
metrics?: {
enabled?: boolean;
sampleIntervalMs?: number;
retentionSeconds?: number;
};
/**
* Global ACME configuration options for SmartProxy
*
* When set, these options will be used as defaults for all routes
* with certificate: 'auto' that don't have their own ACME configuration.
* Route-specific ACME settings will override these defaults.
*
* Example:
* ```ts
* acme: {
* email: 'ssl@example.com',
* useProduction: false,
* port: 80
* }
* ```
*/
acme?: IAcmeOptions;
/**
* Optional certificate provider callback. Return 'http01' to use HTTP-01 challenges,
* or a static certificate object for immediate provisioning.
*/
certProvisionFunction?: (domain: string, eventComms: ICertProvisionEventComms) => Promise<TSmartProxyCertProvisionObject>;
/**
* Whether to fallback to ACME if custom certificate provision fails.
* Default: true
*/
certProvisionFallbackToAcme?: boolean;
/**
* Per-domain timeout in ms for certProvisionFunction calls.
* If a single domain's provisioning takes longer than this, it's aborted
* and a certificate-failed event is emitted.
* Default: 300000 (5 minutes)
*/
certProvisionTimeout?: number;
/**
* Maximum number of domains to provision certificates for concurrently.
* Prevents overwhelming ACME providers when many domains provision at once.
* Default: 4
*/
certProvisionConcurrency?: number;
/**
* Disable the default self-signed fallback certificate.
* When false (default), a self-signed cert is generated at startup and loaded
* as '*' so TLS handshakes never fail due to missing certs.
*/
disableDefaultCert?: boolean;
/**
* Consumer-provided cert storage. SmartProxy never writes certs to disk.
* On startup, loadAll() is called to pre-load persisted certs.
* After each successful cert provision, save() is called.
*/
certStore?: ISmartProxyCertStore;
/**
* Path to the RustProxy binary. If not set, the binary is located
* automatically via env var, platform package, local build, or PATH.
*/
rustBinaryPath?: string;
}
export type TChallengeProviderRegistry = Map<string, plugins.smartchallenge.IChallengeProvider>;
/**
* Enhanced connection record
*/
export interface IConnectionRecord {
id: string;
incoming: plugins.net.Socket | WrappedSocket;
outgoing: plugins.net.Socket | WrappedSocket | null;
incomingStartTime: number;
outgoingStartTime?: number;
outgoingClosedTime?: number;
lockedDomain?: string;
connectionClosed: boolean;
cleanupTimer?: NodeJS.Timeout | null;
alertFallbackTimeout?: NodeJS.Timeout;
lastActivity: number;
pendingData: Buffer[];
pendingDataSize: number;
bytesReceived: number;
bytesSent: number;
remoteIP: string;
remotePort: number;
localPort: number;
isTLS: boolean;
tlsHandshakeComplete: boolean;
hasReceivedInitialData: boolean;
routeConfig?: IRouteConfig;
routeId?: string;
targetHost?: string;
targetPort?: number;
tlsVersion?: string;
hasKeepAlive: boolean;
inactivityWarningIssued?: boolean;
incomingTerminationReason?: string | null;
outgoingTerminationReason?: string | null;
usingNetworkProxy?: boolean;
renegotiationHandler?: (chunk: Buffer) => void;
isBrowserConnection?: boolean;
domainSwitches?: number;
nftablesHandled?: boolean;
httpInfo?: {
method?: string;
path?: string;
headers?: Record<string, string>;
};
}