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:
Philipp Kunz 2025-05-19 17:39:35 +00:00
parent 5c6437c5b3
commit 4b381915e1
9 changed files with 436 additions and 79 deletions

View File

@ -1,5 +1,27 @@
# 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)
No changes detected project structure and documentation remain unchanged.

View File

@ -208,11 +208,18 @@ const smartproxy = new SmartProxy({
// Certificate provisioning was automatic or via certProvisionFunction
```
### After (v18+)
### After (v19+)
```typescript
// New approach with route-based configuration
// New approach with global ACME configuration
const smartproxy = new SmartProxy({
// Global ACME defaults (v19+)
acme: {
email: 'ssl@bleu.de',
useProduction: true,
port: 80 // Or 8080 for non-privileged
},
routes: [{
match: { ports: 443, domains: 'example.com' },
action: {
@ -220,11 +227,7 @@ const smartproxy = new SmartProxy({
target: { host: 'localhost', port: 8080 },
tls: {
mode: 'terminate',
certificate: 'auto',
acme: {
email: 'admin@example.com',
useProduction: true
}
certificate: 'auto' // Uses global ACME settings
}
}
}]
@ -235,9 +238,38 @@ const smartproxy = new SmartProxy({
### Common Issues
1. **Certificate not provisioning**: Ensure port 80 is accessible for ACME challenges
2. **ACME rate limits**: Use staging environment for testing
1. **Certificate not provisioning**: Ensure the ACME challenge port (80 or configured port) is accessible
2. **ACME rate limits**: Use staging environment for testing (`useProduction: false`)
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

View 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);

View 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);
});

View File

@ -3,27 +3,25 @@
*
* This example demonstrates how to dynamically add and remove ports
* 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';
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({
// Global ACME configuration (v19+)
acme: {
email: 'ssl@bleu.de',
useProduction: false,
port: 8080 // Using non-privileged port for ACME challenges
},
routes: [
// Initial route on port 8080
{
match: {
ports: 8080,
domains: ['example.com', '*.example.com']
},
action: {
type: 'forward',
target: { host: 'localhost', port: 3000 }
},
name: 'Initial HTTP Route'
}
createHttpRoute(['example.com', '*.example.com'], { host: 'localhost', port: 3000 })
]
});

View File

@ -5,6 +5,7 @@
* for high-performance network routing that operates at the kernel level.
*
* 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';
@ -50,15 +51,22 @@ async function simpleForwardingExample() {
async function httpsTerminationExample() {
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({
// Global ACME configuration (v19+)
acme: {
email: 'ssl@bleu.de',
useProduction: false,
port: 80 // NFTables needs root, so we can use port 80
},
routes: [
createNfTablesTerminateRoute('secure.example.com', {
host: 'localhost',
port: 8443
}, {
ports: 443,
certificate: 'auto', // Automatic certificate provisioning
certificate: 'auto', // Uses global ACME configuration
tableName: 'smartproxy_https'
})
],

View File

@ -113,7 +113,7 @@ npm install @push.rocks/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
import {
@ -136,10 +136,12 @@ import {
const proxy = new SmartProxy({
// Global ACME settings for all routes with certificate: 'auto'
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
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
@ -216,26 +218,7 @@ const proxy = new SmartProxy({
certificate: 'auto',
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

View File

@ -1,22 +1,15 @@
# SmartProxy Architecture Refactoring Plan
# SmartProxy v19.4.0 - Completed Refactoring
## 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
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)
### HttpProxy (formerly NetworkProxy)
**Purpose**: Handle all HTTP/HTTPS traffic with TLS termination
**Responsibilities**:
**Current Responsibilities**:
- TLS termination for HTTPS
- HTTP/1.1 and HTTP/2 protocol handling
- HTTP request/response parsing
@ -25,29 +18,33 @@ Refactor the proxy architecture to provide clearer separation of concerns betwee
- Static route handlers
- WebSocket protocol upgrades
- Connection pooling for backend servers
- Certificate management (ACME and static)
- Certificate management integration
### 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)
- Route-based connection routing
- TLS passthrough (SNI-based routing)
- NFTables integration
- Delegate HTTP/HTTPS connections to HttpProxy
- Certificate management via SmartCertManager
- Raw TCP proxying
- 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**
- Renamed directory from `network-proxy` to `http-proxy`
- Updated all imports and references
2. **Update class and file names**
### Phase 2: Certificate Management ✅
- Unified certificate management in SmartCertManager
- Global ACME configuration support (v19+)
- Route-level certificate overrides
- Automatic renewal system
- Renamed `network-proxy.ts` to `http-proxy.ts`
- Updated `NetworkProxy` class to `HttpProxy` class
- Updated all type definitions and interfaces
@ -157,16 +154,26 @@ After this refactoring, we can more easily add:
4. Protocol-specific optimizations
5. Better HTTP/2 multiplexing
## Breaking Changes
## Breaking Changes from v18 to v19
1. `NetworkProxy` class renamed to `HttpProxy`
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. Git revert to previous commit
2. Re-deploy previous version
3. Document lessons learned
4. Plan incremental changes
1. HTTP/3 (QUIC) support in HttpProxy
2. Advanced HTTP features (compression, caching)
3. HTTP middleware system
4. Protocol-specific optimizations
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

View File

@ -3,6 +3,6 @@
*/
export const commitinfo = {
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.'
}