@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.
360 lines (308 loc) • 11.8 kB
text/typescript
import * as plugins from '../../../plugins.js';
// Certificate types removed - use local definition
import type { PortRange } from '../../../proxies/nftables-proxy/models/interfaces.js';
import type { IRouteContext } from '../../../core/models/route-context.js';
// Re-export IRouteContext for convenience
export type { IRouteContext };
/**
* Supported action types for route configurations
*/
export type TRouteActionType = 'forward' | 'socket-handler';
/**
* Socket handler function type
*/
export type TSocketHandler = (socket: plugins.net.Socket, context: IRouteContext) => void | Promise<void>;
/**
* TLS handling modes for route configurations
*/
export type TTlsMode = 'passthrough' | 'terminate' | 'terminate-and-reencrypt';
/**
* Port range specification format
*/
export type TPortRange = number | number[] | Array<{ from: number; to: number }>;
/**
* Route match criteria for incoming requests
*/
export interface IRouteMatch {
// Listen on these ports (required)
ports: TPortRange;
// Optional domain patterns to match (default: all domains)
domains?: string | string[];
// Advanced matching criteria
path?: string; // Match specific paths
clientIp?: string[]; // Match specific client IPs
tlsVersion?: string[]; // Match specific TLS versions
headers?: Record<string, string | RegExp>; // Match specific HTTP headers
}
/**
* Target-specific match criteria for sub-routing within a route
*/
export interface ITargetMatch {
ports?: number[]; // Match specific ports from the route
path?: string; // Match specific paths (supports wildcards like /api/*)
headers?: Record<string, string | RegExp>; // Match specific HTTP headers
method?: string[]; // Match specific HTTP methods (GET, POST, etc.)
}
/**
* Target configuration for forwarding with sub-matching and overrides
*/
export interface IRouteTarget {
// Optional sub-matching criteria within the route
match?: ITargetMatch;
// Target destination
host: string | string[] | ((context: IRouteContext) => string | string[]); // Host or hosts with optional function for dynamic resolution
port: number | 'preserve' | ((context: IRouteContext) => number); // Port with optional function for dynamic mapping (use 'preserve' to keep the incoming port)
// Optional target-specific overrides (these override route-level settings)
tls?: IRouteTls; // Override route-level TLS settings
websocket?: IRouteWebSocket; // Override route-level WebSocket settings
loadBalancing?: IRouteLoadBalancing; // Override route-level load balancing
sendProxyProtocol?: boolean; // Override route-level proxy protocol setting
headers?: IRouteHeaders; // Override route-level headers
advanced?: IRouteAdvanced; // Override route-level advanced settings
// Priority for matching (higher values are checked first, default: 0)
priority?: number;
}
/**
* ACME configuration for automatic certificate provisioning
*/
export interface IRouteAcme {
email: string; // Contact email for ACME account
useProduction?: boolean; // Use production ACME servers (default: false)
challengePort?: number; // Port for HTTP-01 challenges (default: 80)
renewBeforeDays?: number; // Days before expiry to renew (default: 30)
}
/**
* TLS configuration for route actions
*/
export interface IRouteTls {
mode: TTlsMode;
certificate?: 'auto' | { // Auto = use ACME
key: string; // PEM-encoded private key
cert: string; // PEM-encoded certificate
ca?: string; // PEM-encoded CA chain
keyFile?: string; // Path to key file (overrides key)
certFile?: string; // Path to cert file (overrides cert)
};
acme?: IRouteAcme; // ACME options when certificate is 'auto'
versions?: string[]; // Allowed TLS versions (e.g., ['TLSv1.2', 'TLSv1.3'])
ciphers?: string; // OpenSSL cipher string
honorCipherOrder?: boolean; // Use server's cipher preferences
sessionTimeout?: number; // TLS session timeout in seconds
}
/**
* Authentication options
*/
export interface IRouteAuthentication {
type: 'basic' | 'digest' | 'oauth' | 'jwt';
credentials?: {
username: string;
password: string;
}[];
realm?: string;
jwtSecret?: string;
jwtIssuer?: string;
oauthProvider?: string;
oauthClientId?: string;
oauthClientSecret?: string;
oauthRedirectUri?: string;
// Specific options for different auth types
options?: Record<string, unknown>;
}
/**
* Security options for routes
*/
export interface IRouteSecurity {
// Access control lists
ipAllowList?: string[]; // IP addresses that are allowed to connect
ipBlockList?: string[]; // IP addresses that are blocked from connecting
// Connection limits
maxConnections?: number; // Maximum concurrent connections
// Authentication
authentication?: IRouteAuthentication;
// Rate limiting
rateLimit?: IRouteRateLimit;
// Authentication methods
basicAuth?: {
enabled: boolean;
users: Array<{ username: string; password: string }>;
realm?: string;
excludePaths?: string[];
};
jwtAuth?: {
enabled: boolean;
secret: string;
algorithm?: string;
issuer?: string;
audience?: string;
expiresIn?: number;
excludePaths?: string[];
};
}
/**
* Static file server configuration
*/
export interface IRouteStaticFiles {
root: string;
index?: string[];
headers?: Record<string, string>;
directory?: string;
indexFiles?: string[];
cacheControl?: string;
expires?: number;
followSymlinks?: boolean;
disableDirectoryListing?: boolean;
}
/**
* Test route response configuration
*/
export interface IRouteTestResponse {
status: number;
headers: Record<string, string>;
body: string;
}
/**
* URL rewriting configuration
*/
export interface IRouteUrlRewrite {
pattern: string; // RegExp pattern to match in URL
target: string; // Replacement pattern (supports template variables like {domain})
flags?: string; // RegExp flags like 'g' for global replacement
onlyRewritePath?: boolean; // Only apply to path, not query string
}
/**
* Advanced options for route actions
*/
export interface IRouteAdvanced {
timeout?: number;
headers?: Record<string, string>;
keepAlive?: boolean;
staticFiles?: IRouteStaticFiles;
testResponse?: IRouteTestResponse;
urlRewrite?: IRouteUrlRewrite; // URL rewriting configuration
// Additional advanced options would go here
}
/**
* WebSocket configuration
*/
export interface IRouteWebSocket {
enabled: boolean; // Whether WebSockets are enabled for this route
pingInterval?: number; // Interval for sending ping frames (ms)
pingTimeout?: number; // Timeout for pong response (ms)
maxPayloadSize?: number; // Maximum message size in bytes
customHeaders?: Record<string, string>; // Custom headers for WebSocket handshake
subprotocols?: string[]; // Supported subprotocols
rewritePath?: string; // Path rewriting for WebSocket connections
allowedOrigins?: string[]; // Allowed origins for WebSocket connections
authenticateRequest?: boolean; // Whether to apply route security to WebSocket connections
}
/**
* Load balancing configuration
*/
export interface IRouteLoadBalancing {
algorithm: 'round-robin' | 'least-connections' | 'ip-hash';
healthCheck?: {
path: string;
interval: number;
timeout: number;
unhealthyThreshold: number;
healthyThreshold: number;
};
}
/**
* Action configuration for route handling
*/
export interface IRouteAction {
// Basic routing
type: TRouteActionType;
// Targets for forwarding (array supports multiple targets with sub-matching)
// Required for 'forward' action type
targets?: IRouteTarget[];
// TLS handling (default for all targets, can be overridden per target)
tls?: IRouteTls;
// WebSocket support (default for all targets, can be overridden per target)
websocket?: IRouteWebSocket;
// Load balancing options (default for all targets, can be overridden per target)
loadBalancing?: IRouteLoadBalancing;
// Advanced options (default for all targets, can be overridden per target)
advanced?: IRouteAdvanced;
// Additional options for backend-specific settings
options?: {
backendProtocol?: 'http1' | 'http2';
[key: string]: any;
};
// Forwarding engine specification
forwardingEngine?: 'node' | 'nftables';
// NFTables-specific options
nftables?: INfTablesOptions;
// Socket handler function (when type is 'socket-handler')
socketHandler?: TSocketHandler;
// PROXY protocol support (default for all targets, can be overridden per target)
sendProxyProtocol?: boolean;
}
/**
* Rate limiting configuration
*/
export interface IRouteRateLimit {
enabled: boolean;
maxRequests: number;
window: number; // Time window in seconds
keyBy?: 'ip' | 'path' | 'header';
headerName?: string;
errorMessage?: string;
}
// IRouteSecurity is defined above - unified definition is used for all routes
/**
* NFTables-specific configuration options
*/
export interface INfTablesOptions {
preserveSourceIP?: boolean; // Preserve original source IP address
protocol?: 'tcp' | 'udp' | 'all'; // Protocol to forward
maxRate?: string; // QoS rate limiting (e.g. "10mbps")
priority?: number; // QoS priority (1-10, lower is higher priority)
tableName?: string; // Optional custom table name
useIPSets?: boolean; // Use IP sets for performance
useAdvancedNAT?: boolean; // Use connection tracking for stateful NAT
}
/**
* CORS configuration for a route
*/
export interface IRouteCors {
enabled: boolean; // Whether CORS is enabled for this route
allowOrigin?: string | string[]; // Allowed origins (*,domain.com,[domain1,domain2])
allowMethods?: string; // Allowed methods (GET,POST,etc.)
allowHeaders?: string; // Allowed headers
allowCredentials?: boolean; // Whether to allow credentials
exposeHeaders?: string; // Headers to expose to the client
maxAge?: number; // Preflight cache duration in seconds
preflight?: boolean; // Whether to respond to preflight requests
}
/**
* Headers configuration
*/
export interface IRouteHeaders {
request?: Record<string, string>; // Headers to add/modify for requests to backend
response?: Record<string, string>; // Headers to add/modify for responses to client
cors?: IRouteCors; // CORS configuration
}
/**
* The core unified configuration interface
*/
export interface IRouteConfig {
// Unique identifier
id?: string;
// What to match
match: IRouteMatch;
// What to do with matched traffic
action: IRouteAction;
// Custom headers
headers?: IRouteHeaders;
// Security features
security?: IRouteSecurity;
// Optional metadata
name?: string; // Human-readable name for this route
description?: string; // Description of the route's purpose
priority?: number; // Controls matching order (higher = matched first)
tags?: string[]; // Arbitrary tags for categorization
enabled?: boolean; // Whether the route is active (default: true)
}
// Configuration moved to models/interfaces.ts as ISmartProxyOptions