# @push.rocks/smartproxy ๐Ÿš€ **A high-performance, Rust-powered proxy toolkit for Node.js** โ€” unified route-based configuration for SSL/TLS termination, HTTP/HTTPS reverse proxying, WebSocket support, load balancing, custom protocol handlers, and kernel-level NFTables forwarding. ## ๐Ÿ“ฆ Installation ```bash npm install @push.rocks/smartproxy # or pnpm add @push.rocks/smartproxy ``` ## Issue Reporting and Security For reporting bugs, issues, or security vulnerabilities, please visit [community.foss.global/](https://community.foss.global/). This is the central community hub for all issue reporting. Developers who sign and comply with our contribution agreement and go through identification can also get a [code.foss.global/](https://code.foss.global/) account to submit Pull Requests directly. ## ๐ŸŽฏ What is SmartProxy? SmartProxy is a production-ready proxy solution that takes the complexity out of traffic management. Under the hood, all networking โ€” TCP, TLS, HTTP reverse proxy, connection tracking, security enforcement, and NFTables โ€” is handled by a **Rust engine** for maximum performance, while you configure everything through a clean TypeScript API with full type safety. Whether you're building microservices, deploying edge infrastructure, or need a battle-tested reverse proxy with automatic Let's Encrypt certificates, SmartProxy has you covered. ### โšก Key Features | Feature | Description | |---------|-------------| | ๐Ÿฆ€ **Rust-Powered Engine** | All networking handled by a high-performance Rust binary via IPC | | ๐Ÿ”€ **Unified Route-Based Config** | Clean match/action patterns for intuitive traffic routing | | ๐Ÿ”’ **Automatic SSL/TLS** | Zero-config HTTPS with Let's Encrypt ACME integration | | ๐ŸŽฏ **Flexible Matching** | Route by port, domain, path, protocol, client IP, TLS version, headers, or custom logic | | ๐Ÿš„ **High-Performance** | Choose between user-space or kernel-level (NFTables) forwarding | | โš–๏ธ **Load Balancing** | Round-robin, least-connections, IP-hash with health checks | | ๐Ÿ›ก๏ธ **Enterprise Security** | IP filtering, rate limiting, basic auth, JWT auth, connection limits | | ๐Ÿ”Œ **WebSocket Support** | First-class WebSocket proxying with ping/pong keep-alive | | ๐ŸŽฎ **Custom Protocols** | Socket handlers for implementing any protocol in TypeScript | | ๐Ÿ“Š **Live Metrics** | Real-time throughput, connection counts, and performance data | | ๐Ÿ”ง **Dynamic Management** | Add/remove ports and routes at runtime without restarts | | ๐Ÿ”„ **PROXY Protocol** | Full PROXY protocol v1/v2 support for preserving client information | | ๐Ÿ’พ **Consumer Cert Storage** | Bring your own persistence โ€” SmartProxy never writes certs to disk | ## ๐Ÿš€ Quick Start Get up and running in 30 seconds: ```typescript import { SmartProxy, createCompleteHttpsServer } from '@push.rocks/smartproxy'; // Create a proxy with automatic HTTPS const proxy = new SmartProxy({ acme: { email: 'ssl@yourdomain.com', useProduction: true }, routes: [ // Complete HTTPS setup in one call! โœจ ...createCompleteHttpsServer('app.example.com', { host: 'localhost', port: 3000 }, { certificate: 'auto' // Automatic Let's Encrypt cert ๐ŸŽฉ }) ] }); await proxy.start(); console.log('๐Ÿš€ Proxy running with automatic HTTPS!'); ``` ## ๐Ÿ“š Core Concepts ### ๐Ÿ—๏ธ Route-Based Architecture SmartProxy uses a powerful **match/action** pattern that makes routing predictable and maintainable: ```typescript { name: 'api-route', match: { ports: 443, domains: 'api.example.com', path: '/v1/*' }, action: { type: 'forward', targets: [{ host: 'backend', port: 8080 }], tls: { mode: 'terminate', certificate: 'auto' } } } ``` Every route consists of: - **Match** โ€” What traffic to capture (ports, domains, paths, protocol, IPs, headers) - **Action** โ€” What to do with it (`forward` or `socket-handler`) - **Security** (optional) โ€” IP allow/block lists, rate limits, authentication - **Headers** (optional) โ€” Request/response header manipulation with template variables - **Name/Priority** (optional) โ€” For identification and ordering ### ๐Ÿ”„ TLS Modes SmartProxy supports three TLS handling modes: | Mode | Description | Use Case | |------|-------------|----------| | `passthrough` | Forward encrypted traffic as-is (SNI-based routing) | Backend handles TLS | | `terminate` | Decrypt at proxy, forward plain HTTP to backend | Standard reverse proxy | | `terminate-and-reencrypt` | Decrypt at proxy, re-encrypt to backend. HTTP traffic gets full per-request routing (Host header, path matching) via the HTTP proxy; non-HTTP traffic uses a raw TLS-to-TLS tunnel | Zero-trust / defense-in-depth environments | ## ๐Ÿ’ก Common Use Cases ### ๐ŸŒ HTTP to HTTPS Redirect ```typescript import { SmartProxy, createHttpToHttpsRedirect } from '@push.rocks/smartproxy'; const proxy = new SmartProxy({ routes: [ createHttpToHttpsRedirect(['example.com', '*.example.com']) ] }); ``` ### โš–๏ธ Load Balancer with Health Checks ```typescript import { SmartProxy, createLoadBalancerRoute } from '@push.rocks/smartproxy'; const proxy = new SmartProxy({ routes: [ createLoadBalancerRoute( 'app.example.com', [ { host: 'server1.internal', port: 8080 }, { host: 'server2.internal', port: 8080 }, { host: 'server3.internal', port: 8080 } ], { tls: { mode: 'terminate', certificate: 'auto' }, algorithm: 'round-robin', healthCheck: { path: '/health', interval: 30000, timeout: 5000, unhealthyThreshold: 3, healthyThreshold: 2 } } ) ] }); ``` ### ๐Ÿ”Œ WebSocket Proxy ```typescript import { SmartProxy, createWebSocketRoute } from '@push.rocks/smartproxy'; const proxy = new SmartProxy({ routes: [ createWebSocketRoute( 'ws.example.com', { host: 'websocket-server', port: 8080 }, { path: '/socket', useTls: true, certificate: 'auto', pingInterval: 30000, pingTimeout: 10000 } ) ] }); ``` ### ๐Ÿšฆ API Gateway with Rate Limiting ```typescript import { SmartProxy, createApiGatewayRoute, addRateLimiting } from '@push.rocks/smartproxy'; let apiRoute = createApiGatewayRoute( 'api.example.com', '/api', { host: 'api-backend', port: 8080 }, { useTls: true, certificate: 'auto', addCorsHeaders: true } ); // Add rate limiting โ€” 100 requests per minute per IP apiRoute = addRateLimiting(apiRoute, { maxRequests: 100, window: 60, keyBy: 'ip' }); const proxy = new SmartProxy({ routes: [apiRoute] }); ``` ### ๐ŸŽฎ Custom Protocol Handler SmartProxy lets you implement any protocol with full socket control. Routes with JavaScript socket handlers are automatically relayed from the Rust engine back to your TypeScript code: ```typescript import { SmartProxy, createSocketHandlerRoute, SocketHandlers } from '@push.rocks/smartproxy'; // Use pre-built handlers const echoRoute = createSocketHandlerRoute( 'echo.example.com', 7777, SocketHandlers.echo ); // Or create your own custom protocol const customRoute = createSocketHandlerRoute( 'custom.example.com', 9999, async (socket) => { console.log(`New connection on custom protocol`); socket.write('Welcome to my custom protocol!\n'); socket.on('data', (data) => { const command = data.toString().trim(); switch (command) { case 'PING': socket.write('PONG\n'); break; case 'TIME': socket.write(`${new Date().toISOString()}\n`); break; case 'QUIT': socket.end('Goodbye!\n'); break; default: socket.write(`Unknown: ${command}\n`); } }); } ); const proxy = new SmartProxy({ routes: [echoRoute, customRoute] }); ``` **Pre-built Socket Handlers:** | Handler | Description | |---------|-------------| | `SocketHandlers.echo` | Echo server โ€” returns everything sent | | `SocketHandlers.proxy(host, port)` | TCP proxy to another server | | `SocketHandlers.lineProtocol(handler)` | Line-based text protocol | | `SocketHandlers.httpResponse(code, body)` | Simple HTTP response | | `SocketHandlers.httpRedirect(url, code)` | HTTP redirect with template variables (`{domain}`, `{path}`, `{port}`, `{clientIp}`) | | `SocketHandlers.httpServer(handler)` | Full HTTP request/response handling | | `SocketHandlers.httpBlock(status, message)` | HTTP block response | | `SocketHandlers.block(message)` | Block with optional message | ### โšก High-Performance NFTables Forwarding For ultra-low latency on Linux, use kernel-level forwarding (requires root): ```typescript import { SmartProxy, createNfTablesTerminateRoute } from '@push.rocks/smartproxy'; const proxy = new SmartProxy({ routes: [ createNfTablesTerminateRoute( 'fast.example.com', { host: 'backend', port: 8080 }, { ports: 443, certificate: 'auto', preserveSourceIP: true // Backend sees real client IP } ) ] }); ``` ### ๐Ÿ”’ SNI Passthrough (TLS Passthrough) Forward encrypted traffic to backends without terminating TLS โ€” the proxy routes based on the SNI hostname alone: ```typescript import { SmartProxy, createHttpsPassthroughRoute } from '@push.rocks/smartproxy'; const proxy = new SmartProxy({ routes: [ createHttpsPassthroughRoute('secure.example.com', { host: 'backend-that-handles-tls', port: 8443 }) ] }); ``` ## ๐Ÿ”ง Advanced Features ### ๐ŸŽฏ Dynamic Routing Route traffic based on runtime conditions using function-based host/port resolution: ```typescript const proxy = new SmartProxy({ routes: [{ name: 'dynamic-backend', match: { ports: 443, domains: 'app.example.com' }, action: { type: 'forward', targets: [{ host: (context) => { return context.path?.startsWith('/premium') ? 'premium-backend' : 'standard-backend'; }, port: 8080 }], tls: { mode: 'terminate', certificate: 'auto' } } }] }); ``` > **Note:** Routes with dynamic functions (host/port callbacks) are automatically relayed through the TypeScript socket handler server, since JavaScript functions can't be serialized to Rust. ### ๐Ÿ”€ Protocol-Specific Routing Restrict routes to specific application-layer protocols. When `protocol` is set, the Rust engine detects the protocol after connection (or after TLS termination) and only matches routes that accept that protocol: ```typescript // HTTP-only route (rejects raw TCP connections) const httpOnlyRoute: IRouteConfig = { name: 'http-api', match: { ports: 443, domains: 'api.example.com', protocol: 'http', // Only match HTTP/1.1, HTTP/2, and WebSocket upgrades }, action: { type: 'forward', targets: [{ host: 'api-backend', port: 8080 }], tls: { mode: 'terminate', certificate: 'auto' } } }; // Raw TCP route (rejects HTTP traffic) const tcpOnlyRoute: IRouteConfig = { name: 'database-proxy', match: { ports: 5432, protocol: 'tcp', // Only match non-HTTP TCP streams }, action: { type: 'forward', targets: [{ host: 'db-server', port: 5432 }] } }; ``` > **Note:** Omitting `protocol` (the default) matches any protocol. For TLS routes, protocol detection happens *after* TLS termination โ€” during the initial SNI-based route match, `protocol` is not yet known and the route is allowed to match. The protocol restriction is enforced after the proxy peeks at the decrypted data. ### ๐Ÿ”’ Security Controls Comprehensive per-route security options: ```typescript { name: 'secure-api', match: { ports: 443, domains: 'api.example.com' }, action: { type: 'forward', targets: [{ host: 'api-backend', port: 8080 }], tls: { mode: 'terminate', certificate: 'auto' } }, security: { // IP-based access control ipAllowList: ['10.0.0.0/8', '192.168.*'], ipBlockList: ['192.168.1.100'], // Connection limits maxConnections: 1000, // Rate limiting rateLimit: { enabled: true, maxRequests: 100, window: 60 }, // Authentication basicAuth: { users: [{ username: 'admin', password: 'secret' }] }, jwtAuth: { secret: 'your-jwt-secret', algorithm: 'HS256' } } } ``` **Security modifier helpers** let you add security to any existing route: ```typescript import { addRateLimiting, addBasicAuth, addJwtAuth } from '@push.rocks/smartproxy'; let route = createHttpsTerminateRoute('api.example.com', { host: 'backend', port: 8080 }); route = addRateLimiting(route, { maxRequests: 100, window: 60, keyBy: 'ip' }); route = addBasicAuth(route, { users: [{ username: 'admin', password: 'secret' }] }); ``` ### ๐Ÿ“Š Runtime Management Control your proxy without restarts: ```typescript // Dynamic port management await proxy.addListeningPort(8443); await proxy.removeListeningPort(8080); const ports = await proxy.getListeningPorts(); // Update routes on the fly (atomic, mutex-locked) await proxy.updateRoutes([...newRoutes]); // Get real-time metrics const metrics = proxy.getMetrics(); console.log(`Active connections: ${metrics.connections.active()}`); console.log(`Bytes in: ${metrics.totals.bytesIn()}`); console.log(`Requests/sec: ${metrics.requests.perSecond()}`); console.log(`Throughput in: ${metrics.throughput.instant().in} bytes/sec`); // Get detailed statistics from the Rust engine const stats = await proxy.getStatistics(); // Certificate management await proxy.provisionCertificate('my-route-name'); await proxy.renewCertificate('my-route-name'); const certStatus = await proxy.getCertificateStatus('my-route-name'); // NFTables status const nftStatus = await proxy.getNfTablesStatus(); ``` ### ๐Ÿ”„ Header Manipulation Transform requests and responses with template variables: ```typescript { action: { type: 'forward', targets: [{ host: 'backend', port: 8080 }] }, headers: { request: { 'X-Real-IP': '{clientIp}', 'X-Request-ID': '{uuid}', 'X-Forwarded-Proto': 'https' }, response: { 'Strict-Transport-Security': 'max-age=31536000', 'X-Frame-Options': 'DENY' } } } ``` ### ๐Ÿ”€ PROXY Protocol Support Preserve original client information through proxy chains: ```typescript const proxy = new SmartProxy({ // Accept PROXY protocol from trusted load balancers acceptProxyProtocol: true, proxyIPs: ['10.0.0.1', '10.0.0.2'], // Forward PROXY protocol to backends sendProxyProtocol: true, routes: [...] }); ``` ### ๐Ÿ—๏ธ Custom Certificate Provisioning Supply your own certificates or integrate with external certificate providers: ```typescript const proxy = new SmartProxy({ certProvisionFunction: async (domain: string) => { // Return 'http01' to let the built-in ACME handle it if (domain.endsWith('.example.com')) return 'http01'; // Or return a static certificate object return { publicKey: myPemCert, privateKey: myPemKey, }; }, certProvisionFallbackToAcme: true, // Fall back to ACME if callback fails routes: [...] }); ``` ### ๐Ÿ’พ Consumer-Managed Certificate Storage SmartProxy **never writes certificates to disk**. Instead, you own all persistence through the `certStore` interface. This gives you full control โ€” store certs in a database, cloud KMS, encrypted vault, or wherever makes sense for your infrastructure: ```typescript const proxy = new SmartProxy({ routes: [...], certProvisionFunction: async (domain) => myAcme.provision(domain), // Your persistence layer โ€” SmartProxy calls these hooks certStore: { // Called once on startup to pre-load persisted certs loadAll: async () => { const certs = await myDb.getAllCerts(); return certs.map(c => ({ domain: c.domain, publicKey: c.certPem, privateKey: c.keyPem, ca: c.caPem, // optional })); }, // Called after each successful cert provision save: async (domain, publicKey, privateKey, ca) => { await myDb.upsertCert({ domain, certPem: publicKey, keyPem: privateKey, caPem: ca }); }, // Optional: called when a cert should be removed remove: async (domain) => { await myDb.deleteCert(domain); }, }, }); ``` **Startup flow:** 1. Rust engine starts 2. Default self-signed `*` fallback cert is loaded (unless `disableDefaultCert: true`) 3. `certStore.loadAll()` is called โ†’ all returned certs are loaded into the Rust TLS stack 4. `certProvisionFunction` runs for any remaining `certificate: 'auto'` routes (skipping domains already loaded from the store) 5. After each successful provision, `certStore.save()` is called This means your second startup is instant โ€” no re-provisioning needed for domains that already have valid certs in your store. ## ๐Ÿ›๏ธ Architecture SmartProxy uses a hybrid **Rust + TypeScript** architecture: ``` โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ”‚ Your Application โ”‚ โ”‚ (TypeScript โ€” routes, config, socket handlers) โ”‚ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ โ”‚ IPC (JSON over stdin/stdout) โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ–ผโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ”‚ Rust Proxy Engine โ”‚ โ”‚ โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ”‚ โ”‚ โ”‚ TCP/TLS โ”‚ โ”‚ HTTP โ”‚ โ”‚ Route โ”‚ โ”‚ ACME โ”‚ โ”‚ โ”‚ โ”‚ Listenerโ”‚ โ”‚ Reverse โ”‚ โ”‚ Matcher โ”‚ โ”‚ Cert Mgr โ”‚ โ”‚ โ”‚ โ”‚ โ”‚ โ”‚ Proxy โ”‚ โ”‚ โ”‚ โ”‚ โ”‚ โ”‚ โ”‚ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ โ”‚ โ”‚ โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ”‚ โ”‚ โ”‚ Securityโ”‚ โ”‚ Metrics โ”‚ โ”‚ Connec- โ”‚ โ”‚ NFTables โ”‚ โ”‚ โ”‚ โ”‚ Enforce โ”‚ โ”‚ Collect โ”‚ โ”‚ tion โ”‚ โ”‚ Mgr โ”‚ โ”‚ โ”‚ โ”‚ โ”‚ โ”‚ โ”‚ โ”‚ Tracker โ”‚ โ”‚ โ”‚ โ”‚ โ”‚ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ โ”‚ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ โ”‚ Unix Socket Relay โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ–ผโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ”‚ TypeScript Socket Handler Server โ”‚ โ”‚ (for JS-defined socket handlers & dynamic routes) โ”‚ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ ``` - **Rust Engine** handles all networking, TLS, HTTP proxying, connection management, security, and metrics - **TypeScript** provides the npm API, configuration types, route helpers, validation, and socket handler callbacks - **IPC** โ€” The TypeScript wrapper uses JSON commands/events over stdin/stdout to communicate with the Rust binary - **Socket Relay** โ€” A Unix domain socket server for routes requiring TypeScript-side handling (socket handlers, dynamic host/port functions) ## ๐ŸŽฏ Route Configuration Reference ### Match Criteria ```typescript interface IRouteMatch { ports: number | number[] | Array<{ from: number; to: number }>; // Required โ€” port(s) to listen on domains?: string | string[]; // 'example.com', '*.example.com' path?: string; // '/api/*', '/users/:id' clientIp?: string[]; // ['10.0.0.0/8', '192.168.*'] tlsVersion?: string[]; // ['TLSv1.2', 'TLSv1.3'] headers?: Record; // Match by HTTP headers protocol?: 'http' | 'tcp'; // Match specific protocol ('http' includes h2 + WebSocket upgrades) } ``` ### Action Types | Type | Description | |------|-------------| | `forward` | Proxy to one or more backend targets (with optional TLS, WebSocket, load balancing) | | `socket-handler` | Custom socket handling function in TypeScript | ### Target Options ```typescript interface IRouteTarget { host: string | string[] | ((context: IRouteContext) => string | string[]); port: number | 'preserve' | ((context: IRouteContext) => number); tls?: IRouteTls; // Per-target TLS override priority?: number; // Target priority match?: ITargetMatch; // Sub-match within a route (by port, path, headers, method) websocket?: IRouteWebSocket; loadBalancing?: IRouteLoadBalancing; sendProxyProtocol?: boolean; headers?: IRouteHeaders; advanced?: IRouteAdvanced; } ``` ### TLS Options ```typescript interface IRouteTls { mode: 'passthrough' | 'terminate' | 'terminate-and-reencrypt'; certificate?: 'auto' | { key: string; cert: string; ca?: string; keyFile?: string; certFile?: string; }; acme?: { email: string; useProduction?: boolean; challengePort?: number; renewBeforeDays?: number; }; versions?: string[]; ciphers?: string; honorCipherOrder?: boolean; sessionTimeout?: number; } ``` ### WebSocket Options ```typescript interface IRouteWebSocket { enabled: boolean; pingInterval?: number; // ms between pings pingTimeout?: number; // ms to wait for pong maxPayloadSize?: number; // Maximum frame payload subprotocols?: string[]; // Allowed subprotocols allowedOrigins?: string[]; // CORS origins } ``` ### Load Balancing Options ```typescript interface IRouteLoadBalancing { algorithm: 'round-robin' | 'least-connections' | 'ip-hash'; healthCheck?: { path: string; interval: number; // ms timeout: number; // ms unhealthyThreshold: number; healthyThreshold: number; }; } ``` ## ๐Ÿ› ๏ธ Helper Functions Reference All helpers are fully typed and return `IRouteConfig` or `IRouteConfig[]`: ```typescript import { // HTTP/HTTPS createHttpRoute, // Plain HTTP route createHttpsTerminateRoute, // HTTPS with TLS termination createHttpsPassthroughRoute, // SNI passthrough (no termination) createHttpToHttpsRedirect, // HTTP โ†’ HTTPS redirect createCompleteHttpsServer, // HTTPS + redirect combo (returns IRouteConfig[]) // Load Balancing createLoadBalancerRoute, // Multi-backend with health checks createSmartLoadBalancer, // Dynamic domain-based backend selection // API & WebSocket createApiRoute, // API route with path matching createApiGatewayRoute, // API gateway with CORS createWebSocketRoute, // WebSocket-enabled route // Custom Protocols createSocketHandlerRoute, // Custom socket handler SocketHandlers, // Pre-built handlers (echo, proxy, block, etc.) // NFTables (Linux, requires root) createNfTablesRoute, // Kernel-level packet forwarding createNfTablesTerminateRoute, // NFTables + TLS termination createCompleteNfTablesHttpsServer, // NFTables HTTPS + redirect combo // Dynamic Routing createPortMappingRoute, // Port mapping with context createOffsetPortMappingRoute, // Simple port offset createDynamicRoute, // Dynamic host/port via functions createPortOffset, // Port offset factory // Security Modifiers addRateLimiting, // Add rate limiting to any route addBasicAuth, // Add basic auth to any route addJwtAuth, // Add JWT auth to any route // Route Utilities mergeRouteConfigs, // Deep-merge two route configs findMatchingRoutes, // Find routes matching criteria findBestMatchingRoute, // Find best matching route cloneRoute, // Deep-clone a route generateRouteId, // Generate deterministic route ID RouteValidator, // Validate route configurations } from '@push.rocks/smartproxy'; ``` ## ๐Ÿ“– API Documentation ### SmartProxy Class ```typescript class SmartProxy extends EventEmitter { constructor(options: ISmartProxyOptions); // Lifecycle start(): Promise; stop(): Promise; // Route Management (atomic, mutex-locked) updateRoutes(routes: IRouteConfig[]): Promise; // Port Management addListeningPort(port: number): Promise; removeListeningPort(port: number): Promise; getListeningPorts(): Promise; // Monitoring & Metrics getMetrics(): IMetrics; // Sync โ€” returns cached metrics adapter getStatistics(): Promise; // Async โ€” queries Rust engine // Certificate Management provisionCertificate(routeName: string): Promise; renewCertificate(routeName: string): Promise; getCertificateStatus(routeName: string): Promise; getEligibleDomainsForCertificates(): string[]; // NFTables getNfTablesStatus(): Promise>; // Events on(event: 'error', handler: (err: Error) => void): this; } ``` ### Configuration Options ```typescript interface ISmartProxyOptions { routes: IRouteConfig[]; // Required: array of route configs // ACME/Let's Encrypt acme?: { email: string; // Contact email for Let's Encrypt useProduction?: boolean; // Use production servers (default: false) port?: number; // HTTP-01 challenge port (default: 80) renewThresholdDays?: number; // Days before expiry to renew (default: 30) autoRenew?: boolean; // Enable auto-renewal (default: true) renewCheckIntervalHours?: number; // Renewal check interval (default: 24) }; // Custom certificate provisioning certProvisionFunction?: (domain: string) => Promise; certProvisionFallbackToAcme?: boolean; // Fall back to ACME on failure (default: true) // Consumer-managed certificate persistence (see "Consumer-Managed Certificate Storage") certStore?: ISmartProxyCertStore; // Self-signed fallback disableDefaultCert?: boolean; // Disable '*' self-signed fallback (default: false) // Global defaults defaults?: { target?: { host: string; port: number }; security?: { ipAllowList?: string[]; ipBlockList?: string[]; maxConnections?: number }; }; // PROXY protocol proxyIPs?: string[]; // Trusted proxy IPs acceptProxyProtocol?: boolean; // Accept PROXY protocol headers sendProxyProtocol?: boolean; // Send PROXY protocol to targets // Timeouts connectionTimeout?: number; // Backend connection timeout (default: 30s) initialDataTimeout?: number; // Initial data/SNI timeout (default: 120s) socketTimeout?: number; // Socket inactivity timeout (default: 1h) maxConnectionLifetime?: number; // Max connection lifetime (default: 24h) inactivityTimeout?: number; // Inactivity timeout (default: 4h) gracefulShutdownTimeout?: number; // Shutdown grace period (default: 30s) // Connection limits maxConnectionsPerIP?: number; // Per-IP connection limit (default: 100) connectionRateLimitPerMinute?: number; // Per-IP rate limit (default: 300/min) // Keep-alive keepAliveTreatment?: 'standard' | 'extended' | 'immortal'; keepAliveInactivityMultiplier?: number; // (default: 6) extendedKeepAliveLifetime?: number; // (default: 7 days) // Metrics metrics?: { enabled?: boolean; sampleIntervalMs?: number; retentionSeconds?: number; }; // Behavior enableDetailedLogging?: boolean; // Verbose connection logging enableTlsDebugLogging?: boolean; // TLS handshake debug logging } ``` ### ISmartProxyCertStore Interface ```typescript interface ISmartProxyCertStore { /** Called once on startup to pre-load persisted certs */ loadAll: () => Promise>; /** Called after each successful cert provision */ save: (domain: string, publicKey: string, privateKey: string, ca?: string) => Promise; /** Optional: remove a cert from storage */ remove?: (domain: string) => Promise; } ``` ### IMetrics Interface The `getMetrics()` method returns a cached metrics adapter that polls the Rust engine: ```typescript const metrics = proxy.getMetrics(); // Connection metrics metrics.connections.active(); // Current active connections metrics.connections.total(); // Total connections since start metrics.connections.byRoute(); // Map metrics.connections.byIP(); // Map metrics.connections.topIPs(10); // Top N IPs by connection count // Throughput (bytes/sec) metrics.throughput.instant(); // { in: number, out: number } metrics.throughput.recent(); // Recent average metrics.throughput.average(); // Overall average metrics.throughput.byRoute(); // Map // Request rates metrics.requests.perSecond(); // Requests per second metrics.requests.perMinute(); // Requests per minute metrics.requests.total(); // Total requests // Cumulative totals metrics.totals.bytesIn(); // Total bytes received metrics.totals.bytesOut(); // Total bytes sent metrics.totals.connections(); // Total connections // Percentiles metrics.percentiles.connectionDuration(); // { p50, p95, p99 } metrics.percentiles.bytesTransferred(); // { in: { p50, p95, p99 }, out: { p50, p95, p99 } } ``` ## ๐Ÿ› Troubleshooting ### Certificate Issues - โœ… Ensure domain DNS points to your server - โœ… Port 80 must be accessible for ACME HTTP-01 challenges - โœ… Check DNS propagation with `dig` or `nslookup` - โœ… Verify the email in ACME configuration is valid - โœ… Use `getCertificateStatus('route-name')` to check cert state ### Connection Problems - โœ… Check route priorities (higher number = matched first) - โœ… Verify security rules aren't blocking legitimate traffic - โœ… Test with `curl -v` for detailed connection output - โœ… Enable debug logging with `enableDetailedLogging: true` ### Rust Binary Not Found SmartProxy searches for the Rust binary in this order: 1. `SMARTPROXY_RUST_BINARY` environment variable 2. Platform-specific npm package (`@push.rocks/smartproxy-linux-x64`, etc.) 3. `dist_rust/rustproxy` relative to the package root (built by `tsrust`) 4. Local dev build (`./rust/target/release/rustproxy`) 5. System PATH (`rustproxy`) ### Performance Tuning - โœ… Use NFTables forwarding for high-traffic routes (Linux only) - โœ… Enable connection keep-alive where appropriate - โœ… Use `getMetrics()` and `getStatistics()` to identify bottlenecks - โœ… Adjust `maxConnectionsPerIP` and `connectionRateLimitPerMinute` based on your workload - โœ… Use `passthrough` TLS mode when backend can handle TLS directly ## ๐Ÿ† Best Practices 1. **๐Ÿ“ Use Helper Functions** โ€” They provide sensible defaults and prevent common mistakes 2. **๐ŸŽฏ Set Route Priorities** โ€” More specific routes should have higher priority values 3. **๐Ÿ”’ Enable Security** โ€” Always use IP filtering and rate limiting for public-facing services 4. **๐Ÿ“Š Monitor Metrics** โ€” Use the built-in metrics to catch issues early 5. **๐Ÿ”„ Certificate Monitoring** โ€” Set up alerts before certificates expire 6. **๐Ÿ›‘ Graceful Shutdown** โ€” Always call `proxy.stop()` for clean connection termination 7. **โœ… Validate Routes** โ€” Use `RouteValidator.validateRoutes()` to catch config errors before deployment 8. **๐Ÿ”€ Atomic Updates** โ€” Use `updateRoutes()` for hot-reloading routes (mutex-locked, no downtime) 9. **๐ŸŽฎ Use Socket Handlers** โ€” For protocols beyond HTTP, implement custom socket handlers instead of fighting the proxy model 10. **๐Ÿ’พ Use `certStore`** โ€” Persist certs in your own storage to avoid re-provisioning on every restart ## License and Legal Information This repository contains open-source code licensed under the MIT License. A copy of the license can be found in the [LICENSE](./LICENSE) file. **Please note:** The MIT License does not grant permission to use the trade names, trademarks, service marks, or product names of the project, except as required for reasonable and customary use in describing the origin of the work and reproducing the content of the NOTICE file. ### Trademarks This project is owned and maintained by Task Venture Capital GmbH. The names and logos associated with Task Venture Capital GmbH and any related products or services are trademarks of Task Venture Capital GmbH or third parties, and are not included within the scope of the MIT license granted herein. Use of these trademarks must comply with Task Venture Capital GmbH's Trademark Guidelines or the guidelines of the respective third-party owners, and any usage must be approved in writing. Third-party trademarks used herein are the property of their respective owners and used only in a descriptive manner, e.g. for an implementation of an API or similar. ### Company Information Task Venture Capital GmbH Registered at District Court Bremen HRB 35230 HB, Germany For any legal inquiries or further information, please contact us via email at hello@task.vc. By using this repository, you acknowledge that you have read this section, agree to comply with its terms, and understand that the licensing of the code does not imply endorsement by Task Venture Capital GmbH of any derivative works.