feat(rustproxy): introduce a Rust-powered proxy engine and workspace with core crates for proxy functionality, ACME/TLS support, passthrough and HTTP proxies, metrics, nftables integration, routing/security, management IPC, tests, and README updates

This commit is contained in:
2026-02-09 10:55:46 +00:00
parent a31fee41df
commit 1df3b7af4a
151 changed files with 16927 additions and 19432 deletions

719
readme.md
View File

@@ -1,6 +1,6 @@
# @push.rocks/smartproxy 🚀
**The Swiss Army Knife of Node.js Proxies** - A unified, high-performance proxy toolkit that handles everything from simple HTTP forwarding to complex enterprise routing scenarios.
**A high-performance, Rust-powered proxy toolkit for Node.js** unified route-based configuration for SSL/TLS termination, HTTP/HTTPS reverse proxying, WebSocket support, load balancing, custom protocol handlers, and kernel-level NFTables forwarding.
## 📦 Installation
@@ -16,22 +16,26 @@ For reporting bugs, issues, or security vulnerabilities, please visit [community
## 🎯 What is SmartProxy?
SmartProxy is a modern, production-ready proxy solution that brings order to the chaos of traffic management. Whether you're building microservices, deploying edge infrastructure, or need a battle-tested reverse proxy, SmartProxy has you covered.
SmartProxy is a production-ready proxy solution that takes the complexity out of traffic management. Under the hood, all networking — TCP, TLS, HTTP reverse proxy, connection tracking, security enforcement, and NFTables — is handled by a **Rust engine** for maximum performance, while you configure everything through a clean TypeScript API with full type safety.
Whether you're building microservices, deploying edge infrastructure, or need a battle-tested reverse proxy with automatic Let's Encrypt certificates, SmartProxy has you covered.
### ⚡ Key Features
| Feature | Description |
|---------|-------------|
| 🦀 **Rust-Powered Engine** | All networking handled by a high-performance Rust binary via IPC |
| 🔀 **Unified Route-Based Config** | Clean match/action patterns for intuitive traffic routing |
| 🔒 **Automatic SSL/TLS** | Zero-config HTTPS with Let's Encrypt ACME integration |
| 🎯 **Flexible Matching** | Route by port, domain, path, client IP, TLS version, or custom logic |
| 🎯 **Flexible Matching** | Route by port, domain, path, client IP, TLS version, headers, or custom logic |
| 🚄 **High-Performance** | Choose between user-space or kernel-level (NFTables) forwarding |
| ⚖️ **Load Balancing** | Distribute traffic with health checks and multiple algorithms |
| 🛡️ **Enterprise Security** | IP filtering, rate limiting, authentication, connection limits |
| ⚖️ **Load Balancing** | Round-robin, least-connections, IP-hash with health checks |
| 🛡️ **Enterprise Security** | IP filtering, rate limiting, basic auth, JWT auth, connection limits |
| 🔌 **WebSocket Support** | First-class WebSocket proxying with ping/pong keep-alive |
| 🎮 **Custom Protocols** | Socket handlers for implementing any protocol |
| 🎮 **Custom Protocols** | Socket handlers for implementing any protocol in TypeScript |
| 📊 **Live Metrics** | Real-time throughput, connection counts, and performance data |
| 🔧 **Dynamic Management** | Add/remove ports and routes at runtime without restarts |
| 🔄 **PROXY Protocol** | Full PROXY protocol v1/v2 support for preserving client information |
## 🚀 Quick Start
@@ -43,16 +47,16 @@ import { SmartProxy, createCompleteHttpsServer } from '@push.rocks/smartproxy';
// Create a proxy with automatic HTTPS
const proxy = new SmartProxy({
acme: {
email: 'ssl@yourdomain.com', // Your email for Let's Encrypt
useProduction: true // Use production servers
email: 'ssl@yourdomain.com',
useProduction: true
},
routes: [
// Complete HTTPS setup in one line! ✨
// Complete HTTPS setup in one call! ✨
...createCompleteHttpsServer('app.example.com', {
host: 'localhost',
port: 3000
}, {
certificate: 'auto' // Magic! 🎩
certificate: 'auto' // Automatic Let's Encrypt cert 🎩
})
]
});
@@ -84,10 +88,11 @@ SmartProxy uses a powerful **match/action** pattern that makes routing predictab
```
Every route consists of:
- **Match** - What traffic to capture (ports, domains, paths, IPs)
- **Action** - What to do with it (forward, redirect, block, socket-handler)
- **Security** (optional) - Access controls, rate limits, authentication
- **Name/Priority** (optional) - For identification and ordering
- **Match** What traffic to capture (ports, domains, paths, IPs, headers)
- **Action** What to do with it (`forward` or `socket-handler`)
- **Security** (optional) — IP allow/block lists, rate limits, authentication
- **Headers** (optional) — Request/response header manipulation with template variables
- **Name/Priority** (optional) — For identification and ordering
### 🔄 TLS Modes
@@ -95,8 +100,8 @@ SmartProxy supports three TLS handling modes:
| Mode | Description | Use Case |
|------|-------------|----------|
| `passthrough` | Forward encrypted traffic as-is | Backend handles TLS |
| `terminate` | Decrypt at proxy, forward plain | Standard reverse proxy |
| `passthrough` | Forward encrypted traffic as-is (SNI-based routing) | Backend handles TLS |
| `terminate` | Decrypt at proxy, forward plain HTTP to backend | Standard reverse proxy |
| `terminate-and-reencrypt` | Decrypt, then re-encrypt to backend | Zero-trust environments |
## 💡 Common Use Cases
@@ -116,53 +121,61 @@ const proxy = new SmartProxy({
### ⚖️ Load Balancer with Health Checks
```typescript
import { createLoadBalancerRoute } from '@push.rocks/smartproxy';
import { SmartProxy, createLoadBalancerRoute } from '@push.rocks/smartproxy';
const route = createLoadBalancerRoute(
'app.example.com',
[
{ host: 'server1.internal', port: 8080 },
{ host: 'server2.internal', port: 8080 },
{ host: 'server3.internal', port: 8080 }
],
{
tls: { mode: 'terminate', certificate: 'auto' },
loadBalancing: {
algorithm: 'round-robin',
healthCheck: {
path: '/health',
interval: 30000,
timeout: 5000
const proxy = new SmartProxy({
routes: [
createLoadBalancerRoute(
'app.example.com',
[
{ host: 'server1.internal', port: 8080 },
{ host: 'server2.internal', port: 8080 },
{ host: 'server3.internal', port: 8080 }
],
{
tls: { mode: 'terminate', certificate: 'auto' },
loadBalancing: {
algorithm: 'round-robin',
healthCheck: {
path: '/health',
interval: 30000,
timeout: 5000
}
}
}
}
}
);
)
]
});
```
### 🔌 WebSocket Proxy
```typescript
import { createWebSocketRoute } from '@push.rocks/smartproxy';
import { SmartProxy, createWebSocketRoute } from '@push.rocks/smartproxy';
const route = createWebSocketRoute(
'ws.example.com',
{ host: 'websocket-server', port: 8080 },
{
path: '/socket',
useTls: true,
certificate: 'auto',
pingInterval: 30000, // Keep connections alive
pingTimeout: 10000
}
);
const proxy = new SmartProxy({
routes: [
createWebSocketRoute(
'ws.example.com',
{ host: 'websocket-server', port: 8080 },
{
path: '/socket',
useTls: true,
certificate: 'auto',
pingInterval: 30000,
pingTimeout: 10000
}
)
]
});
```
### 🚦 API Gateway with Rate Limiting
```typescript
import { createApiGatewayRoute, addRateLimiting } from '@push.rocks/smartproxy';
import { SmartProxy, createApiGatewayRoute, addRateLimiting } from '@push.rocks/smartproxy';
let route = createApiGatewayRoute(
let apiRoute = createApiGatewayRoute(
'api.example.com',
'/api',
{ host: 'api-backend', port: 8080 },
@@ -173,20 +186,22 @@ let route = createApiGatewayRoute(
}
);
// Add rate limiting - 100 requests per minute per IP
route = addRateLimiting(route, {
// Add rate limiting 100 requests per minute per IP
apiRoute = addRateLimiting(apiRoute, {
maxRequests: 100,
window: 60,
keyBy: 'ip'
});
const proxy = new SmartProxy({ routes: [apiRoute] });
```
### 🎮 Custom Protocol Handler
SmartProxy lets you implement any protocol with full socket control:
SmartProxy lets you implement any protocol with full socket control. Routes with JavaScript socket handlers are automatically relayed from the Rust engine back to your TypeScript code:
```typescript
import { createSocketHandlerRoute, SocketHandlers } from '@push.rocks/smartproxy';
import { SmartProxy, createSocketHandlerRoute, SocketHandlers } from '@push.rocks/smartproxy';
// Use pre-built handlers
const echoRoute = createSocketHandlerRoute(
@@ -214,18 +229,21 @@ const customRoute = createSocketHandlerRoute(
});
}
);
const proxy = new SmartProxy({ routes: [echoRoute, customRoute] });
```
**Pre-built Socket Handlers:**
| Handler | Description |
|---------|-------------|
| `SocketHandlers.echo` | Echo server - returns everything sent |
| `SocketHandlers.echo` | Echo server returns everything sent |
| `SocketHandlers.proxy(host, port)` | TCP proxy to another server |
| `SocketHandlers.lineProtocol(handler)` | Line-based text protocol |
| `SocketHandlers.httpResponse(code, body)` | Simple HTTP response |
| `SocketHandlers.httpRedirect(url, code)` | HTTP redirect with templates |
| `SocketHandlers.httpRedirect(url, code)` | HTTP redirect with template variables (`{domain}`, `{path}`, `{port}`, `{clientIp}`) |
| `SocketHandlers.httpServer(handler)` | Full HTTP request/response handling |
| `SocketHandlers.httpBlock(status, message)` | HTTP block response |
| `SocketHandlers.block(message)` | Block with optional message |
### ⚡ High-Performance NFTables Forwarding
@@ -233,48 +251,73 @@ const customRoute = createSocketHandlerRoute(
For ultra-low latency on Linux, use kernel-level forwarding (requires root):
```typescript
import { createNfTablesTerminateRoute } from '@push.rocks/smartproxy';
import { SmartProxy, createNfTablesTerminateRoute } from '@push.rocks/smartproxy';
const route = createNfTablesTerminateRoute(
'fast.example.com',
{ host: 'backend', port: 8080 },
{
ports: 443,
certificate: 'auto',
preserveSourceIP: true, // Backend sees real client IP
maxRate: '1gbps' // QoS rate limiting
}
);
const proxy = new SmartProxy({
routes: [
createNfTablesTerminateRoute(
'fast.example.com',
{ host: 'backend', port: 8080 },
{
ports: 443,
certificate: 'auto',
preserveSourceIP: true, // Backend sees real client IP
maxRate: '1gbps' // QoS rate limiting
}
)
]
});
```
### 🔒 SNI Passthrough (TLS Passthrough)
Forward encrypted traffic to backends without terminating TLS — the proxy routes based on the SNI hostname alone:
```typescript
import { SmartProxy, createHttpsPassthroughRoute } from '@push.rocks/smartproxy';
const proxy = new SmartProxy({
routes: [
createHttpsPassthroughRoute('secure.example.com', {
host: 'backend-that-handles-tls',
port: 8443
})
]
});
```
## 🔧 Advanced Features
### 🎯 Dynamic Routing
Route traffic based on runtime conditions:
Route traffic based on runtime conditions using function-based host/port resolution:
```typescript
{
name: 'business-hours-only',
match: {
ports: 443,
domains: 'internal.example.com'
},
action: {
type: 'forward',
targets: [{
host: (context) => {
// Dynamic host selection based on path
return context.path?.startsWith('/premium')
? 'premium-backend'
: 'standard-backend';
},
port: 8080
}]
}
}
const proxy = new SmartProxy({
routes: [{
name: 'dynamic-backend',
match: {
ports: 443,
domains: 'app.example.com'
},
action: {
type: 'forward',
targets: [{
host: (context) => {
return context.path?.startsWith('/premium')
? 'premium-backend'
: 'standard-backend';
},
port: 8080
}],
tls: { mode: 'terminate', certificate: 'auto' }
}
}]
});
```
> **Note:** Routes with dynamic functions (host/port callbacks) are automatically relayed through the TypeScript socket handler server, since JavaScript functions can't be serialized to Rust.
### 🔒 Security Controls
Comprehensive per-route security options:
@@ -285,7 +328,8 @@ Comprehensive per-route security options:
match: { ports: 443, domains: 'api.example.com' },
action: {
type: 'forward',
targets: [{ host: 'api-backend', port: 8080 }]
targets: [{ host: 'api-backend', port: 8080 }],
tls: { mode: 'terminate', certificate: 'auto' }
},
security: {
// IP-based access control
@@ -294,17 +338,31 @@ Comprehensive per-route security options:
// Connection limits
maxConnections: 1000,
maxConnectionsPerIp: 10,
// Rate limiting
rateLimit: {
enabled: true,
maxRequests: 100,
windowMs: 60000
}
window: 60
},
// Authentication
basicAuth: { users: [{ username: 'admin', password: 'secret' }] },
jwtAuth: { secret: 'your-jwt-secret', algorithm: 'HS256' }
}
}
```
**Security modifier helpers** let you add security to any existing route:
```typescript
import { addRateLimiting, addBasicAuth, addJwtAuth } from '@push.rocks/smartproxy';
let route = createHttpsTerminateRoute('api.example.com', { host: 'backend', port: 8080 });
route = addRateLimiting(route, { maxRequests: 100, window: 60, keyBy: 'ip' });
route = addBasicAuth(route, { users: [{ username: 'admin', password: 'secret' }] });
```
### 📊 Runtime Management
Control your proxy without restarts:
@@ -313,21 +371,26 @@ Control your proxy without restarts:
// Dynamic port management
await proxy.addListeningPort(8443);
await proxy.removeListeningPort(8080);
const ports = await proxy.getListeningPorts();
// Update routes on the fly
// Update routes on the fly (atomic, mutex-locked)
await proxy.updateRoutes([...newRoutes]);
// Monitor status
const status = proxy.getStatus();
console.log(`Active connections: ${status.activeConnections}`);
// Get detailed metrics
// Get real-time metrics
const metrics = proxy.getMetrics();
console.log(`Throughput: ${metrics.throughput.bytesPerSecond} bytes/sec`);
console.log(`Active connections: ${metrics.connections.active()}`);
console.log(`Requests/sec: ${metrics.throughput.requestsPerSecond()}`);
// Get detailed statistics from the Rust engine
const stats = await proxy.getStatistics();
// Certificate management
const certInfo = proxy.getCertificateInfo('example.com');
console.log(`Certificate expires: ${certInfo.expiresAt}`);
await proxy.provisionCertificate('my-route-name');
await proxy.renewCertificate('my-route-name');
const certStatus = await proxy.getCertificateStatus('my-route-name');
// NFTables status
const nftStatus = await proxy.getNfTablesStatus();
```
### 🔄 Header Manipulation
@@ -338,51 +401,107 @@ Transform requests and responses with template variables:
{
action: {
type: 'forward',
targets: [{ host: 'backend', port: 8080 }],
headers: {
request: {
'X-Real-IP': '{clientIp}',
'X-Request-ID': '{uuid}',
'X-Forwarded-Proto': 'https'
},
response: {
'X-Powered-By': 'SmartProxy',
'Strict-Transport-Security': 'max-age=31536000',
'X-Frame-Options': 'DENY'
}
targets: [{ host: 'backend', port: 8080 }]
},
headers: {
request: {
'X-Real-IP': '{clientIp}',
'X-Request-ID': '{uuid}',
'X-Forwarded-Proto': 'https'
},
response: {
'Strict-Transport-Security': 'max-age=31536000',
'X-Frame-Options': 'DENY'
}
}
}
```
### 🔀 PROXY Protocol Support
Preserve original client information through proxy chains:
```typescript
const proxy = new SmartProxy({
// Accept PROXY protocol from trusted load balancers
acceptProxyProtocol: true,
proxyIPs: ['10.0.0.1', '10.0.0.2'],
// Forward PROXY protocol to backends
sendProxyProtocol: true,
routes: [...]
});
```
### 🏗️ Custom Certificate Provisioning
Supply your own certificates or integrate with external certificate providers:
```typescript
const proxy = new SmartProxy({
certProvisionFunction: async (domain: string) => {
// Return 'http01' to let the built-in ACME handle it
if (domain.endsWith('.example.com')) return 'http01';
// Or return a static certificate object
return {
publicKey: myPemCert,
privateKey: myPemKey,
};
},
certProvisionFallbackToAcme: true, // Fall back to ACME if callback fails
routes: [...]
});
```
## 🏛️ Architecture
SmartProxy is built with a modular, extensible architecture:
SmartProxy uses a hybrid **Rust + TypeScript** architecture:
```
SmartProxy
├── 📋 RouteManager # Route matching and prioritization
├── 🔌 PortManager # Dynamic port lifecycle management
── 🔒 SmartCertManager # ACME/Let's Encrypt automation
├── 🚦 ConnectionManager # Connection pooling and tracking
├── 📊 MetricsCollector # Real-time performance monitoring
├── 🛡️ SecurityManager # Access control and rate limiting
├── 🔧 ProtocolDetector # Smart HTTP/TLS/WebSocket detection
├── ⚡ NFTablesManager # Kernel-level forwarding (Linux)
└── 🌐 HttpProxyBridge # HTTP/HTTPS request handling
┌─────────────────────────────────────────────────────┐
│ Your Application │
│ (TypeScript — routes, config, socket handlers) │
──────────────────┬──────────────────────────────────┘
│ IPC (JSON over stdin/stdout)
┌──────────────────▼──────────────────────────────────┐
│ Rust Proxy Engine │
│ ┌─────────┐ ┌─────────┐ ┌─────────┐ ┌──────────┐ │
│ │ TCP/TLS │ │ HTTP │ │ Route │ │ ACME │ │
│ │ Listener│ │ Reverse │ │ Matcher │ │ Cert Mgr │ │
│ │ │ │ Proxy │ │ │ │ │ │
│ └─────────┘ └─────────┘ └─────────┘ └──────────┘ │
│ ┌─────────┐ ┌─────────┐ ┌─────────┐ ┌──────────┐ │
│ │ Security│ │ Metrics │ │ Connec- │ │ NFTables │ │
│ │ Enforce │ │ Collect │ │ tion │ │ Mgr │ │
│ │ │ │ │ │ Tracker │ │ │ │
│ └─────────┘ └─────────┘ └─────────┘ └──────────┘ │
└──────────────────┬──────────────────────────────────┘
│ Unix Socket Relay
┌──────────────────▼──────────────────────────────────┐
│ TypeScript Socket Handler Server │
│ (for JS-defined socket handlers & dynamic routes) │
└─────────────────────────────────────────────────────┘
```
- **Rust Engine** handles all networking, TLS, HTTP proxying, connection management, security, and metrics
- **TypeScript** provides the npm API, configuration types, route helpers, validation, and socket handler callbacks
- **IPC** — JSON commands/events over stdin/stdout for seamless cross-language communication
- **Socket Relay** — a Unix domain socket server for routes requiring TypeScript-side handling (socket handlers, dynamic host/port functions)
## 🎯 Route Configuration Reference
### Match Criteria
```typescript
interface IRouteMatch {
ports: number | number[] | string; // 80, [80, 443], '8000-8999'
domains?: string | string[]; // 'example.com', '*.example.com'
path?: string; // '/api/*', '/users/:id'
clientIp?: string | string[]; // '10.0.0.0/8', ['192.168.*']
tlsVersion?: string | string[]; // ['TLSv1.2', 'TLSv1.3']
ports: number | number[] | Array<{ from: number; to: number }>; // Port(s) to listen on
domains?: string | string[]; // 'example.com', '*.example.com'
path?: string; // '/api/*', '/users/:id'
clientIp?: string[]; // ['10.0.0.0/8', '192.168.*']
tlsVersion?: string[]; // ['TLSv1.2', 'TLSv1.3']
headers?: Record<string, string | RegExp>; // Match by HTTP headers
}
```
@@ -390,69 +509,251 @@ interface IRouteMatch {
| Type | Description |
|------|-------------|
| `forward` | Proxy to one or more backend targets |
| `redirect` | HTTP redirect with status code |
| `block` | Block the connection |
| `socket-handler` | Custom socket handling function |
| `forward` | Proxy to one or more backend targets (with optional TLS, WebSocket, load balancing) |
| `socket-handler` | Custom socket handling function in TypeScript |
### Target Options
```typescript
interface IRouteTarget {
host: string | string[] | ((context: IRouteContext) => string);
port: number | 'preserve' | ((context: IRouteContext) => number);
tls?: { ... }; // Per-target TLS override
priority?: number; // Target priority
match?: ITargetMatch; // Sub-match within a route (by port, path, headers, method)
}
```
### TLS Options
```typescript
interface IRouteTls {
mode: 'passthrough' | 'terminate' | 'terminate-and-reencrypt';
certificate: 'auto' | { key: string; cert: string };
// For terminate-and-reencrypt:
reencrypt?: {
host: string;
port: number;
ca?: string; // Custom CA for backend
certificate: 'auto' | {
key: string;
cert: string;
ca?: string;
keyFile?: string;
certFile?: string;
};
acme?: {
email: string;
useProduction?: boolean;
challengePort?: number;
renewBeforeDays?: number;
};
versions?: string[];
ciphers?: string[];
honorCipherOrder?: boolean;
sessionTimeout?: number;
}
```
### WebSocket Options
```typescript
interface IRouteWebSocket {
enabled: boolean;
pingInterval?: number; // ms between pings
pingTimeout?: number; // ms to wait for pong
maxPayloadSize?: number; // Maximum frame payload
subprotocols?: string[]; // Allowed subprotocols
allowedOrigins?: string[]; // CORS origins
}
```
### Load Balancing Options
```typescript
interface IRouteLoadBalancing {
algorithm: 'round-robin' | 'least-connections' | 'ip-hash';
healthCheck?: {
path: string;
interval: number; // ms
timeout: number; // ms
unhealthyThreshold?: number;
healthyThreshold?: number;
};
}
```
## 🛠️ Helper Functions Reference
All helpers are fully typed and documented:
All helpers are fully typed and return `IRouteConfig` or `IRouteConfig[]`:
```typescript
import {
// HTTP/HTTPS
createHttpRoute,
createHttpsTerminateRoute,
createHttpsPassthroughRoute,
createHttpToHttpsRedirect,
createCompleteHttpsServer,
createHttpRoute, // Plain HTTP route
createHttpsTerminateRoute, // HTTPS with TLS termination
createHttpsPassthroughRoute, // SNI passthrough (no termination)
createHttpToHttpsRedirect, // HTTP → HTTPS redirect
createCompleteHttpsServer, // HTTPS + redirect combo (returns IRouteConfig[])
// Load Balancing
createLoadBalancerRoute,
createSmartLoadBalancer,
createLoadBalancerRoute, // Multi-backend with health checks
createSmartLoadBalancer, // Dynamic domain-based backend selection
// API & WebSocket
createApiRoute,
createApiGatewayRoute,
createWebSocketRoute,
createApiRoute, // API route with path matching
createApiGatewayRoute, // API gateway with CORS
createWebSocketRoute, // WebSocket-enabled route
// Custom Protocols
createSocketHandlerRoute,
SocketHandlers,
createSocketHandlerRoute, // Custom socket handler
SocketHandlers, // Pre-built handlers (echo, proxy, block, etc.)
// NFTables (Linux)
createNfTablesRoute,
createNfTablesTerminateRoute,
createCompleteNfTablesHttpsServer,
// NFTables (Linux, requires root)
createNfTablesRoute, // Kernel-level packet forwarding
createNfTablesTerminateRoute, // NFTables + TLS termination
createCompleteNfTablesHttpsServer, // NFTables HTTPS + redirect combo
// Dynamic Routing
createPortMappingRoute,
createOffsetPortMappingRoute,
createDynamicRoute,
createPortMappingRoute, // Port mapping with context
createOffsetPortMappingRoute, // Simple port offset
createDynamicRoute, // Dynamic host/port via functions
// Security Modifiers
addRateLimiting,
addBasicAuth,
addJwtAuth
addRateLimiting, // Add rate limiting to any route
addBasicAuth, // Add basic auth to any route
addJwtAuth, // Add JWT auth to any route
// Route Utilities
mergeRouteConfigs, // Deep-merge two route configs
findMatchingRoutes, // Find routes matching criteria
findBestMatchingRoute, // Find best matching route
cloneRoute, // Deep-clone a route
generateRouteId, // Generate deterministic route ID
RouteValidator, // Validate route configurations
} from '@push.rocks/smartproxy';
```
## 📖 API Documentation
### SmartProxy Class
```typescript
class SmartProxy extends EventEmitter {
constructor(options: ISmartProxyOptions);
// Lifecycle
start(): Promise<void>;
stop(): Promise<void>;
// Route Management (atomic, mutex-locked)
updateRoutes(routes: IRouteConfig[]): Promise<void>;
// Port Management
addListeningPort(port: number): Promise<void>;
removeListeningPort(port: number): Promise<void>;
getListeningPorts(): Promise<number[]>;
// Monitoring & Metrics
getMetrics(): IMetrics; // Sync — returns cached metrics adapter
getStatistics(): Promise<any>; // Async — queries Rust engine
// Certificate Management
provisionCertificate(routeName: string): Promise<void>;
renewCertificate(routeName: string): Promise<void>;
getCertificateStatus(routeName: string): Promise<any>;
getEligibleDomainsForCertificates(): string[];
// NFTables
getNfTablesStatus(): Promise<Record<string, any>>;
// Events
on(event: 'error', handler: (err: Error) => void): this;
}
```
### Configuration Options
```typescript
interface ISmartProxyOptions {
routes: IRouteConfig[]; // Required: array of route configs
// ACME/Let's Encrypt
acme?: {
email: string; // Contact email for Let's Encrypt
useProduction?: boolean; // Use production servers (default: false)
port?: number; // HTTP-01 challenge port (default: 80)
renewThresholdDays?: number; // Days before expiry to renew (default: 30)
autoRenew?: boolean; // Enable auto-renewal (default: true)
certificateStore?: string; // Directory to store certs (default: './certs')
renewCheckIntervalHours?: number; // Renewal check interval (default: 24)
};
// Custom certificate provisioning
certProvisionFunction?: (domain: string) => Promise<ICert | 'http01'>;
certProvisionFallbackToAcme?: boolean; // Fall back to ACME on failure (default: true)
// Global defaults
defaults?: {
target?: { host: string; port: number };
security?: { ipAllowList?: string[]; ipBlockList?: string[]; maxConnections?: number };
};
// PROXY protocol
proxyIPs?: string[]; // Trusted proxy IPs
acceptProxyProtocol?: boolean; // Accept PROXY protocol headers
sendProxyProtocol?: boolean; // Send PROXY protocol to targets
// Timeouts
connectionTimeout?: number; // Backend connection timeout (default: 30s)
initialDataTimeout?: number; // Initial data/SNI timeout (default: 120s)
socketTimeout?: number; // Socket inactivity timeout (default: 1h)
maxConnectionLifetime?: number; // Max connection lifetime (default: 24h)
inactivityTimeout?: number; // Inactivity timeout (default: 4h)
gracefulShutdownTimeout?: number; // Shutdown grace period (default: 30s)
// Connection limits
maxConnectionsPerIP?: number; // Per-IP connection limit (default: 100)
connectionRateLimitPerMinute?: number; // Per-IP rate limit (default: 300/min)
// Keep-alive
keepAliveTreatment?: 'standard' | 'extended' | 'immortal';
keepAliveInactivityMultiplier?: number; // (default: 6)
extendedKeepAliveLifetime?: number; // (default: 7 days)
// Metrics
metrics?: {
enabled?: boolean;
sampleIntervalMs?: number;
retentionSeconds?: number;
};
// Behavior
enableDetailedLogging?: boolean; // Verbose connection logging
enableTlsDebugLogging?: boolean; // TLS handshake debug logging
// Rust binary
rustBinaryPath?: string; // Custom path to the Rust binary
}
```
### NfTablesProxy Class
A standalone class for managing nftables NAT rules directly (Linux only, requires root):
```typescript
import { NfTablesProxy } from '@push.rocks/smartproxy';
const nftProxy = new NfTablesProxy({
fromPorts: [80, 443],
toHost: 'backend-server',
toPorts: [8080, 8443],
protocol: 'tcp',
preserveSourceIP: true,
enableIPv6: true,
maxRate: '1gbps',
useIPSets: true
});
await nftProxy.start(); // Apply nftables rules
const status = nftProxy.getStatus();
await nftProxy.stop(); // Remove rules
```
## 🐛 Troubleshooting
### Certificate Issues
@@ -460,93 +761,41 @@ import {
- ✅ Port 80 must be accessible for ACME HTTP-01 challenges
- ✅ Check DNS propagation with `dig` or `nslookup`
- ✅ Verify the email in ACME configuration is valid
- ✅ Use `getCertificateStatus('route-name')` to check cert state
### Connection Problems
- ✅ Check route priorities (higher number = matched first)
- ✅ Verify security rules aren't blocking legitimate traffic
- ✅ Test with `curl -v` for detailed connection output
- ✅ Enable debug logging for verbose output
- ✅ Enable debug logging with `enableDetailedLogging: true`
### Rust Binary Not Found
SmartProxy searches for the Rust binary in this order:
1. `SMARTPROXY_RUST_BINARY` environment variable
2. Platform-specific npm package (`@push.rocks/smartproxy-linux-x64`, etc.)
3. Local dev build (`./rust/target/release/rustproxy`)
4. System PATH (`rustproxy`)
Set `rustBinaryPath` in options to override.
### Performance Tuning
- ✅ Use NFTables forwarding for high-traffic routes (Linux only)
- ✅ Enable connection keep-alive where appropriate
-Monitor metrics to identify bottlenecks
- ✅ Adjust `maxConnections` based on your server resources
### Debug Mode
```typescript
const proxy = new SmartProxy({
enableDetailedLogging: true, // Verbose connection logging
routes: [...]
});
```
-Use `getMetrics()` and `getStatistics()` to identify bottlenecks
- ✅ Adjust `maxConnectionsPerIP` and `connectionRateLimitPerMinute` based on your workload
- ✅ Use `passthrough` TLS mode when backend can handle TLS directly
## 🏆 Best Practices
1. **📝 Use Helper Functions** - They provide sensible defaults and prevent common mistakes
2. **🎯 Set Route Priorities** - More specific routes should have higher priority values
3. **🔒 Enable Security** - Always use IP filtering and rate limiting for public services
4. **📊 Monitor Metrics** - Use the built-in metrics to identify issues early
5. **🔄 Certificate Monitoring** - Set up alerts for certificate expiration
6. **🛑 Graceful Shutdown** - Always call `proxy.stop()` for clean connection termination
7. **🔧 Test Routes** - Validate your route configurations before deploying to production
## 📖 API Documentation
### SmartProxy Class
```typescript
class SmartProxy {
constructor(options: ISmartProxyOptions);
// Lifecycle
start(): Promise<void>;
stop(): Promise<void>;
// Route Management
updateRoutes(routes: IRouteConfig[]): Promise<void>;
// Port Management
addListeningPort(port: number): Promise<void>;
removeListeningPort(port: number): Promise<void>;
getListeningPorts(): number[];
// Monitoring
getStatus(): IProxyStatus;
getMetrics(): IMetrics;
// Certificate Management
getCertificateInfo(domain: string): ICertStatus | null;
}
```
### Configuration Options
```typescript
interface ISmartProxyOptions {
routes: IRouteConfig[]; // Required: array of route configs
// ACME/Let's Encrypt
acme?: {
email: string; // Contact email
useProduction?: boolean; // Use production servers (default: false)
port?: number; // Challenge port (default: 80)
renewThresholdDays?: number; // Days before expiry to renew (default: 30)
};
// Defaults
defaults?: {
target?: { host: string; port: number };
security?: IRouteSecurity;
tls?: IRouteTls;
};
// Behavior
enableDetailedLogging?: boolean;
gracefulShutdownTimeout?: number; // ms to wait for connections to close
}
```
1. **📝 Use Helper Functions** They provide sensible defaults and prevent common mistakes
2. **🎯 Set Route Priorities** More specific routes should have higher priority values
3. **🔒 Enable Security** Always use IP filtering and rate limiting for public-facing services
4. **📊 Monitor Metrics** Use the built-in metrics to catch issues early
5. **🔄 Certificate Monitoring** Set up alerts before certificates expire
6. **🛑 Graceful Shutdown** Always call `proxy.stop()` for clean connection termination
7. **✅ Validate Routes** — Use `RouteValidator.validateRoutes()` to catch config errors before deployment
8. **🔀 Atomic Updates** — Use `updateRoutes()` for hot-reloading routes (mutex-locked, no downtime)
9. **🎮 Use Socket Handlers** — For protocols beyond HTTP, implement custom socket handlers instead of fighting the proxy model
## License and Legal Information