diff --git a/readme.md b/readme.md index 957e545..f7c4e07 100644 --- a/readme.md +++ b/readme.md @@ -6,14 +6,15 @@ A unified high-performance proxy toolkit for Node.js, with **SmartProxy** as the - **SSL/TLS Support**: Automatic HTTPS with Let's Encrypt certificate provisioning - **Flexible Matching Patterns**: Route by port, domain, path, client IP, and TLS version - **Advanced SNI Handling**: Smart TCP/SNI-based forwarding with IP filtering -- **Multiple Action Types**: Forward (with TLS modes), redirect, or block traffic +- **Multiple Action Types**: Forward traffic or handle with custom socket handlers - **Dynamic Port Management**: Add or remove listening ports at runtime without restart -- **Security Features**: IP allowlists, connection limits, timeouts, and more +- **Security Features**: Route-specific IP allowlists, blocklists, connection limits, and authentication - **NFTables Integration**: High-performance kernel-level packet forwarding with Linux NFTables +- **Socket Handlers**: Custom socket handling for specialized protocols and use cases ## Project Architecture Overview -SmartProxy has been restructured using a modern, modular architecture with a unified route-based configuration system in v14.0.0: +SmartProxy has been restructured using a modern, modular architecture with a unified route-based configuration system: ``` /ts @@ -21,10 +22,6 @@ SmartProxy has been restructured using a modern, modular architecture with a uni │ ├── /models # Data models and interfaces │ ├── /utils # Shared utilities (IP validation, logging, etc.) │ └── /events # Common event definitions -├── /certificate # Certificate management (deprecated in v18+) -│ ├── /acme # Moved to SmartCertManager -│ ├── /providers # Now integrated in route configuration -│ └── /storage # Now uses CertStore ├── /forwarding # Forwarding system │ ├── /handlers # Various forwarding handlers │ │ ├── base-handler.ts # Abstract base handler @@ -37,7 +34,7 @@ SmartProxy has been restructured using a modern, modular architecture with a uni │ │ ├── /models # SmartProxy-specific interfaces │ │ │ ├── route-types.ts # Route-based configuration types │ │ │ └── interfaces.ts # SmartProxy interfaces -│ │ ├── certificate-manager.ts # SmartCertManager (new in v18+) +│ │ ├── certificate-manager.ts # SmartCertManager │ │ ├── cert-store.ts # Certificate file storage │ │ ├── route-helpers.ts # Helper functions for creating routes │ │ ├── route-manager.ts # Route management system @@ -48,10 +45,8 @@ SmartProxy has been restructured using a modern, modular architecture with a uni ├── /tls # TLS-specific functionality │ ├── /sni # SNI handling components │ └── /alerts # TLS alerts system -└── /http # HTTP-specific functionality - ├── /port80 # Port80Handler (removed in v18+) - ├── /router # HTTP routing system - └── /redirects # Redirect handlers +└── /routing # Routing functionality + └── /router # HTTP routing system ``` ## Main Components @@ -62,31 +57,34 @@ SmartProxy has been restructured using a modern, modular architecture with a uni The central unified API for all proxy needs, featuring: - Route-based configuration with match/action pattern - Flexible matching criteria (ports, domains, paths, client IPs) - - Multiple action types (forward, redirect, block) + - Multiple action types (forward, redirect, block, socket-handler) - Automatic certificate management - Advanced security controls + - Custom socket handling capabilities ### Helper Functions -- **createRoute**, **createHttpRoute**, **createHttpsRoute**, **createPassthroughRoute** +- **createHttpRoute**, **createHttpsTerminateRoute**, **createHttpsPassthroughRoute** Helper functions to create different route configurations with clean syntax -- **createRedirectRoute**, **createHttpToHttpsRedirect**, **createBlockRoute** - Helper functions for common redirect and security configurations -- **createLoadBalancerRoute**, **createHttpsServer** +- **createHttpToHttpsRedirect** + Helper function for HTTP to HTTPS redirects using socket handlers +- **createLoadBalancerRoute**, **createCompleteHttpsServer** Helper functions for complex configurations -- **createNfTablesRoute**, **createNfTablesTerminateRoute** +- **createSocketHandlerRoute**, **SocketHandlers** + Helper functions for custom socket handling +- **createNfTablesRoute**, **createNfTablesTerminateRoute**, **createCompleteNfTablesHttpsServer** Helper functions for NFTables-based high-performance kernel-level routing +- **createPortMappingRoute**, **createOffsetPortMappingRoute**, **createDynamicRoute**, **createSmartLoadBalancer** + Helper functions for dynamic routing and port mapping +- **createApiGatewayRoute**, **addRateLimiting**, **addBasicAuth**, **addJwtAuth** + Helper functions for API gateway features and authentication ### Specialized Components - **HttpProxy** (`ts/proxies/http-proxy/http-proxy.ts`) HTTP/HTTPS reverse proxy with TLS termination and WebSocket support -- **Port80Handler** (`ts/http/port80/port80-handler.ts`) - ACME HTTP-01 challenge handler for Let's Encrypt certificates - **NfTablesProxy** (`ts/proxies/nftables-proxy/nftables-proxy.ts`) Low-level port forwarding using nftables NAT rules -- **Redirect**, **SslRedirect** (`ts/http/redirects/redirect-handler.ts`) - HTTP-to-HTTPS redirects with customizable rules - **SniHandler** (`ts/tls/sni/sni-handler.ts`) Utilities for SNI extraction from TLS handshakes @@ -102,7 +100,6 @@ SmartProxy has been restructured using a modern, modular architecture with a uni - `IRouteConfig`, `IRouteMatch`, `IRouteAction` (`ts/proxies/smart-proxy/models/route-types.ts`) - `IRoutedSmartProxyOptions` (`ts/proxies/smart-proxy/models/route-types.ts`) - `IHttpProxyOptions` (`ts/proxies/http-proxy/models/types.ts`) -- `IAcmeOptions`, `IDomainOptions` (`ts/certificate/models/certificate-types.ts`) - `INfTableProxySettings` (`ts/proxies/nftables-proxy/models/interfaces.ts`) ## Installation @@ -113,7 +110,7 @@ npm install @push.rocks/smartproxy ## Quick Start with SmartProxy -SmartProxy v19.4.0 provides a unified route-based configuration system with enhanced certificate management, NFTables integration for high-performance kernel-level routing, and improved helper functions for common proxy setups. +SmartProxy v19.5.3 provides a unified route-based configuration system with enhanced certificate management, NFTables integration for high-performance kernel-level routing, custom socket handling, and improved helper functions for common proxy setups. ```typescript import { @@ -124,12 +121,21 @@ import { createHttpToHttpsRedirect, createCompleteHttpsServer, createLoadBalancerRoute, - createStaticFileRoute, createApiRoute, createWebSocketRoute, - createSecurityConfig, + createSocketHandlerRoute, createNfTablesRoute, - createNfTablesTerminateRoute + createNfTablesTerminateRoute, + createCompleteNfTablesHttpsServer, + createPortMappingRoute, + createOffsetPortMappingRoute, + createDynamicRoute, + createSmartLoadBalancer, + createApiGatewayRoute, + addRateLimiting, + addBasicAuth, + addJwtAuth, + SocketHandlers } from '@push.rocks/smartproxy'; // Create a new SmartProxy instance with route-based configuration @@ -179,12 +185,6 @@ const proxy = new SmartProxy({ pingInterval: 30000 }), - // Static file server for web assets - createStaticFileRoute('static.example.com', '/var/www/html', { - serveOnHttps: true, - certificate: 'auto', - indexFiles: ['index.html', 'index.htm', 'default.html'] - }), // Load balancer with multiple backend servers createLoadBalancerRoute( @@ -195,15 +195,16 @@ const proxy = new SmartProxy({ tls: { mode: 'terminate', certificate: 'auto' - }, - security: createSecurityConfig({ - allowedIps: ['10.0.0.*', '192.168.1.*'], - blockedIps: ['1.2.3.4'], - maxConnections: 1000 - }) + } } ), + // Custom socket handler for specialized protocols + createSocketHandlerRoute('telnet.example.com', 23, SocketHandlers.lineProtocol((line, socket) => { + console.log('Received:', line); + socket.write(`Echo: ${line}\n`); + })), + // High-performance NFTables route (requires root/sudo) createNfTablesRoute('fast.example.com', { host: 'backend-server', port: 8080 }, { ports: 80, @@ -217,7 +218,29 @@ const proxy = new SmartProxy({ ports: 443, certificate: 'auto', maxRate: '100mbps' - }) + }), + + // Route with security configuration + { + name: 'secure-admin', + match: { + ports: 443, + domains: 'admin.example.com' + }, + action: { + type: 'forward', + target: { host: 'localhost', port: 8080 }, + tls: { + mode: 'terminate', + certificate: 'auto' + } + }, + security: { + ipAllowList: ['10.0.0.*', '192.168.1.*'], + ipBlockList: ['192.168.1.100'], + maxConnections: 100 + } + } ] }); @@ -243,7 +266,7 @@ await proxy.stop(); ## Route-Based Configuration System -SmartProxy v14.0.0 introduces a new unified route configuration system based on the `IRouteConfig` interface. This system follows a match/action pattern that makes routing more powerful, flexible, and declarative. +SmartProxy uses a unified route configuration system based on the `IRouteConfig` interface. This system follows a match/action pattern that makes routing more powerful, flexible, and declarative. ### IRouteConfig Interface @@ -257,11 +280,15 @@ interface IRouteConfig { // What to do with matched traffic (required) action: IRouteAction; + // Security configuration (optional) + security?: IRouteSecurity; + // Metadata (all optional) 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) } ``` @@ -281,6 +308,7 @@ interface IRouteMatch { path?: string; // Match specific URL paths, supports glob patterns clientIp?: string[]; // Match specific client IPs, supports glob patterns tlsVersion?: string[]; // Match specific TLS versions e.g. ['TLSv1.2', 'TLSv1.3'] + headers?: Record; // Match specific HTTP headers } ``` @@ -316,7 +344,7 @@ The `action` property defines what to do with traffic that matches the criteria: ```typescript interface IRouteAction { // Action type (required) - type: 'forward' | 'redirect' | 'block'; + type: 'forward' | 'socket-handler'; // For 'forward' actions target?: IRouteTarget; @@ -324,14 +352,23 @@ interface IRouteAction { // TLS handling for 'forward' actions tls?: IRouteTls; - // For 'redirect' actions - redirect?: IRouteRedirect; + // For 'socket-handler' actions + socketHandler?: TSocketHandler; - // Security options for any action - security?: IRouteSecurity; + // WebSocket support + websocket?: IRouteWebSocket; + + // Load balancing options + loadBalancing?: IRouteLoadBalancing; // Advanced options advanced?: IRouteAdvanced; + + // Additional backend-specific options + options?: { + backendProtocol?: 'http1' | 'http2'; + [key: string]: any; + }; // Forwarding engine selection forwardingEngine?: 'node' | 'nftables'; @@ -341,6 +378,27 @@ interface IRouteAction { } ``` +#### Security Configuration (IRouteSecurity) + +Security is configured at the route level, not within the action: + +```typescript +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 (requires TLS termination) + authentication?: IRouteAuthentication; + + // Rate limiting + rateLimit?: IRouteRateLimit; +} +``` + ### ACME/Let's Encrypt Configuration SmartProxy supports automatic certificate provisioning and renewal with Let's Encrypt. ACME can be configured globally or per-route. @@ -400,14 +458,16 @@ Override global settings for specific routes: } } } +``` + +### Action Types **Forward Action:** When `type: 'forward'`, the traffic is forwarded to the specified target: ```typescript interface IRouteTarget { - host: string | string[]; // Target host(s) - string array enables round-robin - port: number; // Target port - preservePort?: boolean; // Use incoming port as target port (default: false) + host: string | string[] | ((context: IRouteContext) => string | string[]); // Target host(s) - string array enables round-robin, function enables dynamic routing + port: number | 'preserve' | ((context: IRouteContext) => number); // Target port - 'preserve' keeps incoming port, function enables dynamic port mapping } ``` @@ -447,44 +507,146 @@ interface INfTablesOptions { } ``` -**Redirect Action:** -When `type: 'redirect'`, the client is redirected: +**Redirect and Block Actions:** +Redirects and blocks are implemented using socket handlers. Use the helper functions or pre-built handlers: ```typescript -interface IRouteRedirect { - to: string; // URL or template with variables - status: 301 | 302 | 307 | 308; // HTTP status code +// HTTP to HTTPS redirect +createHttpToHttpsRedirect('example.com', 443) + +// Block connections +{ + action: { + type: 'socket-handler', + socketHandler: SocketHandlers.httpBlock(403, 'Access denied') + } } ``` -**Block Action:** -When `type: 'block'`, the connection is immediately closed. - -**Security Options:** -For any action type, you can add security controls: +**Socket Handler Action:** +When `type: 'socket-handler'`, custom socket handling logic is applied: ```typescript -interface IRouteSecurity { - allowedIps?: string[]; // IP allowlist with glob pattern support - blockedIps?: string[]; // IP blocklist with glob pattern support - maxConnections?: number; // Maximum concurrent connections - authentication?: { // Optional authentication (future support) - type: 'basic' | 'digest' | 'oauth'; - // Auth-specific options - }; +type TSocketHandler = (socket: net.Socket, context: IRouteContext) => void | Promise; +``` + +The socket handler receives: +- `socket`: The raw Node.js Socket object +- `context`: Route context containing clientIp, port, domain, route info, etc. + +### Socket Handlers + +SmartProxy v19.5.0 introduces socket handlers for custom protocol handling: + +```typescript +// Create a custom socket handler route +createSocketHandlerRoute('custom.example.com', 9000, async (socket, context) => { + console.log(`New connection from ${context.clientIp}`); + + // Custom protocol handling + socket.write('Welcome to custom protocol server\n'); + + socket.on('data', (data) => { + // Process custom protocol data + const response = processProtocolData(data); + socket.write(response); + }); + + socket.on('error', (err) => { + console.error('Socket error:', err); + }); +}); + +// Use pre-built socket handlers +import { SocketHandlers } from '@push.rocks/smartproxy'; + +// Echo server +createSocketHandlerRoute('echo.example.com', 7000, SocketHandlers.echo), + +// TCP proxy +createSocketHandlerRoute('proxy.example.com', 8000, SocketHandlers.proxy('backend-server', 8080)), + +// Line-based protocol +createSocketHandlerRoute('telnet.example.com', 23, SocketHandlers.lineProtocol((line, socket) => { + socket.write(`You said: ${line}\n`); +})), + +// HTTP response +createSocketHandlerRoute('simple.example.com', 8080, SocketHandlers.httpResponse(200, 'Hello World')), + +// HTTP redirect +createSocketHandlerRoute('redirect.example.com', 80, SocketHandlers.httpRedirect('https://{domain}{path}', 301)), + +// HTTP blocking with custom message +createSocketHandlerRoute('forbidden.example.com', 80, SocketHandlers.httpBlock(403, 'Access Forbidden')), + +// Block connections immediately +createSocketHandlerRoute('blocked.example.com', 443, SocketHandlers.block('Access denied')), + +// Full HTTP server for complex handling +createSocketHandlerRoute('http-api.example.com', 8080, SocketHandlers.httpServer((req, res) => { + if (req.url === '/health') { + res.status(200); + res.send('OK'); + } else { + res.status(404); + res.send('Not Found'); + } +})) +``` + +### Dynamic Routing + +SmartProxy supports dynamic routing using functions for host and port selection: + +```typescript +// Dynamic host selection based on domain +createDynamicRoute({ + ports: 80, + domains: ['*.tenant.example.com'], + targetHost: (context) => { + // Extract tenant from subdomain + const tenant = context.domain.split('.')[0]; + return `${tenant}-backend`; + }, + portMapper: (context) => 8080 +}); + +// Port mapping with offset +createOffsetPortMappingRoute({ + ports: [8000, 8001, 8002], + targetHost: 'backend', + offset: -1000 // Maps 8000->7000, 8001->7001, etc. +}); + +// Smart load balancer with domain-based routing +createSmartLoadBalancer({ + ports: 443, + domainTargets: { + 'api.example.com': ['api-1', 'api-2'], + 'web.example.com': ['web-1', 'web-2', 'web-3'], + 'admin.example.com': 'admin-server' + }, + portMapper: (context) => 8080, + defaultTarget: 'fallback-server' +}); +``` + +### Route Context + +The `IRouteContext` interface provides information about the current connection: + +```typescript +interface IRouteContext { + clientIp: string; // Client's IP address + port: number; // Incoming port + domain?: string; // Domain from SNI or Host header + path?: string; // Request path (HTTP only) + sni?: string; // SNI hostname (TLS only) + protocol?: string; // Protocol information + route?: IRouteConfig; // Matched route configuration } ``` -**Advanced Options:** -Additional advanced configurations: -```typescript -interface IRouteAdvanced { - timeout?: number; // Connection timeout in milliseconds - headers?: Record; // Custom HTTP headers - keepAlive?: boolean; // Enable connection pooling - // Additional advanced options -} -``` - -#### Template Variables +### Template Variables String values in redirect URLs and headers can include variables: @@ -503,7 +665,7 @@ redirect: { } ``` -#### Route Metadata and Prioritization +### Route Metadata and Prioritization You can add metadata to routes to help with organization and control matching priority: @@ -518,7 +680,7 @@ You can add metadata to routes to help with organization and control matching pr Routes with higher priority values are matched first, allowing you to create specialized routes that take precedence over more general ones. -#### Complete Route Configuration Example +### Complete Route Configuration Example ```typescript // Example of a complete route configuration @@ -539,10 +701,6 @@ Routes with higher priority values are matched first, allowing you to create spe mode: 'terminate', certificate: 'auto' // Use Let's Encrypt }, - security: { - allowedIps: ['10.0.0.*'], - maxConnections: 100 - }, advanced: { timeout: 30000, headers: { @@ -552,6 +710,10 @@ Routes with higher priority values are matched first, allowing you to create spe keepAlive: true } }, + security: { + ipAllowList: ['10.0.0.*'], + maxConnections: 100 + }, name: 'Secure API Route', description: 'Route for secure API endpoints with authentication', priority: 100, @@ -576,19 +738,19 @@ Routes with higher priority values are matched first, allowing you to create spe preserveSourceIP: true, maxRate: '1gbps', useIPSets: true - }, - security: { - ipAllowList: ['10.0.0.*'], - blockedIps: ['malicious.ip.range.*'] } }, + security: { + ipAllowList: ['10.0.0.*'], + ipBlockList: ['malicious.ip.range.*'] + }, name: 'High Performance NFTables Route', description: 'Kernel-level forwarding for maximum performance', priority: 150 } ``` -### Using Helper Functions +## Using Helper Functions While you can create route configurations manually, SmartProxy provides helper functions to make it easier: @@ -610,18 +772,23 @@ Available helper functions: - `createHttpRoute()` - Create an HTTP forwarding route - `createHttpsTerminateRoute()` - Create an HTTPS route with TLS termination - `createHttpsPassthroughRoute()` - Create an HTTPS passthrough route -- `createHttpToHttpsRedirect()` - Create an HTTP to HTTPS redirect +- `createHttpToHttpsRedirect()` - Create an HTTP to HTTPS redirect using socket handler - `createCompleteHttpsServer()` - Create a complete HTTPS server setup with HTTP redirect - `createLoadBalancerRoute()` - Create a route for load balancing across multiple backends -- `createStaticFileRoute()` - Create a route for serving static files - `createApiRoute()` - Create an API route with path matching and CORS support - `createWebSocketRoute()` - Create a route for WebSocket connections +- `createSocketHandlerRoute()` - Create a route with custom socket handling - `createNfTablesRoute()` - Create a high-performance NFTables route - `createNfTablesTerminateRoute()` - Create an NFTables route with TLS termination -- `createPortRange()` - Helper to create port range configurations -- `createSecurityConfig()` - Helper to create security configuration objects -- `createBlockRoute()` - Create a route to block specific traffic -- `createTestRoute()` - Create a test route for debugging and testing +- `createCompleteNfTablesHttpsServer()` - Create a complete NFTables HTTPS setup with HTTP redirect +- `createPortMappingRoute()` - Create a route with dynamic port mapping +- `createOffsetPortMappingRoute()` - Create a route with port offset mapping +- `createDynamicRoute()` - Create a route with dynamic host/port selection +- `createSmartLoadBalancer()` - Create a smart load balancer with domain-based routing +- `createApiGatewayRoute()` - Create an API gateway route with advanced features +- `addRateLimiting()` - Add rate limiting to a route +- `addBasicAuth()` - Add basic authentication to a route +- `addJwtAuth()` - Add JWT authentication to a route ## What You Can Do with SmartProxy @@ -660,13 +827,18 @@ Available helper functions: 4. **Security Controls** ```typescript // Restrict access based on IP addresses - createHttpsTerminateRoute('admin.example.com', { host: 'localhost', port: 8080 }, { - certificate: 'auto', + { + match: { ports: 443, domains: 'admin.example.com' }, + action: { + type: 'forward', + target: { host: 'localhost', port: 8080 }, + tls: { mode: 'terminate', certificate: 'auto' } + }, security: { - allowedIps: ['10.0.0.*', '192.168.1.*'], + ipAllowList: ['10.0.0.*', '192.168.1.*'], maxConnections: 100 } - }) + } ``` 5. **Wildcard Domains** @@ -686,11 +858,15 @@ Available helper functions: 7. **Block Malicious Traffic** ```typescript - // Block traffic from specific IPs - createBlockRoute([80, 443], { - clientIp: ['1.2.3.*', '5.6.7.*'], + // Block traffic from specific IPs or patterns + { + match: { ports: [80, 443], clientIp: ['1.2.3.*', '5.6.7.*'] }, + action: { + type: 'socket-handler', + socketHandler: SocketHandlers.httpBlock(403, 'Access denied') + }, priority: 1000 // High priority to ensure blocking - }) + } ``` 8. **Dynamic Port Management** @@ -728,6 +904,21 @@ Available helper functions: }) ``` +10. **Custom Protocol Handling** + ```typescript + // Implement custom protocols or specialized handling + createSocketHandlerRoute('custom.example.com', 9000, async (socket, context) => { + // Your custom protocol logic here + socket.write('CUSTOM PROTOCOL v1.0\n'); + + socket.on('data', (data) => { + // Handle custom protocol messages + const response = processCustomProtocol(data); + socket.write(response); + }); + }) + ``` + ## Other Components While SmartProxy provides a unified API for most needs, you can also use individual components: @@ -779,32 +970,6 @@ await proxy.updateRouteConfigs([ } } ]); - -// Legacy configuration (for backward compatibility) -await proxy.updateProxyConfigs([ - { - hostName: 'legacy.example.com', - destinationIps: ['127.0.0.1'], - destinationPorts: [3000], - publicKey: fs.readFileSync('cert.pem', 'utf8'), - privateKey: fs.readFileSync('key.pem', 'utf8'), - } -]); -``` - -### Port80Handler -For standalone ACME certificate management: - -```typescript -import { Port80Handler } from '@push.rocks/smartproxy'; - -const acme = new Port80Handler({ - port: 80, - contactEmail: 'admin@example.com', - useProduction: true -}); -acme.on('certificate-issued', evt => console.log(`Certificate ready: ${evt.domain}`)); -await acme.start(); ``` ### NfTablesProxy @@ -822,15 +987,14 @@ const nft = new NfTablesProxy({ await nft.start(); ``` -### Redirect / SslRedirect -For HTTP-to-HTTPS redirects: +### SniHandler +For SNI extraction from TLS handshakes: ```typescript -import { SslRedirect } from '@push.rocks/smartproxy'; +import { SniHandler } from '@push.rocks/smartproxy'; -// Quick HTTP→HTTPS helper on port 80 -const redirect = new SslRedirect(80); -await redirect.start(); +// The SniHandler is typically used internally by SmartProxy +// but can be used directly for custom implementations ``` ## NFTables Integration @@ -898,6 +1062,15 @@ const proxy = new SmartProxy({ ports: 443, certificate: 'auto', useAdvancedNAT: true + }), + + // Complete NFTables HTTPS server with HTTP redirect + ...createCompleteNfTablesHttpsServer('complete-nftables.example.com', { + host: 'backend', + port: 8080 + }, { + certificate: 'auto', + preserveSourceIP: true }) ] }); @@ -953,78 +1126,84 @@ NFTables routing has some limitations: For scenarios requiring application-level features (header manipulation, WebSocket handling, etc.), use the standard SmartProxy routes without NFTables. -## Migration to v18.0.0 +## Migration to v19.5.3 -Version 18.0.0 continues the evolution with NFTables integration while maintaining the unified route-based configuration system: +Version 19.5.3 includes important fixes and improvements: ### Key Changes -1. **NFTables Integration**: High-performance kernel-level packet forwarding for Linux systems -2. **Pure Route-Based API**: The configuration now exclusively uses the match/action pattern with no legacy interfaces -3. **Improved Helper Functions**: Enhanced helper functions with cleaner parameter signatures -4. **Removed Legacy Support**: Legacy domain-based APIs have been completely removed -5. **More Route Pattern Helpers**: Additional helper functions for common routing patterns including NFTables routes +1. **Security Configuration Location**: Security configuration is now at the route level (`route.security`), not inside the action (`route.action.security`) +2. **Socket Handler Support**: New `socket-handler` action type for custom protocol handling +3. **Improved ACME Timing**: Certificate provisioning now waits for ports to be ready +4. **Route-Specific Security**: IP allow/block lists are now properly enforced per route +5. **Enhanced Helper Functions**: New helpers for socket handling and NFTables complete server setup ### Migration Example -**Legacy Configuration (pre-v14)**: +**Before (v18.x and earlier)**: ```typescript -import { SmartProxy, createDomainConfig, httpOnly, tlsTerminateToHttp } from '@push.rocks/smartproxy'; - -const proxy = new SmartProxy({ - fromPort: 443, - domainConfigs: [ - createDomainConfig('example.com', tlsTerminateToHttp({ - target: { host: 'localhost', port: 8080 }, - acme: { enabled: true, production: true } - })) - ], - sniEnabled: true -}); -``` - -**Current Configuration (v18.0.0)**: -```typescript -import { SmartProxy, createHttpsTerminateRoute } from '@push.rocks/smartproxy'; - -const proxy = new SmartProxy({ - routes: [ - createHttpsTerminateRoute('example.com', { host: 'localhost', port: 8080 }, { - certificate: 'auto' - }) - ], - acme: { - enabled: true, - useProduction: true +{ + match: { ports: 443, domains: 'api.example.com' }, + action: { + type: 'forward', + target: { host: 'localhost', port: 3000 }, + security: { // WRONG: Security was incorrectly placed here + ipAllowList: ['10.0.0.*'] + } } -}); +} ``` -### Migration from v14.x/v15.x to v16.0.0 - -If you're already using route-based configuration, update your helper function calls: - +**After (v19.5.3)**: ```typescript -// Old v14.x/v15.x style: -createHttpsRoute({ - domains: 'example.com', - target: { host: 'localhost', port: 8080 }, - certificate: 'auto' -}) - -// New v16.0.0 style: -createHttpsTerminateRoute('example.com', { host: 'localhost', port: 8080 }, { - certificate: 'auto' -}) +{ + match: { ports: 443, domains: 'api.example.com' }, + action: { + type: 'forward', + target: { host: 'localhost', port: 3000 } + }, + security: { // CORRECT: Security is at the route level + ipAllowList: ['10.0.0.*'] + } +} ``` +### New Features in v19.5.x + +1. **Socket Handlers** - Custom protocol handling: + ```typescript + createSocketHandlerRoute('custom.example.com', 9000, async (socket, context) => { + // Custom protocol implementation + }) + ``` + +2. **Pre-built Socket Handlers** - Common patterns: + - `SocketHandlers.echo` - Echo server + - `SocketHandlers.proxy` - TCP proxy + - `SocketHandlers.lineProtocol` - Line-based protocols + - `SocketHandlers.httpResponse` - Simple HTTP responses + - `SocketHandlers.httpRedirect` - HTTP redirects + - `SocketHandlers.httpBlock` - HTTP blocking with status code + - `SocketHandlers.block` - Connection blocking + - `SocketHandlers.httpServer` - Full HTTP server handler + +3. **Complete NFTables Server** - HTTPS with HTTP redirect: + ```typescript + ...createCompleteNfTablesHttpsServer('example.com', { + host: 'backend', + port: 8080 + }, { + certificate: 'auto' + }) + ``` + ### Complete Migration Steps -1. Replace any remaining `domainConfigs` with route-based configuration using the `routes` array -2. Update helper function calls to use the newer parameter format (domain first, target second, options third) -3. Use the new specific helper functions (e.g., `createHttpsTerminateRoute` instead of `createHttpsRoute`) -4. Update any code that uses `updateDomainConfigs()` to use `addRoutes()` or `updateRoutes()` -5. For port-only configurations, create route configurations with port matching only +1. Move any security configuration from `action.security` to `route.security` +2. Update to use new socket handler features for custom protocols +3. Take advantage of improved ACME timing (no action needed, just update) +4. Use the new helper functions for cleaner configuration +5. Review and update any custom route creation code ## Architecture & Flow Diagrams @@ -1036,9 +1215,11 @@ flowchart TB direction TB RouteConfig["Route Configuration
(Match/Action)"] RouteManager["Route Manager"] - HTTPS443["HTTPS Port 443
HttpProxy"] SmartProxy["SmartProxy
(TCP/SNI Proxy)"] - ACME["Port80Handler
(ACME HTTP-01)"] + HttpProxyBridge["HttpProxy Bridge"] + HttpProxy["HttpProxy
(HTTPS/TLS Termination)"] + NfTablesManager["NFTables Manager
(Kernel Routing)"] + CertManager["SmartCertManager
(ACME/Let's Encrypt)"] Certs[(SSL Certificates)] end @@ -1054,20 +1235,25 @@ flowchart TB RouteManager -->|Use| RouteConfig RouteManager -->|Execute Action| SmartProxy + SmartProxy -->|TLS Termination| HttpProxyBridge + HttpProxyBridge -->|Forward| HttpProxy + SmartProxy -->|Kernel Routing| NfTablesManager + SmartProxy -->|Forward| Service1 SmartProxy -->|Redirect| Client SmartProxy -->|Forward| Service2 SmartProxy -->|Forward| Service3 - ACME -.->|Generate/Manage| Certs + CertManager -.->|Generate/Manage| Certs Certs -.->|Provide TLS Certs| SmartProxy + Certs -.->|Provide TLS Certs| HttpProxy classDef component fill:#f9f,stroke:#333,stroke-width:2px; classDef backend fill:#bbf,stroke:#333,stroke-width:1px; classDef client fill:#dfd,stroke:#333,stroke-width:2px; class Client client; - class RouteConfig,RouteManager,HTTPS443,SmartProxy,ACME component; + class RouteConfig,RouteManager,SmartProxy,HttpProxyBridge,HttpProxy,NfTablesManager,CertManager component; class Service1,Service2,Service3 backend; ``` @@ -1079,6 +1265,7 @@ sequenceDiagram participant Client participant SmartProxy participant RouteManager + participant SecurityManager participant Backend Client->>SmartProxy: Connection (TCP/HTTP/HTTPS) @@ -1093,28 +1280,40 @@ sequenceDiagram RouteManager->>RouteManager: Determine highest priority matching route - alt Forward Action - RouteManager->>SmartProxy: Use forward action + alt Route Matched + SmartProxy->>SecurityManager: Check route security + SecurityManager->>SecurityManager: Validate IP allow/block lists + SecurityManager->>SecurityManager: Check connection limits - alt TLS Termination - SmartProxy->>SmartProxy: Terminate TLS - SmartProxy->>Backend: Forward as HTTP/HTTPS - else TLS Passthrough - SmartProxy->>Backend: Forward raw TCP + alt Security Check Passed + alt Forward Action + SmartProxy->>SmartProxy: Apply action configuration + + alt TLS Termination + SmartProxy->>SmartProxy: Terminate TLS + SmartProxy->>Backend: Forward as HTTP/HTTPS + else TLS Passthrough + SmartProxy->>Backend: Forward raw TCP + else Socket Handler + SmartProxy->>SmartProxy: Execute custom handler + end + + else Redirect Action + SmartProxy->>Client: Send redirect response + + else Block Action + SmartProxy->>Client: Close connection + end + else Security Check Failed + SmartProxy->>Client: Close connection (unauthorized) end - - else Redirect Action - RouteManager->>SmartProxy: Use redirect action - SmartProxy->>Client: Send redirect response - - else Block Action - RouteManager->>SmartProxy: Use block action - SmartProxy->>Client: Close connection + else No Route Matched + SmartProxy->>Client: Close connection (no route) end loop Connection Active SmartProxy-->>SmartProxy: Monitor Activity - SmartProxy-->>SmartProxy: Check Security Rules + SmartProxy-->>SecurityManager: Check Security Rules alt Security Violation or Timeout SmartProxy->>Client: Close Connection SmartProxy->>Backend: Close Connection @@ -1127,7 +1326,7 @@ sequenceDiagram - **Route-Based Traffic Management** • Match/action pattern for flexible routing • Port, domain, path, client IP, and TLS version matching - • Multiple action types (forward, redirect, block) + • Forward traffic or use custom socket handlers for any protocol - **TLS Handling Options** • TLS passthrough for end-to-end encryption @@ -1138,29 +1337,44 @@ sequenceDiagram • HTTP-01 challenge handling • Certificate issuance/renewal • Pluggable storage + • Per-route and global configuration - **Security Controls** - • IP allow/block lists with glob pattern support + • Route-specific IP allow/block lists with glob pattern support • Connection limits and rate limiting • Timeout controls and connection monitoring + • Authentication support (Basic, JWT, OAuth) - **Load Balancing** • Round-robin distribution across multiple backends + • Dynamic host selection based on context • Health checks and failure handling +- **Custom Protocol Support** + • Socket handler action type for custom protocols + • Pre-built handlers for common patterns + • Full control over socket lifecycle + - **Advanced Features** • Custom header manipulation + • URL rewriting • Template variables for dynamic values • Priority-based route matching + • WebSocket support with configuration + • Static file serving + +- **High Performance** + • NFTables integration for kernel-level forwarding + • Connection pooling and keep-alive + • Efficient SNI extraction + • Minimal overhead routing ## Certificate Hooks & Events Listen for certificate events via EventEmitter: -- **Port80Handler**: - - `certificate-issued`, `certificate-renewed`, `certificate-failed` - - `manager-started`, `manager-stopped`, `request-forwarded` - **SmartProxy**: - `certificate` (domain, publicKey, privateKey, expiryDate, source, isRenewal) + - Events from CertManager are propagated Provide a `certProvisionFunction(domain)` in SmartProxy settings to supply static certs or return `'http01'`. @@ -1192,12 +1406,17 @@ const apiGateway = new SmartProxy({ }), // Admin dashboard with extra security - createHttpsTerminateRoute('admin.example.com', { host: 'admin-dashboard', port: 8080 }, { - certificate: 'auto', + { + match: { ports: 443, domains: 'admin.example.com' }, + action: { + type: 'forward', + target: { host: 'admin-dashboard', port: 8080 }, + tls: { mode: 'terminate', certificate: 'auto' } + }, security: { - allowedIps: ['10.0.0.*', '192.168.1.*'] // Only allow internal network + ipAllowList: ['10.0.0.*', '192.168.1.*'] // Only allow internal network } - }) + } ] }); @@ -1209,16 +1428,13 @@ await apiGateway.start(); Easily set up a secure HTTPS server with automatic redirection from HTTP: ```typescript -import { SmartProxy, createHttpsServer } from '@push.rocks/smartproxy'; +import { SmartProxy, createCompleteHttpsServer } from '@push.rocks/smartproxy'; const webServer = new SmartProxy({ routes: [ - // createHttpsServer creates both the HTTPS route and HTTP redirect - ...createHttpsServer({ - domains: 'example.com', - target: { host: 'localhost', port: 8080 }, - certificate: 'auto', - addHttpRedirect: true + // createCompleteHttpsServer creates both the HTTPS route and HTTP redirect + ...createCompleteHttpsServer('example.com', { host: 'localhost', port: 8080 }, { + certificate: 'auto' }) ] }); @@ -1231,28 +1447,24 @@ await webServer.start(); Support dynamically created tenants with wildcard domain matching: ```typescript -import { SmartProxy, createHttpsRoute, createHttpToHttpsRedirect } from '@push.rocks/smartproxy'; +import { SmartProxy, createDynamicRoute } from '@push.rocks/smartproxy'; const multiTenantApp = new SmartProxy({ routes: [ - // Handle all tenant subdomains with one route - createHttpsRoute({ + // Dynamic routing based on subdomain + createDynamicRoute({ ports: 443, - domains: '*.example.com', - target: { host: 'tenant-router', port: 8080 }, - certificate: 'auto', - // Pass original hostname to backend for tenant identification - advanced: { - headers: { - 'X-Original-Host': '{sni}' - } - } + domains: '*.tenant.example.com', + targetHost: (context) => { + // Extract tenant ID from subdomain + const tenant = context.domain.split('.')[0]; + return `${tenant}-backend.internal`; + }, + portMapper: (context) => 8080 }), // Redirect HTTP to HTTPS for all subdomains - createHttpToHttpsRedirect({ - domains: ['*.example.com'] - }) + createHttpToHttpsRedirect(['*.tenant.example.com']) ] }); @@ -1266,68 +1478,63 @@ Create a comprehensive proxy solution with multiple services and security contro ```typescript import { SmartProxy, - createHttpsRoute, - createPassthroughRoute, - createBlockRoute, - createHttpToHttpsRedirect + createHttpsTerminateRoute, + createHttpsPassthroughRoute, + createSocketHandlerRoute, + createHttpToHttpsRedirect, + SocketHandlers } from '@push.rocks/smartproxy'; const enterpriseProxy = new SmartProxy({ routes: [ // Web application with automatic HTTPS - createHttpsRoute({ - ports: 443, - domains: 'app.example.com', - target: { host: 'web-app', port: 8080 }, + createHttpsTerminateRoute('app.example.com', { host: 'web-app', port: 8080 }, { certificate: 'auto' }), // Legacy system that needs HTTPS passthrough - createPassthroughRoute({ - ports: 443, - domains: 'legacy.example.com', - target: { host: 'legacy-server', port: 443 } - }), + createHttpsPassthroughRoute('legacy.example.com', { host: 'legacy-server', port: 443 }), // Internal APIs with IP restrictions - createHttpsRoute({ - ports: 443, - domains: 'api.internal.example.com', - target: { host: 'api-gateway', port: 3000 }, - certificate: 'auto', + { + match: { ports: 443, domains: 'api.internal.example.com' }, + action: { + type: 'forward', + target: { host: 'api-gateway', port: 3000 }, + tls: { mode: 'terminate', certificate: 'auto' } + }, security: { - allowedIps: ['10.0.0.0/16', '192.168.0.0/16'], + ipAllowList: ['10.0.0.0/16', '192.168.0.0/16'], maxConnections: 500 } - }), + }, + + // Custom protocol handler + createSocketHandlerRoute('telnet.example.com', 23, SocketHandlers.lineProtocol((line, socket) => { + // Handle telnet-like protocol + socket.write(`Command received: ${line}\n`); + })), // Block known malicious IPs - createBlockRoute({ - ports: [80, 443], - clientIp: ['1.2.3.*', '5.6.7.*'], - priority: 1000 - }), + { + match: { ports: [80, 443], clientIp: ['1.2.3.*', '5.6.7.*'] }, + action: { + type: 'socket-handler', + socketHandler: SocketHandlers.block('Access denied') + }, + priority: 1000 // High priority to ensure blocking + }, // Redirect all HTTP to HTTPS - createHttpToHttpsRedirect({ - domains: ['*.example.com', 'example.com'] - }) + createHttpToHttpsRedirect(['*.example.com', 'example.com']) ], - // Global settings that apply to all routes - defaults: { - security: { - maxConnections: 1000 - } - }, - // Enable connection timeouts for security inactivityTimeout: 30000, // Using global certificate management acme: { - enabled: true, - contactEmail: 'admin@example.com', + email: 'admin@example.com', useProduction: true, renewThresholdDays: 30 } @@ -1355,6 +1562,9 @@ await enterpriseProxy.start(); - **tlsVersion**: `string[]` (optional) Match specific TLS versions (e.g., `TLSv1.2`, `TLSv1.3`) +- **headers**: `Record` (optional) + Match specific HTTP headers + ### Action Types 1. **Forward**: @@ -1366,18 +1576,13 @@ await enterpriseProxy.start(); } ``` -2. **Redirect**: +2. **Socket Handler**: ```typescript { - type: 'redirect', - redirect: { to: 'https://{domain}{path}', status: 301 } - } - ``` - -3. **Block**: - ```typescript - { - type: 'block' + type: 'socket-handler', + socketHandler: async (socket, context) => { + // Custom protocol handling + } } ``` @@ -1400,10 +1605,17 @@ Template variables can be used in string values: Example: ```typescript -createRedirectRoute({ - domains: 'old.example.com', - redirectTo: 'https://new.example.com{path}?source=redirect' -}) +// Using the HTTP redirect helper +createHttpToHttpsRedirect('old.example.com', 443) + +// Or with custom redirect using socket handler +{ + match: { ports: 80, domains: 'old.example.com' }, + action: { + type: 'socket-handler', + socketHandler: SocketHandlers.httpRedirect('https://new.example.com{path}?source=redirect', 301) + } +} ``` ## Configuration Options @@ -1447,17 +1659,6 @@ HttpProxy now supports full route-based configuration including: - WebSocket configuration with path rewriting, custom headers, ping control, and size limits - Context-aware CORS configuration -### Port80Handler (IAcmeOptions) -- `enabled` (boolean, default true) -- `port` (number, default 80) -- `contactEmail` (string) -- `useProduction` (boolean, default false) -- `renewThresholdDays` (number, default 30) -- `autoRenew` (boolean, default true) -- `certificateStore` (string) -- `skipConfiguredCerts` (boolean) -- `domainForwards` (IDomainForwardConfig[]) - ### NfTablesProxy (INfTableProxySettings) - `fromPort` / `toPort` (number|range|array) - `toHost` (string, default 'localhost') @@ -1479,6 +1680,7 @@ HttpProxy now supports full route-based configuration including: - For domain matching issues, verify SNI extraction is working - Use higher priority for block routes to ensure they take precedence - Enable `enableDetailedLogging` or `enableTlsDebugLogging` for debugging +- Security configuration must be at route level (`route.security`), not in action ### ACME HTTP-01 Challenges - If ACME HTTP-01 challenges fail, ensure: @@ -1502,6 +1704,12 @@ HttpProxy now supports full route-based configuration including: - "Connection refused" during challenges → Update to v19.3.9+ for timing fix - HTTP requests not parsed → Ensure port is in `useHttpProxy` array +### Socket Handlers +- Socket handlers require initial data from the client to trigger routing +- For async handlers, initial data is buffered until handler setup completes (v19.5.0+) +- Use `SocketHandlers.httpServer` for ACME challenge handling in custom implementations +- Test socket handlers with telnet or nc for debugging + ### NFTables Integration - Ensure NFTables is installed: `apt install nftables` or `yum install nftables` - Verify root/sudo permissions for NFTables operations @@ -1513,19 +1721,25 @@ HttpProxy now supports full route-based configuration including: - For certificate issues, check the ACME settings and domain validation - Ensure domains are publicly accessible for Let's Encrypt validation - For TLS handshake issues, increase `initialDataTimeout` and `maxPendingDataSize` +- Certificate configuration can be global or per-route ### HttpProxy - Verify ports, certificates and `rejectUnauthorized` for TLS errors - Configure CORS for preflight issues - Increase `maxConnections` or `connectionPoolSize` under load +- HttpProxy is designed for HTTPS/TLS termination, use direct forwarding for plain HTTP -### Port80Handler -- Run as root or grant CAP_NET_BIND_SERVICE for port 80 -- Inspect `certificate-failed` events and switch staging/production +### Security Configuration +- Security must be defined at route level: `route.security` +- IP lists support glob patterns: `192.168.*`, `10.?.?.1` +- Block lists take precedence over allow lists +- Authentication requires TLS termination +- Route matching is separate from security enforcement ### NfTablesProxy - Ensure `nft` is installed and run with sufficient privileges - Use `forceCleanSlate:true` to clear conflicting rules +- Check kernel modules are loaded: `lsmod | grep nf_tables` ## License and Legal Information