diff --git a/changelog.md b/changelog.md index 681e11d..f98706a 100644 --- a/changelog.md +++ b/changelog.md @@ -1,5 +1,12 @@ # Changelog +## 2026-03-19 - 25.15.0 - feat(readme) +document UDP, QUIC, and HTTP/3 support in the README + +- Adds README examples for UDP datagram handlers, QUIC/HTTP3 forwarding, and dual-stack TCP/UDP routes +- Expands configuration and API reference sections to cover transport matching, UDP/QUIC options, backend transport selection, and UDP metrics +- Updates architecture and feature descriptions to reflect UDP, QUIC, HTTP/3, and datagram handler capabilities + ## 2026-03-19 - 25.14.1 - fix(deps) update build and runtime dependencies and align route validation test expectations diff --git a/readme.md b/readme.md index e18a6dc..12ccbdf 100644 --- a/readme.md +++ b/readme.md @@ -1,6 +1,6 @@ # @push.rocks/smartproxy ๐Ÿš€ -**A high-performance, Rust-powered proxy toolkit for Node.js** โ€” unified route-based configuration for SSL/TLS termination, HTTP/HTTPS reverse proxying, WebSocket support, load balancing, custom protocol handlers, and kernel-level NFTables forwarding. +**A high-performance, Rust-powered proxy toolkit for Node.js** โ€” unified route-based configuration for SSL/TLS termination, HTTP/HTTPS reverse proxying, WebSocket support, UDP/QUIC/HTTP3, load balancing, custom protocol handlers, and kernel-level NFTables forwarding. ## ๐Ÿ“ฆ Installation @@ -16,9 +16,9 @@ For reporting bugs, issues, or security vulnerabilities, please visit [community ## ๐ŸŽฏ What is SmartProxy? -SmartProxy is a production-ready proxy solution that takes the complexity out of traffic management. Under the hood, all networking โ€” TCP, TLS, HTTP reverse proxy, connection tracking, security enforcement, and NFTables โ€” is handled by a **Rust engine** for maximum performance, while you configure everything through a clean TypeScript API with full type safety. +SmartProxy is a production-ready proxy solution that takes the complexity out of traffic management. Under the hood, all networking โ€” TCP, UDP, TLS, HTTP reverse proxy, QUIC/HTTP3, 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. +Whether you're building microservices, deploying edge infrastructure, proxying UDP-based protocols, or need a battle-tested reverse proxy with automatic Let's Encrypt certificates, SmartProxy has you covered. ### โšก Key Features @@ -29,11 +29,12 @@ Whether you're building microservices, deploying edge infrastructure, or need a | ๐Ÿ”’ **Automatic SSL/TLS** | Zero-config HTTPS with Let's Encrypt ACME integration | | ๐ŸŽฏ **Flexible Matching** | Route by port, domain, path, protocol, client IP, TLS version, headers, or custom logic | | ๐Ÿš„ **High-Performance** | Choose between user-space or kernel-level (NFTables) forwarding | +| ๐Ÿ“ก **UDP & QUIC/HTTP3** | First-class UDP transport, datagram handlers, QUIC tunneling, and HTTP/3 support | | โš–๏ธ **Load Balancing** | Round-robin, least-connections, IP-hash with health checks | | ๐Ÿ›ก๏ธ **Enterprise Security** | IP filtering, rate limiting, basic auth, JWT auth, connection limits | | ๐Ÿ”Œ **WebSocket Support** | First-class WebSocket proxying with ping/pong keep-alive | -| ๐ŸŽฎ **Custom Protocols** | Socket handlers for implementing any protocol in TypeScript | -| ๐Ÿ“Š **Live Metrics** | Real-time throughput, connection counts, and performance data | +| ๐ŸŽฎ **Custom Protocols** | Socket and datagram handlers for implementing any protocol in TypeScript | +| ๐Ÿ“Š **Live Metrics** | Real-time throughput, connection counts, UDP sessions, and performance data | | ๐Ÿ”ง **Dynamic Management** | Add/remove ports and routes at runtime without restarts | | ๐Ÿ”„ **PROXY Protocol** | Full PROXY protocol v1/v2 support for preserving client information | | ๐Ÿ’พ **Consumer Cert Storage** | Bring your own persistence โ€” SmartProxy never writes certs to disk | @@ -89,7 +90,7 @@ SmartProxy uses a powerful **match/action** pattern that makes routing predictab ``` Every route consists of: -- **Match** โ€” What traffic to capture (ports, domains, paths, protocol, IPs, headers) +- **Match** โ€” What traffic to capture (ports, domains, paths, transport, protocol, IPs, headers) - **Action** โ€” What to do with it (`forward` or `socket-handler`) - **Security** (optional) โ€” IP allow/block lists, rate limits, authentication - **Headers** (optional) โ€” Request/response header manipulation with template variables @@ -197,7 +198,7 @@ apiRoute = addRateLimiting(apiRoute, { const proxy = new SmartProxy({ routes: [apiRoute] }); ``` -### ๐ŸŽฎ Custom Protocol Handler +### ๐ŸŽฎ Custom Protocol Handler (TCP) 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: @@ -247,6 +248,98 @@ const proxy = new SmartProxy({ routes: [echoRoute, customRoute] }); | `SocketHandlers.httpBlock(status, message)` | HTTP block response | | `SocketHandlers.block(message)` | Block with optional message | +### ๐Ÿ“ก UDP Datagram Handler + +Handle raw UDP datagrams with custom TypeScript logic โ€” perfect for DNS, game servers, IoT protocols, or any UDP-based service: + +```typescript +import { SmartProxy } from '@push.rocks/smartproxy'; +import type { IRouteConfig, TDatagramHandler, IDatagramInfo } from '@push.rocks/smartproxy'; + +// Custom UDP echo handler +const udpHandler: TDatagramHandler = (datagram, info, reply) => { + console.log(`UDP from ${info.sourceIp}:${info.sourcePort} on port ${info.destPort}`); + reply(datagram); // Echo it back +}; + +const proxy = new SmartProxy({ + routes: [{ + name: 'udp-echo', + match: { + ports: 5353, + transport: 'udp' // ๐Ÿ‘ˆ Listen for UDP datagrams + }, + action: { + type: 'socket-handler', + datagramHandler: udpHandler, // ๐Ÿ‘ˆ Process each datagram + udp: { + sessionTimeout: 60000, // Session idle timeout (ms) + maxSessionsPerIP: 100, + maxDatagramSize: 65535 + } + } + }] +}); + +await proxy.start(); +``` + +### ๐Ÿ“ก QUIC / HTTP3 Forwarding + +Forward QUIC traffic to backends with optional protocol translation (e.g., receive QUIC, forward as TCP/HTTP1): + +```typescript +import { SmartProxy } from '@push.rocks/smartproxy'; +import type { IRouteConfig } from '@push.rocks/smartproxy'; + +const quicRoute: IRouteConfig = { + name: 'quic-to-backend', + match: { + ports: 443, + transport: 'udp', + protocol: 'quic' // ๐Ÿ‘ˆ Match QUIC protocol + }, + action: { + type: 'forward', + targets: [{ + host: 'backend-server', + port: 8443, + backendTransport: 'tcp' // ๐Ÿ‘ˆ Translate QUIC โ†’ TCP for backend + }], + udp: { + quic: { + enableHttp3: true, + maxIdleTimeout: 30000, + maxConcurrentBidiStreams: 100, + altSvcPort: 443, // Advertise in Alt-Svc header + altSvcMaxAge: 86400 + } + } + } +}; + +const proxy = new SmartProxy({ routes: [quicRoute] }); +``` + +### ๐Ÿ” Dual-Stack TCP + UDP Route + +Listen on both TCP and UDP with a single route โ€” handle each transport with its own handler: + +```typescript +const dualStackRoute: IRouteConfig = { + name: 'dual-stack-dns', + match: { + ports: 53, + transport: 'all' // ๐Ÿ‘ˆ Listen on both TCP and UDP + }, + action: { + type: 'socket-handler', + socketHandler: handleTcpDns, // ๐Ÿ‘ˆ TCP connections + datagramHandler: handleUdpDns, // ๐Ÿ‘ˆ UDP datagrams + } +}; +``` + ### โšก High-Performance NFTables Forwarding For ultra-low latency on Linux, use kernel-level forwarding (requires root): @@ -419,6 +512,10 @@ console.log(`Bytes in: ${metrics.totals.bytesIn()}`); console.log(`Requests/sec: ${metrics.requests.perSecond()}`); console.log(`Throughput in: ${metrics.throughput.instant().in} bytes/sec`); +// UDP metrics +console.log(`UDP sessions: ${metrics.udp.activeSessions()}`); +console.log(`Datagrams in: ${metrics.udp.datagramsIn()}`); + // Get detailed statistics from the Rust engine const stats = await proxy.getStatistics(); @@ -545,7 +642,7 @@ SmartProxy uses a hybrid **Rust + TypeScript** architecture: ``` โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ”‚ Your Application โ”‚ -โ”‚ (TypeScript โ€” routes, config, socket handlers) โ”‚ +โ”‚ (TypeScript โ€” routes, config, handlers) โ”‚ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ โ”‚ IPC (JSON over stdin/stdout) โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ–ผโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” @@ -556,22 +653,23 @@ SmartProxy uses a hybrid **Rust + TypeScript** architecture: โ”‚ โ”‚ โ”‚ โ”‚ Proxy โ”‚ โ”‚ โ”‚ โ”‚ โ”‚ โ”‚ โ”‚ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ โ”‚ โ”‚ โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ”‚ -โ”‚ โ”‚ Securityโ”‚ โ”‚ Metrics โ”‚ โ”‚ Connec- โ”‚ โ”‚ NFTables โ”‚ โ”‚ -โ”‚ โ”‚ Enforce โ”‚ โ”‚ Collect โ”‚ โ”‚ tion โ”‚ โ”‚ Mgr โ”‚ โ”‚ -โ”‚ โ”‚ โ”‚ โ”‚ โ”‚ โ”‚ Tracker โ”‚ โ”‚ โ”‚ โ”‚ +โ”‚ โ”‚ UDP โ”‚ โ”‚ Securityโ”‚ โ”‚ Metrics โ”‚ โ”‚ NFTables โ”‚ โ”‚ +โ”‚ โ”‚ QUIC โ”‚ โ”‚ Enforce โ”‚ โ”‚ Collect โ”‚ โ”‚ Mgr โ”‚ โ”‚ +โ”‚ โ”‚ HTTP/3 โ”‚ โ”‚ โ”‚ โ”‚ โ”‚ โ”‚ โ”‚ โ”‚ โ”‚ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ โ”‚ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ โ”‚ Unix Socket Relay โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ–ผโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” -โ”‚ TypeScript Socket Handler Server โ”‚ -โ”‚ (for JS-defined socket handlers & dynamic routes) โ”‚ +โ”‚ TypeScript Socket & Datagram Handler Servers โ”‚ +โ”‚ (for JS socket handlers, datagram handlers, โ”‚ +โ”‚ and 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 +- **Rust Engine** handles all networking: TCP, UDP, TLS, QUIC, HTTP proxying, connection management, security, and metrics +- **TypeScript** provides the npm API, configuration types, route helpers, validation, and handler callbacks - **IPC** โ€” The TypeScript wrapper uses JSON commands/events over stdin/stdout to communicate with the Rust binary -- **Socket Relay** โ€” A Unix domain socket server for routes requiring TypeScript-side handling (socket handlers, dynamic host/port functions) +- **Socket/Datagram Relay** โ€” Unix domain socket servers for routes requiring TypeScript-side handling (socket handlers, datagram handlers, dynamic host/port functions) ## ๐ŸŽฏ Route Configuration Reference @@ -579,22 +677,26 @@ SmartProxy uses a hybrid **Rust + TypeScript** architecture: ```typescript interface IRouteMatch { - ports: number | number[] | Array<{ from: number; to: number }>; // Required โ€” port(s) to listen on - domains?: string | string[]; // 'example.com', '*.example.com' - path?: string; // '/api/*', '/users/:id' - clientIp?: string[]; // ['10.0.0.0/8', '192.168.*'] - tlsVersion?: string[]; // ['TLSv1.2', 'TLSv1.3'] + ports: TPortRange; // Required โ€” port(s) to listen on + transport?: 'tcp' | 'udp' | 'all'; // Transport protocol (default: 'tcp') + domains?: string | string[]; // 'example.com', '*.example.com' + path?: string; // '/api/*', '/users/:id' + clientIp?: string[]; // ['10.0.0.0/8', '192.168.*'] + tlsVersion?: string[]; // ['TLSv1.2', 'TLSv1.3'] headers?: Record; // Match by HTTP headers - protocol?: 'http' | 'tcp'; // Match specific protocol ('http' includes h2 + WebSocket upgrades) + protocol?: 'http' | 'tcp' | 'udp' | 'quic' | 'http3'; // Application-layer protocol } + +// Port range supports single numbers, arrays, and ranges +type TPortRange = number | Array; ``` ### Action Types | Type | Description | |------|-------------| -| `forward` | Proxy to one or more backend targets (with optional TLS, WebSocket, load balancing) | -| `socket-handler` | Custom socket handling function in TypeScript | +| `forward` | Proxy to one or more backend targets (with optional TLS, WebSocket, load balancing, UDP/QUIC) | +| `socket-handler` | Custom socket/datagram handling function in TypeScript | ### Target Options @@ -602,14 +704,15 @@ interface IRouteMatch { interface IRouteTarget { host: string | string[] | ((context: IRouteContext) => string | string[]); port: number | 'preserve' | ((context: IRouteContext) => number); - tls?: IRouteTls; // Per-target TLS override - priority?: number; // Target priority - match?: ITargetMatch; // Sub-match within a route (by port, path, headers, method) + tls?: IRouteTls; // Per-target TLS override + priority?: number; // Target priority + match?: ITargetMatch; // Sub-match within a route (by port, path, headers, method) websocket?: IRouteWebSocket; loadBalancing?: IRouteLoadBalancing; sendProxyProtocol?: boolean; headers?: IRouteHeaders; advanced?: IRouteAdvanced; + backendTransport?: 'tcp' | 'udp'; // Backend transport (e.g., receive QUIC, forward as TCP) } ``` @@ -666,6 +769,27 @@ interface IRouteLoadBalancing { } ``` +### UDP & QUIC Options + +```typescript +interface IRouteUdp { + sessionTimeout?: number; // Idle timeout per UDP session (ms, default: 60000) + maxSessionsPerIP?: number; // Max concurrent sessions per IP (default: 1000) + maxDatagramSize?: number; // Max datagram size in bytes (default: 65535) + quic?: IRouteQuic; +} + +interface IRouteQuic { + maxIdleTimeout?: number; // QUIC idle timeout (ms, default: 30000) + maxConcurrentBidiStreams?: number; // Max bidi streams (default: 100) + maxConcurrentUniStreams?: number; // Max uni streams (default: 100) + enableHttp3?: boolean; // Enable HTTP/3 (default: false) + altSvcPort?: number; // Port for Alt-Svc header + altSvcMaxAge?: number; // Alt-Svc max age in seconds (default: 86400) + initialCongestionWindow?: number; // Initial congestion window (bytes) +} +``` + ## ๐Ÿ› ๏ธ Helper Functions Reference All helpers are fully typed and return `IRouteConfig` or `IRouteConfig[]`: @@ -689,7 +813,7 @@ import { createWebSocketRoute, // WebSocket-enabled route // Custom Protocols - createSocketHandlerRoute, // Custom socket handler + createSocketHandlerRoute, // Custom TCP socket handler SocketHandlers, // Pre-built handlers (echo, proxy, block, etc.) // NFTables (Linux, requires root) @@ -718,6 +842,8 @@ import { } from '@push.rocks/smartproxy'; ``` +> **Tip:** For UDP datagram handler routes or QUIC/HTTP3 routes, construct `IRouteConfig` objects directly โ€” there are no helper functions for these yet. See the [UDP Datagram Handler](#-udp-datagram-handler) and [QUIC / HTTP3 Forwarding](#-quic--http3-forwarding) examples above. + ## ๐Ÿ“– API Documentation ### SmartProxy Class @@ -753,6 +879,8 @@ class SmartProxy extends EventEmitter { // Events on(event: 'error', handler: (err: Error) => void): this; + on(event: 'certificate-issued', handler: (ev: ICertificateIssuedEvent) => void): this; + on(event: 'certificate-failed', handler: (ev: ICertificateFailedEvent) => void): this; } ``` @@ -775,6 +903,8 @@ interface ISmartProxyOptions { // Custom certificate provisioning certProvisionFunction?: (domain: string) => Promise; certProvisionFallbackToAcme?: boolean; // Fall back to ACME on failure (default: true) + certProvisionTimeout?: number; // Timeout per provision call (ms) + certProvisionConcurrency?: number; // Max concurrent provisions // Consumer-managed certificate persistence (see "Consumer-Managed Certificate Storage") certStore?: ISmartProxyCertStore; @@ -782,6 +912,9 @@ interface ISmartProxyOptions { // Self-signed fallback disableDefaultCert?: boolean; // Disable '*' self-signed fallback (default: false) + // Rust binary path override + rustBinaryPath?: string; // Custom path to the Rust proxy binary + // Global defaults defaults?: { target?: { host: string; port: number }; @@ -868,11 +1001,22 @@ metrics.requests.perSecond(); // Requests per second metrics.requests.perMinute(); // Requests per minute metrics.requests.total(); // Total requests +// UDP metrics +metrics.udp.activeSessions(); // Current active UDP sessions +metrics.udp.totalSessions(); // Total UDP sessions since start +metrics.udp.datagramsIn(); // Datagrams received +metrics.udp.datagramsOut(); // Datagrams sent + // Cumulative totals metrics.totals.bytesIn(); // Total bytes received metrics.totals.bytesOut(); // Total bytes sent metrics.totals.connections(); // Total connections +// Backend metrics +metrics.backends.byBackend(); // Map +metrics.backends.protocols(); // Map +metrics.backends.topByErrors(10); // Top N error-prone backends + // Percentiles metrics.percentiles.connectionDuration(); // { p50, p95, p99 } metrics.percentiles.bytesTransferred(); // { in: { p50, p95, p99 }, out: { p50, p95, p99 } } @@ -896,11 +1040,12 @@ metrics.percentiles.bytesTransferred(); // { in: { p50, p95, p99 }, out: { p5 ### Rust Binary Not Found SmartProxy searches for the Rust binary in this order: -1. `SMARTPROXY_RUST_BINARY` environment variable -2. Platform-specific npm package (`@push.rocks/smartproxy-linux-x64`, etc.) -3. `dist_rust/rustproxy` relative to the package root (built by `tsrust`) -4. Local dev build (`./rust/target/release/rustproxy`) -5. System PATH (`rustproxy`) +1. `rustBinaryPath` option in `ISmartProxyOptions` +2. `SMARTPROXY_RUST_BINARY` environment variable +3. Platform-specific npm package (`@push.rocks/smartproxy-linux-x64`, etc.) +4. `dist_rust/rustproxy` relative to the package root (built by `tsrust`) +5. Local dev build (`./rust/target/release/rustproxy`) +6. System PATH (`rustproxy`) ### Performance Tuning - โœ… Use NFTables forwarding for high-traffic routes (Linux only) diff --git a/ts/00_commitinfo_data.ts b/ts/00_commitinfo_data.ts index 508336d..76e38ea 100644 --- a/ts/00_commitinfo_data.ts +++ b/ts/00_commitinfo_data.ts @@ -3,6 +3,6 @@ */ export const commitinfo = { name: '@push.rocks/smartproxy', - version: '25.14.1', + version: '25.15.0', 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.' }