|
|
|
|
@@ -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<string, string | RegExp>; // 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<number | { from: number; to: number }>;
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
### 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<ICert | 'http01'>;
|
|
|
|
|
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<backend, IBackendMetrics>
|
|
|
|
|
metrics.backends.protocols(); // Map<backend, protocol>
|
|
|
|
|
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)
|
|
|
|
|
|