2022-07-29 01:52:34 +02:00
2019-08-20 17:50:17 +02:00
2026-01-30 10:44:28 +00:00

@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.

📦 Installation

npm install @push.rocks/smartproxy
# or
pnpm add @push.rocks/smartproxy

Issue Reporting and Security

For reporting bugs, issues, or security vulnerabilities, please visit community.foss.global/. This is the central community hub for all issue reporting. Developers who sign and comply with our contribution agreement and go through identification can also get a code.foss.global/ account to submit Pull Requests directly.

🎯 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.

Key Features

Feature Description
🔀 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
🚄 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
🔌 WebSocket Support First-class WebSocket proxying with ping/pong keep-alive
🎮 Custom Protocols Socket handlers for implementing any protocol
📊 Live Metrics Real-time throughput, connection counts, and performance data
🔧 Dynamic Management Add/remove ports and routes at runtime without restarts

🚀 Quick Start

Get up and running in 30 seconds:

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
  },
  routes: [
    // Complete HTTPS setup in one line! ✨
    ...createCompleteHttpsServer('app.example.com', {
      host: 'localhost',
      port: 3000
    }, {
      certificate: 'auto'  // Magic! 🎩
    })
  ]
});

await proxy.start();
console.log('🚀 Proxy running with automatic HTTPS!');

📚 Core Concepts

🏗️ Route-Based Architecture

SmartProxy uses a powerful match/action pattern that makes routing predictable and maintainable:

{
  name: 'api-route',
  match: {
    ports: 443,
    domains: 'api.example.com',
    path: '/v1/*'
  },
  action: {
    type: 'forward',
    targets: [{ host: 'backend', port: 8080 }],
    tls: { mode: 'terminate', certificate: 'auto' }
  }
}

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

🔄 TLS Modes

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
terminate-and-reencrypt Decrypt, then re-encrypt to backend Zero-trust environments

💡 Common Use Cases

🌐 HTTP to HTTPS Redirect

import { SmartProxy, createHttpToHttpsRedirect } from '@push.rocks/smartproxy';

const proxy = new SmartProxy({
  routes: [
    createHttpToHttpsRedirect(['example.com', '*.example.com'])
  ]
});

⚖️ Load Balancer with Health Checks

import { 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
      }
    }
  }
);

🔌 WebSocket Proxy

import { 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
  }
);

🚦 API Gateway with Rate Limiting

import { createApiGatewayRoute, addRateLimiting } from '@push.rocks/smartproxy';

let route = createApiGatewayRoute(
  'api.example.com',
  '/api',
  { host: 'api-backend', port: 8080 },
  {
    useTls: true,
    certificate: 'auto',
    addCorsHeaders: true
  }
);

// Add rate limiting - 100 requests per minute per IP
route = addRateLimiting(route, {
  maxRequests: 100,
  window: 60,
  keyBy: 'ip'
});

🎮 Custom Protocol Handler

SmartProxy lets you implement any protocol with full socket control:

import { createSocketHandlerRoute, SocketHandlers } from '@push.rocks/smartproxy';

// Use pre-built handlers
const echoRoute = createSocketHandlerRoute(
  'echo.example.com',
  7777,
  SocketHandlers.echo
);

// Or create your own custom protocol
const customRoute = createSocketHandlerRoute(
  'custom.example.com',
  9999,
  async (socket, context) => {
    console.log(`Connection from ${context.clientIp}`);
    socket.write('Welcome to my custom protocol!\n');

    socket.on('data', (data) => {
      const command = data.toString().trim();
      switch (command) {
        case 'PING': socket.write('PONG\n'); break;
        case 'TIME': socket.write(`${new Date().toISOString()}\n`); break;
        case 'QUIT': socket.end('Goodbye!\n'); break;
        default: socket.write(`Unknown: ${command}\n`);
      }
    });
  }
);

Pre-built Socket Handlers:

Handler Description
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.httpServer(handler) Full HTTP request/response handling
SocketHandlers.block(message) Block with optional message

High-Performance NFTables Forwarding

For ultra-low latency on Linux, use kernel-level forwarding (requires root):

import { 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
  }
);

🔧 Advanced Features

🎯 Dynamic Routing

Route traffic based on runtime conditions:

{
  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
    }]
  }
}

🔒 Security Controls

Comprehensive per-route security options:

{
  name: 'secure-api',
  match: { ports: 443, domains: 'api.example.com' },
  action: {
    type: 'forward',
    targets: [{ host: 'api-backend', port: 8080 }]
  },
  security: {
    // IP-based access control
    ipAllowList: ['10.0.0.0/8', '192.168.*'],
    ipBlockList: ['192.168.1.100'],

    // Connection limits
    maxConnections: 1000,
    maxConnectionsPerIp: 10,

    // Rate limiting
    rateLimit: {
      maxRequests: 100,
      windowMs: 60000
    }
  }
}

📊 Runtime Management

Control your proxy without restarts:

// Dynamic port management
await proxy.addListeningPort(8443);
await proxy.removeListeningPort(8080);

// Update routes on the fly
await proxy.updateRoutes([...newRoutes]);

// Monitor status
const status = proxy.getStatus();
console.log(`Active connections: ${status.activeConnections}`);

// Get detailed metrics
const metrics = proxy.getMetrics();
console.log(`Throughput: ${metrics.throughput.bytesPerSecond} bytes/sec`);

// Certificate management
const certInfo = proxy.getCertificateInfo('example.com');
console.log(`Certificate expires: ${certInfo.expiresAt}`);

🔄 Header Manipulation

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'
      }
    }
  }
}

🏛️ Architecture

SmartProxy is built with a modular, extensible 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

🎯 Route Configuration Reference

Match Criteria

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']
}

Action Types

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

TLS Options

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

🛠️ Helper Functions Reference

All helpers are fully typed and documented:

import {
  // HTTP/HTTPS
  createHttpRoute,
  createHttpsTerminateRoute,
  createHttpsPassthroughRoute,
  createHttpToHttpsRedirect,
  createCompleteHttpsServer,

  // Load Balancing
  createLoadBalancerRoute,
  createSmartLoadBalancer,

  // API & WebSocket
  createApiRoute,
  createApiGatewayRoute,
  createWebSocketRoute,

  // Custom Protocols
  createSocketHandlerRoute,
  SocketHandlers,

  // NFTables (Linux)
  createNfTablesRoute,
  createNfTablesTerminateRoute,
  createCompleteNfTablesHttpsServer,

  // Dynamic Routing
  createPortMappingRoute,
  createOffsetPortMappingRoute,
  createDynamicRoute,

  // Security Modifiers
  addRateLimiting,
  addBasicAuth,
  addJwtAuth
} from '@push.rocks/smartproxy';

🐛 Troubleshooting

Certificate Issues

  • Ensure domain DNS points to your server
  • 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

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

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

const proxy = new SmartProxy({
  enableDetailedLogging: true,  // Verbose connection logging
  routes: [...]
});

🏆 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

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

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
}

This repository contains open-source code licensed under the MIT License. A copy of the license can be found in the LICENSE file.

Please note: The MIT License does not grant permission to use the trade names, trademarks, service marks, or product names of the project, except as required for reasonable and customary use in describing the origin of the work and reproducing the content of the NOTICE file.

Trademarks

This project is owned and maintained by Task Venture Capital GmbH. The names and logos associated with Task Venture Capital GmbH and any related products or services are trademarks of Task Venture Capital GmbH or third parties, and are not included within the scope of the MIT license granted herein.

Use of these trademarks must comply with Task Venture Capital GmbH's Trademark Guidelines or the guidelines of the respective third-party owners, and any usage must be approved in writing. Third-party trademarks used herein are the property of their respective owners and used only in a descriptive manner, e.g. for an implementation of an API or similar.

Company Information

Task Venture Capital GmbH Registered at District Court Bremen HRB 35230 HB, Germany

For any legal inquiries or further information, please contact us via email at hello@task.vc.

By using this repository, you acknowledge that you have read this section, agree to comply with its terms, and understand that the licensing of the code does not imply endorsement by Task Venture Capital GmbH of any derivative works.

Description
a proxy for handling high workloads of proxying
Readme 16 MiB
Languages
TypeScript 100%