fix(docs, tests, acme): fix: update changelog, documentation, examples and tests for v19.4.0 release. Adjust global ACME configuration to use ssl@bleu.de and add non-privileged port examples.
This commit is contained in:
		
							
								
								
									
										22
									
								
								changelog.md
									
									
									
									
									
								
							
							
						
						
									
										22
									
								
								changelog.md
									
									
									
									
									
								
							| @@ -1,5 +1,27 @@ | |||||||
| # Changelog | # Changelog | ||||||
|  |  | ||||||
|  | ## 2025-05-19 - 19.3.4 - fix(docs, tests, acme) | ||||||
|  | fix: update changelog, documentation, examples and tests for v19.4.0 release. Adjust global ACME configuration to use ssl@bleu.de and add non-privileged port examples. | ||||||
|  |  | ||||||
|  | - Updated changelog with new v19.4.0 entry detailing fixes in tests and docs | ||||||
|  | - Revised README and certificate-management.md to demonstrate global ACME settings (using ssl@bleu.de, non-privileged port support, auto-renewal configuration, and renewCheckIntervalHours) | ||||||
|  | - Added new examples (certificate-management-v19.ts and complete-example-v19.ts) and updated existing examples (dynamic port management, NFTables integration) to reflect v19.4.0 features | ||||||
|  | - Fixed test exports and port mapping issues in several test files (acme-state-manager, port80-management, race-conditions, etc.) | ||||||
|  | - Updated readme.plan.md to reflect completed refactoring and breaking changes from v19.3.3 | ||||||
|  |  | ||||||
|  | ## 2025-05-19 - 19.4.0 - fix(tests) & docs | ||||||
|  | Fix failing tests and update documentation for v19+ features | ||||||
|  |  | ||||||
|  | - Fix ForwardingHandlerFactory.applyDefaults to set port and socket properties correctly | ||||||
|  | - Fix route finding logic in forwarding tests to properly identify redirect routes | ||||||
|  | - Fix test exports in acme-state-manager.node.ts, port80-management.node.ts, and race-conditions.node.ts | ||||||
|  | - Update ACME email configuration to use ssl@bleu.de instead of test domains | ||||||
|  | - Update README with v19.4.0 features including global ACME configuration | ||||||
|  | - Update certificate-management.md documentation to reflect v19+ changes | ||||||
|  | - Add new examples: certificate-management-v19.ts and complete-example-v19.ts | ||||||
|  | - Update existing examples to demonstrate global ACME configuration | ||||||
|  | - Update readme.plan.md to reflect completed refactoring | ||||||
|  |  | ||||||
| ## 2025-05-19 - 19.3.3 - fix(core) | ## 2025-05-19 - 19.3.3 - fix(core) | ||||||
| No changes detected – project structure and documentation remain unchanged. | No changes detected – project structure and documentation remain unchanged. | ||||||
|  |  | ||||||
|   | |||||||
| @@ -208,11 +208,18 @@ const smartproxy = new SmartProxy({ | |||||||
| // Certificate provisioning was automatic or via certProvisionFunction | // Certificate provisioning was automatic or via certProvisionFunction | ||||||
| ``` | ``` | ||||||
|  |  | ||||||
| ### After (v18+) | ### After (v19+) | ||||||
|  |  | ||||||
| ```typescript | ```typescript | ||||||
| // New approach with route-based configuration | // New approach with global ACME configuration | ||||||
| const smartproxy = new SmartProxy({ | const smartproxy = new SmartProxy({ | ||||||
|  |   // Global ACME defaults (v19+) | ||||||
|  |   acme: { | ||||||
|  |     email: 'ssl@bleu.de', | ||||||
|  |     useProduction: true, | ||||||
|  |     port: 80  // Or 8080 for non-privileged | ||||||
|  |   }, | ||||||
|  |    | ||||||
|   routes: [{ |   routes: [{ | ||||||
|     match: { ports: 443, domains: 'example.com' }, |     match: { ports: 443, domains: 'example.com' }, | ||||||
|     action: { |     action: { | ||||||
| @@ -220,11 +227,7 @@ const smartproxy = new SmartProxy({ | |||||||
|       target: { host: 'localhost', port: 8080 }, |       target: { host: 'localhost', port: 8080 }, | ||||||
|       tls: { |       tls: { | ||||||
|         mode: 'terminate', |         mode: 'terminate', | ||||||
|         certificate: 'auto', |         certificate: 'auto'  // Uses global ACME settings | ||||||
|         acme: { |  | ||||||
|           email: 'admin@example.com', |  | ||||||
|           useProduction: true |  | ||||||
|         } |  | ||||||
|       } |       } | ||||||
|     } |     } | ||||||
|   }] |   }] | ||||||
| @@ -235,9 +238,38 @@ const smartproxy = new SmartProxy({ | |||||||
|  |  | ||||||
| ### Common Issues | ### Common Issues | ||||||
|  |  | ||||||
| 1. **Certificate not provisioning**: Ensure port 80 is accessible for ACME challenges | 1. **Certificate not provisioning**: Ensure the ACME challenge port (80 or configured port) is accessible | ||||||
| 2. **ACME rate limits**: Use staging environment for testing | 2. **ACME rate limits**: Use staging environment for testing (`useProduction: false`) | ||||||
| 3. **Permission errors**: Ensure the certificate directory is writable | 3. **Permission errors**: Ensure the certificate directory is writable | ||||||
|  | 4. **Invalid email domain**: ACME servers may reject certain email domains (e.g., example.com). Use a real email domain | ||||||
|  | 5. **Port binding errors**: Use higher ports (e.g., 8080) if running without root privileges | ||||||
|  |  | ||||||
|  | ### Using Non-Privileged Ports | ||||||
|  |  | ||||||
|  | For development or non-root environments: | ||||||
|  |  | ||||||
|  | ```typescript | ||||||
|  | const proxy = new SmartProxy({ | ||||||
|  |   acme: { | ||||||
|  |     email: 'ssl@bleu.de', | ||||||
|  |     port: 8080,  // Use 8080 instead of 80 | ||||||
|  |     useProduction: false | ||||||
|  |   }, | ||||||
|  |   routes: [ | ||||||
|  |     { | ||||||
|  |       match: { ports: 8443, domains: 'example.com' }, | ||||||
|  |       action: { | ||||||
|  |         type: 'forward', | ||||||
|  |         target: { host: 'localhost', port: 3000 }, | ||||||
|  |         tls: { | ||||||
|  |           mode: 'terminate', | ||||||
|  |           certificate: 'auto' | ||||||
|  |         } | ||||||
|  |       } | ||||||
|  |     } | ||||||
|  |   ] | ||||||
|  | }); | ||||||
|  | ``` | ||||||
|  |  | ||||||
| ### Debug Mode | ### Debug Mode | ||||||
|  |  | ||||||
|   | |||||||
							
								
								
									
										119
									
								
								examples/certificate-management-v19.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										119
									
								
								examples/certificate-management-v19.ts
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,119 @@ | |||||||
|  | /** | ||||||
|  |  * Certificate Management Example (v19+) | ||||||
|  |  *  | ||||||
|  |  * This example demonstrates the new global ACME configuration introduced in v19+ | ||||||
|  |  * along with route-level overrides for specific domains. | ||||||
|  |  */ | ||||||
|  |  | ||||||
|  | import {  | ||||||
|  |   SmartProxy,  | ||||||
|  |   createHttpRoute,  | ||||||
|  |   createHttpsTerminateRoute, | ||||||
|  |   createCompleteHttpsServer | ||||||
|  | } from '../dist_ts/index.js'; | ||||||
|  |  | ||||||
|  | async function main() { | ||||||
|  |   // Create a SmartProxy instance with global ACME configuration | ||||||
|  |   const proxy = new SmartProxy({ | ||||||
|  |     // Global ACME configuration (v19+) | ||||||
|  |     // These settings apply to all routes with certificate: 'auto' | ||||||
|  |     acme: { | ||||||
|  |       email: 'ssl@bleu.de',           // Global contact email | ||||||
|  |       useProduction: false,           // Use staging by default | ||||||
|  |       port: 8080,                     // Use non-privileged port | ||||||
|  |       renewThresholdDays: 30,         // Renew 30 days before expiry | ||||||
|  |       autoRenew: true,               // Enable automatic renewal | ||||||
|  |       renewCheckIntervalHours: 12     // Check twice daily | ||||||
|  |     }, | ||||||
|  |      | ||||||
|  |     routes: [ | ||||||
|  |       // Route that uses global ACME settings | ||||||
|  |       createHttpsTerminateRoute('app.example.com',  | ||||||
|  |         { host: 'localhost', port: 3000 },  | ||||||
|  |         { certificate: 'auto' }  // Uses global ACME configuration | ||||||
|  |       ), | ||||||
|  |        | ||||||
|  |       // Route with route-level ACME override | ||||||
|  |       { | ||||||
|  |         name: 'production-api', | ||||||
|  |         match: { ports: 443, domains: 'api.example.com' }, | ||||||
|  |         action: { | ||||||
|  |           type: 'forward', | ||||||
|  |           target: { host: 'localhost', port: 3001 }, | ||||||
|  |           tls: { | ||||||
|  |             mode: 'terminate', | ||||||
|  |             certificate: 'auto', | ||||||
|  |             acme: { | ||||||
|  |               email: 'api-certs@example.com',  // Override email | ||||||
|  |               useProduction: true,             // Use production for API | ||||||
|  |               renewThresholdDays: 60          // Earlier renewal for critical API | ||||||
|  |             } | ||||||
|  |           } | ||||||
|  |         } | ||||||
|  |       }, | ||||||
|  |        | ||||||
|  |       // Complete HTTPS server with automatic redirects | ||||||
|  |       ...createCompleteHttpsServer('website.example.com',  | ||||||
|  |         { host: 'localhost', port: 8080 },  | ||||||
|  |         { certificate: 'auto' } | ||||||
|  |       ), | ||||||
|  |        | ||||||
|  |       // Static certificate (not using ACME) | ||||||
|  |       { | ||||||
|  |         name: 'internal-service', | ||||||
|  |         match: { ports: 8443, domains: 'internal.local' }, | ||||||
|  |         action: { | ||||||
|  |           type: 'forward', | ||||||
|  |           target: { host: 'localhost', port: 3002 }, | ||||||
|  |           tls: { | ||||||
|  |             mode: 'terminate', | ||||||
|  |             certificate: { | ||||||
|  |               cert: '-----BEGIN CERTIFICATE-----\n...\n-----END CERTIFICATE-----', | ||||||
|  |               key: '-----BEGIN PRIVATE KEY-----\n...\n-----END PRIVATE KEY-----' | ||||||
|  |             } | ||||||
|  |           } | ||||||
|  |         } | ||||||
|  |       } | ||||||
|  |     ] | ||||||
|  |   }); | ||||||
|  |    | ||||||
|  |   // Monitor certificate events | ||||||
|  |   proxy.on('certificate:issued', (event) => { | ||||||
|  |     console.log(`Certificate issued for ${event.domain}`); | ||||||
|  |     console.log(`Expires: ${event.expiryDate}`); | ||||||
|  |   }); | ||||||
|  |    | ||||||
|  |   proxy.on('certificate:renewed', (event) => { | ||||||
|  |     console.log(`Certificate renewed for ${event.domain}`); | ||||||
|  |   }); | ||||||
|  |    | ||||||
|  |   proxy.on('certificate:error', (event) => { | ||||||
|  |     console.error(`Certificate error for ${event.domain}: ${event.error}`); | ||||||
|  |   }); | ||||||
|  |    | ||||||
|  |   // Start the proxy | ||||||
|  |   await proxy.start(); | ||||||
|  |   console.log('SmartProxy started with global ACME configuration'); | ||||||
|  |    | ||||||
|  |   // Check certificate status programmatically | ||||||
|  |   setTimeout(async () => { | ||||||
|  |     // Get status for a specific route | ||||||
|  |     const status = proxy.getCertificateStatus('app-route'); | ||||||
|  |     console.log('Certificate status:', status); | ||||||
|  |      | ||||||
|  |     // Manually trigger renewal if needed | ||||||
|  |     if (status && status.status === 'expiring') { | ||||||
|  |       await proxy.renewCertificate('app-route'); | ||||||
|  |     } | ||||||
|  |   }, 10000); | ||||||
|  |    | ||||||
|  |   // Handle shutdown gracefully | ||||||
|  |   process.on('SIGINT', async () => { | ||||||
|  |     console.log('Shutting down proxy...'); | ||||||
|  |     await proxy.stop(); | ||||||
|  |     process.exit(0); | ||||||
|  |   }); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // Run the example | ||||||
|  | main().catch(console.error); | ||||||
							
								
								
									
										188
									
								
								examples/complete-example-v19.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										188
									
								
								examples/complete-example-v19.ts
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,188 @@ | |||||||
|  | /** | ||||||
|  |  * Complete SmartProxy Example (v19+) | ||||||
|  |  *  | ||||||
|  |  * This comprehensive example demonstrates all major features of SmartProxy v19+: | ||||||
|  |  * - Global ACME configuration | ||||||
|  |  * - Route-based configuration | ||||||
|  |  * - Helper functions for common patterns | ||||||
|  |  * - Dynamic route management | ||||||
|  |  * - Certificate status monitoring | ||||||
|  |  * - Error handling and recovery | ||||||
|  |  */ | ||||||
|  |  | ||||||
|  | import {  | ||||||
|  |   SmartProxy, | ||||||
|  |   createHttpRoute, | ||||||
|  |   createHttpsTerminateRoute, | ||||||
|  |   createHttpsPassthroughRoute, | ||||||
|  |   createHttpToHttpsRedirect, | ||||||
|  |   createCompleteHttpsServer, | ||||||
|  |   createLoadBalancerRoute, | ||||||
|  |   createApiRoute, | ||||||
|  |   createWebSocketRoute, | ||||||
|  |   createStaticFileRoute, | ||||||
|  |   createNfTablesRoute | ||||||
|  | } from '../dist_ts/index.js'; | ||||||
|  |  | ||||||
|  | async function main() { | ||||||
|  |   // Create SmartProxy with comprehensive configuration | ||||||
|  |   const proxy = new SmartProxy({ | ||||||
|  |     // Global ACME configuration (v19+) | ||||||
|  |     acme: { | ||||||
|  |       email: 'ssl@bleu.de', | ||||||
|  |       useProduction: false,  // Use staging for this example | ||||||
|  |       port: 8080,           // Non-privileged port for development | ||||||
|  |       autoRenew: true, | ||||||
|  |       renewCheckIntervalHours: 12 | ||||||
|  |     }, | ||||||
|  |      | ||||||
|  |     // Initial routes | ||||||
|  |     routes: [ | ||||||
|  |       // Basic HTTP service | ||||||
|  |       createHttpRoute('api.example.com', { host: 'localhost', port: 3000 }), | ||||||
|  |        | ||||||
|  |       // HTTPS with automatic certificates | ||||||
|  |       createHttpsTerminateRoute('secure.example.com',  | ||||||
|  |         { host: 'localhost', port: 3001 },  | ||||||
|  |         { certificate: 'auto' } | ||||||
|  |       ), | ||||||
|  |        | ||||||
|  |       // Complete HTTPS server with HTTP->HTTPS redirect | ||||||
|  |       ...createCompleteHttpsServer('www.example.com',  | ||||||
|  |         { host: 'localhost', port: 8080 },  | ||||||
|  |         { certificate: 'auto' } | ||||||
|  |       ), | ||||||
|  |        | ||||||
|  |       // Load balancer with multiple backends | ||||||
|  |       createLoadBalancerRoute( | ||||||
|  |         'app.example.com', | ||||||
|  |         ['10.0.0.1', '10.0.0.2', '10.0.0.3'], | ||||||
|  |         8080, | ||||||
|  |         { | ||||||
|  |           tls: { | ||||||
|  |             mode: 'terminate', | ||||||
|  |             certificate: 'auto' | ||||||
|  |           } | ||||||
|  |         } | ||||||
|  |       ), | ||||||
|  |        | ||||||
|  |       // API route with CORS | ||||||
|  |       createApiRoute('api.example.com', '/v1',  | ||||||
|  |         { host: 'api-backend', port: 8081 },  | ||||||
|  |         { | ||||||
|  |           useTls: true, | ||||||
|  |           certificate: 'auto', | ||||||
|  |           addCorsHeaders: true | ||||||
|  |         } | ||||||
|  |       ), | ||||||
|  |        | ||||||
|  |       // WebSocket support | ||||||
|  |       createWebSocketRoute('ws.example.com', '/socket',  | ||||||
|  |         { host: 'websocket-server', port: 8082 },  | ||||||
|  |         { | ||||||
|  |           useTls: true, | ||||||
|  |           certificate: 'auto' | ||||||
|  |         } | ||||||
|  |       ), | ||||||
|  |        | ||||||
|  |       // Static file server | ||||||
|  |       createStaticFileRoute(['cdn.example.com', 'static.example.com'],  | ||||||
|  |         '/var/www/static',  | ||||||
|  |         { | ||||||
|  |           serveOnHttps: true, | ||||||
|  |           certificate: 'auto' | ||||||
|  |         } | ||||||
|  |       ), | ||||||
|  |        | ||||||
|  |       // HTTPS passthrough for services that handle their own TLS | ||||||
|  |       createHttpsPassthroughRoute('legacy.example.com',  | ||||||
|  |         { host: '192.168.1.100', port: 443 } | ||||||
|  |       ), | ||||||
|  |        | ||||||
|  |       // HTTP to HTTPS redirects | ||||||
|  |       createHttpToHttpsRedirect(['*.example.com', 'example.com']) | ||||||
|  |     ], | ||||||
|  |      | ||||||
|  |     // Enable detailed logging for debugging | ||||||
|  |     enableDetailedLogging: true | ||||||
|  |   }); | ||||||
|  |    | ||||||
|  |   // Event handlers | ||||||
|  |   proxy.on('connection', (event) => { | ||||||
|  |     console.log(`New connection: ${event.source} -> ${event.destination}`); | ||||||
|  |   }); | ||||||
|  |    | ||||||
|  |   proxy.on('certificate:issued', (event) => { | ||||||
|  |     console.log(`Certificate issued for ${event.domain}`); | ||||||
|  |   }); | ||||||
|  |    | ||||||
|  |   proxy.on('certificate:renewed', (event) => { | ||||||
|  |     console.log(`Certificate renewed for ${event.domain}`); | ||||||
|  |   }); | ||||||
|  |    | ||||||
|  |   proxy.on('error', (error) => { | ||||||
|  |     console.error('Proxy error:', error); | ||||||
|  |   }); | ||||||
|  |    | ||||||
|  |   // Start the proxy | ||||||
|  |   await proxy.start(); | ||||||
|  |   console.log('SmartProxy started successfully'); | ||||||
|  |   console.log('Listening on ports:', proxy.getListeningPorts()); | ||||||
|  |    | ||||||
|  |   // Demonstrate dynamic route management | ||||||
|  |   setTimeout(async () => { | ||||||
|  |     console.log('Adding new route dynamically...'); | ||||||
|  |      | ||||||
|  |     // Get current routes and add a new one | ||||||
|  |     const currentRoutes = proxy.settings.routes; | ||||||
|  |     const newRoutes = [ | ||||||
|  |       ...currentRoutes, | ||||||
|  |       createHttpsTerminateRoute('new-service.example.com',  | ||||||
|  |         { host: 'localhost', port: 3003 },  | ||||||
|  |         { certificate: 'auto' } | ||||||
|  |       ) | ||||||
|  |     ]; | ||||||
|  |      | ||||||
|  |     // Update routes | ||||||
|  |     await proxy.updateRoutes(newRoutes); | ||||||
|  |     console.log('New route added successfully'); | ||||||
|  |   }, 5000); | ||||||
|  |    | ||||||
|  |   // Check certificate status periodically | ||||||
|  |   setInterval(async () => { | ||||||
|  |     const routes = proxy.settings.routes; | ||||||
|  |     for (const route of routes) { | ||||||
|  |       if (route.action.tls?.certificate === 'auto') { | ||||||
|  |         const status = proxy.getCertificateStatus(route.name); | ||||||
|  |         if (status) { | ||||||
|  |           console.log(`Certificate status for ${route.name}:`, status); | ||||||
|  |            | ||||||
|  |           // Renew if expiring soon | ||||||
|  |           if (status.status === 'expiring') { | ||||||
|  |             console.log(`Renewing certificate for ${route.name}...`); | ||||||
|  |             await proxy.renewCertificate(route.name); | ||||||
|  |           } | ||||||
|  |         } | ||||||
|  |       } | ||||||
|  |     } | ||||||
|  |   }, 3600000); // Check every hour | ||||||
|  |    | ||||||
|  |   // Graceful shutdown | ||||||
|  |   process.on('SIGINT', async () => { | ||||||
|  |     console.log('Shutting down gracefully...'); | ||||||
|  |     await proxy.stop(); | ||||||
|  |     process.exit(0); | ||||||
|  |   }); | ||||||
|  |    | ||||||
|  |   process.on('SIGTERM', async () => { | ||||||
|  |     console.log('Received SIGTERM, shutting down...'); | ||||||
|  |     await proxy.stop(); | ||||||
|  |     process.exit(0); | ||||||
|  |   }); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // Run the example | ||||||
|  | main().catch((error) => { | ||||||
|  |   console.error('Failed to start proxy:', error); | ||||||
|  |   process.exit(1); | ||||||
|  | }); | ||||||
| @@ -3,27 +3,25 @@ | |||||||
|  *  |  *  | ||||||
|  * This example demonstrates how to dynamically add and remove ports |  * This example demonstrates how to dynamically add and remove ports | ||||||
|  * while SmartProxy is running, without requiring a restart. |  * while SmartProxy is running, without requiring a restart. | ||||||
|  |  * Also shows the new v19+ global ACME configuration. | ||||||
|  */ |  */ | ||||||
|  |  | ||||||
| import { SmartProxy } from '../dist_ts/index.js'; | import { SmartProxy, createHttpRoute, createHttpsTerminateRoute } from '../dist_ts/index.js'; | ||||||
| import type { IRouteConfig } from '../dist_ts/index.js'; | import type { IRouteConfig } from '../dist_ts/index.js'; | ||||||
|  |  | ||||||
| async function main() { | async function main() { | ||||||
|   // Create a SmartProxy instance with initial routes |   // Create a SmartProxy instance with initial routes and global ACME config | ||||||
|   const proxy = new SmartProxy({ |   const proxy = new SmartProxy({ | ||||||
|  |     // Global ACME configuration (v19+) | ||||||
|  |     acme: { | ||||||
|  |       email: 'ssl@bleu.de', | ||||||
|  |       useProduction: false, | ||||||
|  |       port: 8080  // Using non-privileged port for ACME challenges | ||||||
|  |     }, | ||||||
|  |      | ||||||
|     routes: [ |     routes: [ | ||||||
|       // Initial route on port 8080 |       // Initial route on port 8080 | ||||||
|       { |       createHttpRoute(['example.com', '*.example.com'], { host: 'localhost', port: 3000 }) | ||||||
|         match: {  |  | ||||||
|           ports: 8080, |  | ||||||
|           domains: ['example.com', '*.example.com'] |  | ||||||
|         }, |  | ||||||
|         action: { |  | ||||||
|           type: 'forward', |  | ||||||
|           target: { host: 'localhost', port: 3000 } |  | ||||||
|         }, |  | ||||||
|         name: 'Initial HTTP Route' |  | ||||||
|       } |  | ||||||
|     ] |     ] | ||||||
|   }); |   }); | ||||||
|  |  | ||||||
|   | |||||||
| @@ -5,6 +5,7 @@ | |||||||
|  * for high-performance network routing that operates at the kernel level. |  * for high-performance network routing that operates at the kernel level. | ||||||
|  *  |  *  | ||||||
|  * NOTE: This requires elevated privileges to run (sudo) as it interacts with nftables. |  * NOTE: This requires elevated privileges to run (sudo) as it interacts with nftables. | ||||||
|  |  * Also shows the new v19+ global ACME configuration. | ||||||
|  */ |  */ | ||||||
|  |  | ||||||
| import { SmartProxy } from '../ts/proxies/smart-proxy/index.js'; | import { SmartProxy } from '../ts/proxies/smart-proxy/index.js'; | ||||||
| @@ -50,15 +51,22 @@ async function simpleForwardingExample() { | |||||||
| async function httpsTerminationExample() { | async function httpsTerminationExample() { | ||||||
|   console.log('Starting HTTPS termination with NFTables example...'); |   console.log('Starting HTTPS termination with NFTables example...'); | ||||||
|    |    | ||||||
|   // Create a SmartProxy instance with an HTTPS termination route using NFTables |   // Create a SmartProxy instance with global ACME and NFTables HTTPS termination | ||||||
|   const proxy = new SmartProxy({ |   const proxy = new SmartProxy({ | ||||||
|  |     // Global ACME configuration (v19+) | ||||||
|  |     acme: { | ||||||
|  |       email: 'ssl@bleu.de', | ||||||
|  |       useProduction: false, | ||||||
|  |       port: 80  // NFTables needs root, so we can use port 80 | ||||||
|  |     }, | ||||||
|  |      | ||||||
|     routes: [ |     routes: [ | ||||||
|       createNfTablesTerminateRoute('secure.example.com', { |       createNfTablesTerminateRoute('secure.example.com', { | ||||||
|         host: 'localhost', |         host: 'localhost', | ||||||
|         port: 8443 |         port: 8443 | ||||||
|       }, { |       }, { | ||||||
|         ports: 443, |         ports: 443, | ||||||
|         certificate: 'auto', // Automatic certificate provisioning |         certificate: 'auto', // Uses global ACME configuration | ||||||
|         tableName: 'smartproxy_https' |         tableName: 'smartproxy_https' | ||||||
|       }) |       }) | ||||||
|     ], |     ], | ||||||
|   | |||||||
							
								
								
									
										29
									
								
								readme.md
									
									
									
									
									
								
							
							
						
						
									
										29
									
								
								readme.md
									
									
									
									
									
								
							| @@ -113,7 +113,7 @@ npm install @push.rocks/smartproxy | |||||||
|  |  | ||||||
| ## Quick Start with SmartProxy | ## Quick Start with SmartProxy | ||||||
|  |  | ||||||
| SmartProxy v18.0.0 continues the evolution of the unified route-based configuration system making your proxy setup more flexible and intuitive with improved helper functions and NFTables integration for high-performance kernel-level routing. | 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. | ||||||
|  |  | ||||||
| ```typescript | ```typescript | ||||||
| import { | import { | ||||||
| @@ -136,10 +136,12 @@ import { | |||||||
| const proxy = new SmartProxy({ | const proxy = new SmartProxy({ | ||||||
|   // Global ACME settings for all routes with certificate: 'auto' |   // Global ACME settings for all routes with certificate: 'auto' | ||||||
|   acme: { |   acme: { | ||||||
|     email: 'ssl@example.com',      // Required for Let's Encrypt |     email: 'ssl@bleu.de',          // Required for Let's Encrypt | ||||||
|     useProduction: false,          // Use staging by default |     useProduction: false,          // Use staging by default | ||||||
|     renewThresholdDays: 30,        // Renew 30 days before expiry |     renewThresholdDays: 30,        // Renew 30 days before expiry | ||||||
|     port: 80                       // Port for HTTP-01 challenges |     port: 80,                      // Port for HTTP-01 challenges (use 8080 for non-privileged) | ||||||
|  |     autoRenew: true,              // Enable automatic renewal | ||||||
|  |     renewCheckIntervalHours: 24    // Check for renewals daily | ||||||
|   }, |   }, | ||||||
|    |    | ||||||
|   // Define all your routing rules in a single array |   // Define all your routing rules in a single array | ||||||
| @@ -216,26 +218,7 @@ const proxy = new SmartProxy({ | |||||||
|       certificate: 'auto', |       certificate: 'auto', | ||||||
|       maxRate: '100mbps' |       maxRate: '100mbps' | ||||||
|     }) |     }) | ||||||
|   ], |   ] | ||||||
|  |  | ||||||
|   // Global settings that apply to all routes |  | ||||||
|   defaults: { |  | ||||||
|     security: { |  | ||||||
|       maxConnections: 500 |  | ||||||
|     } |  | ||||||
|   }, |  | ||||||
|  |  | ||||||
|   // Automatic Let's Encrypt integration |  | ||||||
|   acme: { |  | ||||||
|     enabled: true, |  | ||||||
|     contactEmail: 'admin@example.com', |  | ||||||
|     useProduction: true |  | ||||||
|   } |  | ||||||
| }); |  | ||||||
|  |  | ||||||
| // Listen for certificate events |  | ||||||
| proxy.on('certificate', evt => { |  | ||||||
|   console.log(`Certificate for ${evt.domain} ready, expires: ${evt.expiryDate}`); |  | ||||||
| }); | }); | ||||||
|  |  | ||||||
| // Start the proxy | // Start the proxy | ||||||
|   | |||||||
| @@ -1,22 +1,15 @@ | |||||||
| # SmartProxy Architecture Refactoring Plan | # SmartProxy v19.4.0 - Completed Refactoring | ||||||
|  |  | ||||||
| ## Overview | ## Overview | ||||||
|  |  | ||||||
| Refactor the proxy architecture to provide clearer separation of concerns between HTTP/HTTPS traffic handling and low-level connection routing. | SmartProxy has been successfully refactored with clearer separation of concerns between HTTP/HTTPS traffic handling and low-level connection routing. Version 19.4.0 introduces global ACME configuration and enhanced route management. | ||||||
|  |  | ||||||
| ## Current Architecture Problems | ## Current Architecture (v19.4.0) | ||||||
|  |  | ||||||
| 1. NetworkProxy name doesn't clearly indicate it handles HTTP/HTTPS | ### HttpProxy (formerly NetworkProxy) | ||||||
| 2. HTTP parsing logic is duplicated in RouteConnectionHandler |  | ||||||
| 3. Redirect and static route handling is embedded in SmartProxy |  | ||||||
| 4. Unclear separation between TCP routing and HTTP processing |  | ||||||
|  |  | ||||||
| ## Proposed Architecture |  | ||||||
|  |  | ||||||
| ### HttpProxy (renamed from NetworkProxy) |  | ||||||
| **Purpose**: Handle all HTTP/HTTPS traffic with TLS termination | **Purpose**: Handle all HTTP/HTTPS traffic with TLS termination | ||||||
|  |  | ||||||
| **Responsibilities**: | **Current Responsibilities**: | ||||||
| - TLS termination for HTTPS | - TLS termination for HTTPS | ||||||
| - HTTP/1.1 and HTTP/2 protocol handling | - HTTP/1.1 and HTTP/2 protocol handling | ||||||
| - HTTP request/response parsing | - HTTP request/response parsing | ||||||
| @@ -25,29 +18,33 @@ Refactor the proxy architecture to provide clearer separation of concerns betwee | |||||||
| - Static route handlers | - Static route handlers | ||||||
| - WebSocket protocol upgrades | - WebSocket protocol upgrades | ||||||
| - Connection pooling for backend servers | - Connection pooling for backend servers | ||||||
| - Certificate management (ACME and static) | - Certificate management integration | ||||||
|  |  | ||||||
| ### SmartProxy | ### SmartProxy | ||||||
| **Purpose**: Low-level connection router and port manager | **Purpose**: Central API for all proxy needs with route-based configuration | ||||||
|  |  | ||||||
| **Responsibilities**: | **Current Responsibilities**: | ||||||
| - Port management (listen on multiple ports) | - Port management (listen on multiple ports) | ||||||
| - Route-based connection routing | - Route-based connection routing | ||||||
| - TLS passthrough (SNI-based routing) | - TLS passthrough (SNI-based routing) | ||||||
| - NFTables integration | - NFTables integration | ||||||
| - Delegate HTTP/HTTPS connections to HttpProxy | - Certificate management via SmartCertManager | ||||||
| - Raw TCP proxying | - Raw TCP proxying | ||||||
| - Connection lifecycle management | - Connection lifecycle management | ||||||
|  | - Global ACME configuration (v19+) | ||||||
|  |  | ||||||
| ## Implementation Plan | ## Completed Implementation | ||||||
|  |  | ||||||
| ### Phase 1: Rename and Reorganize NetworkProxy ✅ | ### Phase 1: Rename and Reorganize ✅ | ||||||
|  | - NetworkProxy renamed to HttpProxy | ||||||
|  | - Directory structure reorganized | ||||||
|  | - All imports and references updated | ||||||
|  |  | ||||||
| 1. **Rename NetworkProxy to HttpProxy** | ### Phase 2: Certificate Management ✅ | ||||||
|    - Renamed directory from `network-proxy` to `http-proxy` | - Unified certificate management in SmartCertManager | ||||||
|    - Updated all imports and references | - Global ACME configuration support (v19+) | ||||||
|  | - Route-level certificate overrides | ||||||
| 2. **Update class and file names** | - Automatic renewal system | ||||||
|    - Renamed `network-proxy.ts` to `http-proxy.ts` |    - Renamed `network-proxy.ts` to `http-proxy.ts` | ||||||
|    - Updated `NetworkProxy` class to `HttpProxy` class |    - Updated `NetworkProxy` class to `HttpProxy` class | ||||||
|    - Updated all type definitions and interfaces |    - Updated all type definitions and interfaces | ||||||
| @@ -157,16 +154,26 @@ After this refactoring, we can more easily add: | |||||||
| 4. Protocol-specific optimizations | 4. Protocol-specific optimizations | ||||||
| 5. Better HTTP/2 multiplexing | 5. Better HTTP/2 multiplexing | ||||||
|  |  | ||||||
| ## Breaking Changes | ## Breaking Changes from v18 to v19 | ||||||
|  |  | ||||||
| 1. `NetworkProxy` class renamed to `HttpProxy` | 1. `NetworkProxy` class renamed to `HttpProxy` | ||||||
| 2. Import paths change from `network-proxy` to `http-proxy` | 2. Import paths change from `network-proxy` to `http-proxy` | ||||||
| 3. Some type names may change for consistency | 3. Global ACME configuration now available at the top level | ||||||
|  | 4. Certificate management unified under SmartCertManager | ||||||
|  |  | ||||||
| ## Rollback Plan | ## Future Enhancements | ||||||
|  |  | ||||||
| If issues arise: | 1. HTTP/3 (QUIC) support in HttpProxy | ||||||
| 1. Git revert to previous commit | 2. Advanced HTTP features (compression, caching) | ||||||
| 2. Re-deploy previous version | 3. HTTP middleware system | ||||||
| 3. Document lessons learned | 4. Protocol-specific optimizations | ||||||
| 4. Plan incremental changes | 5. Better HTTP/2 multiplexing | ||||||
|  | 6. Enhanced monitoring and metrics | ||||||
|  |  | ||||||
|  | ## Key Features in v19.4.0 | ||||||
|  |  | ||||||
|  | 1. **Global ACME Configuration**: Default settings for all routes with `certificate: 'auto'` | ||||||
|  | 2. **Enhanced Route Management**: Better separation between routing and certificate management | ||||||
|  | 3. **Improved Test Coverage**: Fixed test exports and port bindings | ||||||
|  | 4. **Better Error Messages**: Clear guidance for ACME configuration issues | ||||||
|  | 5. **Non-Privileged Port Support**: Examples for development environments | ||||||
| @@ -3,6 +3,6 @@ | |||||||
|  */ |  */ | ||||||
| export const commitinfo = { | export const commitinfo = { | ||||||
|   name: '@push.rocks/smartproxy', |   name: '@push.rocks/smartproxy', | ||||||
|   version: '19.3.3', |   version: '19.3.4', | ||||||
|   description: '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.' |   description: '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.' | ||||||
| } | } | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user