Philipp Kunz 9646dba601
Some checks failed
Default (tags) / security (push) Successful in 25s
Default (tags) / test (push) Failing after 23s
Default (tags) / release (push) Has been skipped
Default (tags) / metadata (push) Has been skipped
19.2.6
2025-05-19 03:42:47 +00:00
2022-07-29 01:52:34 +02:00
2025-05-18 18:31:40 +00:00
2019-08-20 17:50:17 +02:00
2025-05-19 03:42:47 +00:00
2025-05-18 15:51:09 +00:00
2025-05-18 15:51:09 +00:00

@push.rocks/smartproxy

A unified high-performance proxy toolkit for Node.js, with SmartProxy as the central API to handle all your proxy needs:

  • Unified Route-Based Configuration: Match/action pattern for clean, consistent traffic routing
  • SSL/TLS Support: Automatic HTTPS with Let's Encrypt certificate provisioning
  • Flexible Matching Patterns: Route by port, domain, path, client IP, and TLS version
  • Advanced SNI Handling: Smart TCP/SNI-based forwarding with IP filtering
  • Multiple Action Types: Forward (with TLS modes), redirect, or block traffic
  • Dynamic Port Management: Add or remove listening ports at runtime without restart
  • Security Features: IP allowlists, connection limits, timeouts, and more
  • NFTables Integration: High-performance kernel-level packet forwarding with Linux NFTables

Project Architecture Overview

SmartProxy has been restructured using a modern, modular architecture with a unified route-based configuration system in v14.0.0:

/ts
├── /core                     # Core functionality
│   ├── /models               # Data models and interfaces
│   ├── /utils                # Shared utilities (IP validation, logging, etc.)
│   └── /events               # Common event definitions
├── /certificate              # Certificate management (deprecated in v18+)
│   ├── /acme                 # Moved to SmartCertManager
│   ├── /providers            # Now integrated in route configuration 
│   └── /storage              # Now uses CertStore
├── /forwarding               # Forwarding system
│   ├── /handlers             # Various forwarding handlers
│   │   ├── base-handler.ts   # Abstract base handler
│   │   ├── http-handler.ts   # HTTP-only handler
│   │   └── ...               # Other handlers
│   ├── /config               # Configuration models
│   └── /factory              # Factory for creating handlers
├── /proxies                  # Different proxy implementations
│   ├── /smart-proxy          # SmartProxy implementation
│   │   ├── /models           # SmartProxy-specific interfaces
│   │   │   ├── route-types.ts # Route-based configuration types
│   │   │   └── interfaces.ts  # SmartProxy interfaces
│   │   ├── certificate-manager.ts # SmartCertManager (new in v18+)
│   │   ├── cert-store.ts     # Certificate file storage
│   │   ├── route-helpers.ts  # Helper functions for creating routes
│   │   ├── route-manager.ts  # Route management system
│   │   ├── smart-proxy.ts    # Main SmartProxy class
│   │   └── ...               # Supporting classes
│   ├── /network-proxy        # NetworkProxy implementation
│   └── /nftables-proxy       # NfTablesProxy implementation
├── /tls                      # TLS-specific functionality
│   ├── /sni                  # SNI handling components
│   └── /alerts               # TLS alerts system
└── /http                     # HTTP-specific functionality
    ├── /port80               # Port80Handler (removed in v18+)
    ├── /router               # HTTP routing system
    └── /redirects            # Redirect handlers

Main Components

  • SmartProxy (ts/proxies/smart-proxy/smart-proxy.ts) The central unified API for all proxy needs, featuring:
    • Route-based configuration with match/action pattern
    • Flexible matching criteria (ports, domains, paths, client IPs)
    • Multiple action types (forward, redirect, block)
    • Automatic certificate management
    • Advanced security controls

Helper Functions

  • createRoute, createHttpRoute, createHttpsRoute, createPassthroughRoute Helper functions to create different route configurations with clean syntax
  • createRedirectRoute, createHttpToHttpsRedirect, createBlockRoute Helper functions for common redirect and security configurations
  • createLoadBalancerRoute, createHttpsServer Helper functions for complex configurations
  • createNfTablesRoute, createNfTablesTerminateRoute Helper functions for NFTables-based high-performance kernel-level routing

Specialized Components

  • NetworkProxy (ts/proxies/network-proxy/network-proxy.ts) HTTP/HTTPS reverse proxy with TLS termination and WebSocket support
  • Port80Handler (ts/http/port80/port80-handler.ts) ACME HTTP-01 challenge handler for Let's Encrypt certificates
  • NfTablesProxy (ts/proxies/nftables-proxy/nftables-proxy.ts) Low-level port forwarding using nftables NAT rules
  • Redirect, SslRedirect (ts/http/redirects/redirect-handler.ts) HTTP-to-HTTPS redirects with customizable rules
  • SniHandler (ts/tls/sni/sni-handler.ts) Utilities for SNI extraction from TLS handshakes

Core Utilities

  • ValidationUtils (ts/core/utils/validation-utils.ts) Domain, port, and configuration validation
  • IpUtils (ts/core/utils/ip-utils.ts) IP address validation and filtering with glob patterns

Interfaces and Types

  • IRouteConfig, IRouteMatch, IRouteAction (ts/proxies/smart-proxy/models/route-types.ts)
  • IRoutedSmartProxyOptions (ts/proxies/smart-proxy/models/route-types.ts)
  • INetworkProxyOptions (ts/proxies/network-proxy/models/types.ts)
  • IAcmeOptions, IDomainOptions (ts/certificate/models/certificate-types.ts)
  • INfTableProxySettings (ts/proxies/nftables-proxy/models/interfaces.ts)

Installation

Install via npm:

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.

import {
  SmartProxy,
  createHttpRoute,
  createHttpsTerminateRoute,
  createHttpsPassthroughRoute,
  createHttpToHttpsRedirect,
  createCompleteHttpsServer,
  createLoadBalancerRoute,
  createStaticFileRoute,
  createApiRoute,
  createWebSocketRoute,
  createSecurityConfig,
  createNfTablesRoute,
  createNfTablesTerminateRoute
} from '@push.rocks/smartproxy';

// Create a new SmartProxy instance with route-based configuration
const proxy = new SmartProxy({
  // Global ACME settings for all routes with certificate: 'auto'
  acme: {
    email: 'ssl@example.com',      // 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
  },
  
  // Define all your routing rules in a single array
  routes: [
    // Basic HTTP route - forward traffic from port 80 to internal service
    createHttpRoute('api.example.com', { host: 'localhost', port: 3000 }),

    // HTTPS route with TLS termination and automatic certificates
    createHttpsTerminateRoute('secure.example.com', { host: 'localhost', port: 8080 }, {
      certificate: 'auto'  // Uses global ACME settings
    }),

    // HTTPS passthrough for legacy systems
    createHttpsPassthroughRoute('legacy.example.com', { host: '192.168.1.10', port: 443 }),

    // Redirect HTTP to HTTPS for all domains and subdomains
    createHttpToHttpsRedirect(['example.com', '*.example.com']),

    // Complete HTTPS server (creates both HTTPS route and HTTP redirect)
    ...createCompleteHttpsServer('complete.example.com', { host: 'localhost', port: 3000 }, {
      certificate: 'auto'
    }),

    // API route with CORS headers
    createApiRoute('api.service.com', '/v1', { host: 'api-backend', port: 8081 }, {
      useTls: true,
      certificate: 'auto',
      addCorsHeaders: true
    }),

    // WebSocket route for real-time communication
    createWebSocketRoute('ws.example.com', '/socket', { host: 'socket-server', port: 8082 }, {
      useTls: true,
      certificate: 'auto',
      pingInterval: 30000
    }),

    // Static file server for web assets
    createStaticFileRoute('static.example.com', '/var/www/html', {
      serveOnHttps: true,
      certificate: 'auto',
      indexFiles: ['index.html', 'index.htm', 'default.html']
    }),

    // Load balancer with multiple backend servers
    createLoadBalancerRoute(
      'app.example.com',
      ['192.168.1.10', '192.168.1.11', '192.168.1.12'],
      8080,
      {
        tls: {
          mode: 'terminate',
          certificate: 'auto'
        },
        security: createSecurityConfig({
          allowedIps: ['10.0.0.*', '192.168.1.*'],
          blockedIps: ['1.2.3.4'],
          maxConnections: 1000
        })
      }
    ),

    // High-performance NFTables route (requires root/sudo)
    createNfTablesRoute('fast.example.com', { host: 'backend-server', port: 8080 }, {
      ports: 80,
      protocol: 'tcp',
      preserveSourceIP: true,
      ipAllowList: ['10.0.0.*']
    }),

    // NFTables HTTPS termination for ultra-fast TLS handling
    createNfTablesTerminateRoute('secure-fast.example.com', { host: 'backend-ssl', port: 443 }, {
      ports: 443,
      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
await proxy.start();

// Dynamically add new routes later
await proxy.updateRoutes([
  ...proxy.settings.routes,
  createHttpsTerminateRoute('new-domain.com', { host: 'localhost', port: 9000 }, {
    certificate: 'auto'
  })
]);

// Dynamically add or remove port listeners
await proxy.addListeningPort(8081);
await proxy.removeListeningPort(8081);
console.log('Currently listening on ports:', proxy.getListeningPorts());

// Later, gracefully shut down
await proxy.stop();

Route-Based Configuration System

SmartProxy v14.0.0 introduces a new unified route configuration system based on the IRouteConfig interface. This system follows a match/action pattern that makes routing more powerful, flexible, and declarative.

IRouteConfig Interface

The IRouteConfig interface is the core building block of SmartProxy's configuration system. Each route definition consists of match criteria and an action to perform on matched traffic:

interface IRouteConfig {
  // What traffic to match (required)
  match: IRouteMatch;

  // What to do with matched traffic (required)
  action: IRouteAction;

  // Metadata (all optional)
  name?: string;             // Human-readable name for this route
  description?: string;      // Description of the route's purpose
  priority?: number;         // Controls matching order (higher = matched first)
  tags?: string[];           // Arbitrary tags for categorization
}

Match Criteria (IRouteMatch)

The match property defines criteria for identifying which incoming traffic should be handled by this route:

interface IRouteMatch {
  // Listen on these ports (required)
  ports: TPortRange;  // number | number[] | Array<{ from: number; to: number }>

  // Optional domain patterns to match (default: all domains)
  domains?: string | string[];  // Supports wildcards like '*.example.com'

  // Advanced matching criteria (all optional)
  path?: string;           // Match specific URL paths, supports glob patterns
  clientIp?: string[];     // Match specific client IPs, supports glob patterns
  tlsVersion?: string[];   // Match specific TLS versions e.g. ['TLSv1.2', 'TLSv1.3']
}

Port Specification:

  • Single port: ports: 80
  • Multiple ports: ports: [80, 443]
  • Port ranges: ports: [{ from: 8000, to: 8100 }]
  • Mixed format: ports: [80, 443, { from: 8000, to: 8100 }]

Domain Matching:

  • Single domain: domains: 'example.com'
  • Multiple domains: domains: ['example.com', 'api.example.com']
  • Wildcard domains: domains: '*.example.com' (matches any subdomain)
  • Root domain + subdomains: domains: ['example.com', '*.example.com']

Path Matching:

  • Exact path: path: '/api' (matches only /api exactly)
  • Prefix match: path: '/api/*' (matches /api and any paths under it)
  • Multiple patterns: Use multiple routes with different priorities

Client IP Matching:

  • Exact IP: clientIp: ['192.168.1.1']
  • Subnet wildcards: clientIp: ['10.0.0.*', '192.168.1.*']
  • CIDR notation: clientIp: ['10.0.0.0/24']

TLS Version Matching:

  • tlsVersion: ['TLSv1.2', 'TLSv1.3'] (only match these TLS versions)

Action Configuration (IRouteAction)

The action property defines what to do with traffic that matches the criteria:

interface IRouteAction {
  // Action type (required)
  type: 'forward' | 'redirect' | 'block';

  // For 'forward' actions
  target?: IRouteTarget;

  // TLS handling for 'forward' actions
  tls?: IRouteTls;

  // For 'redirect' actions
  redirect?: IRouteRedirect;

  // Security options for any action
  security?: IRouteSecurity;

  // Advanced options
  advanced?: IRouteAdvanced;

  // Forwarding engine selection
  forwardingEngine?: 'node' | 'nftables';

  // NFTables-specific options
  nftables?: INfTablesOptions;
}

ACME/Let's Encrypt Configuration

SmartProxy supports automatic certificate provisioning and renewal with Let's Encrypt. ACME can be configured globally or per-route.

Global ACME Configuration

Set default ACME settings for all routes with certificate: 'auto':

const proxy = new SmartProxy({
  // Global ACME configuration
  acme: {
    email: 'ssl@example.com',         // Required - Let's Encrypt account email
    useProduction: false,             // Use staging (false) or production (true)
    renewThresholdDays: 30,           // Renew certificates 30 days before expiry
    port: 80,                         // Port for HTTP-01 challenges
    certificateStore: './certs',      // Directory to store certificates
    autoRenew: true,                  // Enable automatic renewal
    renewCheckIntervalHours: 24       // Check for renewals every 24 hours
  },
  
  routes: [
    // This route will use the global ACME settings
    {
      name: 'website',
      match: { ports: 443, domains: 'example.com' },
      action: {
        type: 'forward',
        target: { host: 'localhost', port: 8080 },
        tls: {
          mode: 'terminate',
          certificate: 'auto'  // Uses global ACME configuration
        }
      }
    }
  ]
});

Route-Specific ACME Configuration

Override global settings for specific routes:

{
  name: 'api',
  match: { ports: 443, domains: 'api.example.com' },
  action: {
    type: 'forward',
    target: { host: 'localhost', port: 3000 },
    tls: {
      mode: 'terminate',
      certificate: 'auto',
      acme: {
        email: 'api-ssl@example.com',  // Different email for this route
        useProduction: true,           // Use production while global uses staging
        renewBeforeDays: 60            // Route-specific renewal threshold
      }
    }
  }
}

**Forward Action:**
When `type: 'forward'`, the traffic is forwarded to the specified target:
```typescript
interface IRouteTarget {
  host: string | string[];  // Target host(s) - string array enables round-robin
  port: number;             // Target port
  preservePort?: boolean;   // Use incoming port as target port (default: false)
}

TLS Configuration: When forwarding with TLS, you can configure how TLS is handled:

interface IRouteTls {
  mode: 'passthrough' | 'terminate' | 'terminate-and-reencrypt';
  certificate?: 'auto' | {   // 'auto' = use ACME (Let's Encrypt)
    key: string;            // TLS private key content
    cert: string;           // TLS certificate content
  };
}

TLS Modes:

  • passthrough: Forward raw encrypted TLS traffic without decryption
  • terminate: Terminate TLS and forward as HTTP
  • terminate-and-reencrypt: Terminate TLS and create a new TLS connection to the backend

Forwarding Engine: When forwardingEngine is specified, it determines how packets are forwarded:

  • node: (default) Application-level forwarding using Node.js
  • nftables: Kernel-level forwarding using Linux NFTables (requires root privileges)

NFTables Options: When using forwardingEngine: 'nftables', you can configure:

interface INfTablesOptions {
  protocol?: 'tcp' | 'udp' | 'all';
  preserveSourceIP?: boolean;
  maxRate?: string;              // Rate limiting (e.g., '100mbps')
  priority?: number;             // QoS priority
  tableName?: string;           // Custom NFTables table name
  useIPSets?: boolean;          // Use IP sets for performance
  useAdvancedNAT?: boolean;     // Use connection tracking
}

Redirect Action: When type: 'redirect', the client is redirected:

interface IRouteRedirect {
  to: string;                   // URL or template with variables
  status: 301 | 302 | 307 | 308;  // HTTP status code
}

Block Action: When type: 'block', the connection is immediately closed.

Security Options: For any action type, you can add security controls:

interface IRouteSecurity {
  allowedIps?: string[];     // IP allowlist with glob pattern support
  blockedIps?: string[];     // IP blocklist with glob pattern support
  maxConnections?: number;   // Maximum concurrent connections
  authentication?: {         // Optional authentication (future support)
    type: 'basic' | 'digest' | 'oauth';
    // Auth-specific options
  };
}

Advanced Options: Additional advanced configurations:

interface IRouteAdvanced {
  timeout?: number;                 // Connection timeout in milliseconds
  headers?: Record<string, string>; // Custom HTTP headers
  keepAlive?: boolean;              // Enable connection pooling
  // Additional advanced options
}

Template Variables

String values in redirect URLs and headers can include variables:

  • {domain}: The requested domain name
  • {port}: The incoming port number
  • {path}: The requested URL path
  • {query}: The query string
  • {clientIp}: The client's IP address
  • {sni}: The SNI hostname

Example with template variables:

redirect: {
  to: 'https://{domain}{path}?source=redirect',
  status: 301
}

Route Metadata and Prioritization

You can add metadata to routes to help with organization and control matching priority:

{
  name: 'API Server',                 // Human-readable name
  description: 'Main API endpoints',  // Description
  priority: 100,                      // Matching priority (higher = matched first)
  tags: ['api', 'internal']           // Arbitrary tags
}

Routes with higher priority values are matched first, allowing you to create specialized routes that take precedence over more general ones.

Complete Route Configuration Example

// Example of a complete route configuration
{
  match: {
    ports: 443,
    domains: ['api.example.com', 'api-v2.example.com'],
    path: '/secure/*',
    clientIp: ['10.0.0.*', '192.168.1.*']
  },
  action: {
    type: 'forward',
    target: {
      host: ['10.0.0.1', '10.0.0.2'],  // Round-robin between these hosts
      port: 8080
    },
    tls: {
      mode: 'terminate',
      certificate: 'auto'  // Use Let's Encrypt
    },
    security: {
      allowedIps: ['10.0.0.*'],
      maxConnections: 100
    },
    advanced: {
      timeout: 30000,
      headers: {
        'X-Original-Host': '{domain}',
        'X-Client-IP': '{clientIp}'
      },
      keepAlive: true
    }
  },
  name: 'Secure API Route',
  description: 'Route for secure API endpoints with authentication',
  priority: 100,
  tags: ['api', 'secure', 'internal']
}

// Example with NFTables forwarding engine
{
  match: {
    ports: [80, 443],
    domains: 'high-traffic.example.com'
  },
  action: {
    type: 'forward',
    target: {
      host: 'backend-server',
      port: 8080
    },
    forwardingEngine: 'nftables',  // Use kernel-level forwarding
    nftables: {
      protocol: 'tcp',
      preserveSourceIP: true,
      maxRate: '1gbps',
      useIPSets: true
    },
    security: {
      ipAllowList: ['10.0.0.*'],
      blockedIps: ['malicious.ip.range.*']
    }
  },
  name: 'High Performance NFTables Route',
  description: 'Kernel-level forwarding for maximum performance',
  priority: 150
}

Using Helper Functions

While you can create route configurations manually, SmartProxy provides helper functions to make it easier:

// Instead of building the full object:
const route = {
  match: { ports: 80, domains: 'example.com' },
  action: { type: 'forward', target: { host: 'localhost', port: 8080 } },
  name: 'Web Server'
};

// Use the helper function for cleaner syntax:
const route = createHttpRoute('example.com', { host: 'localhost', port: 8080 }, {
  name: 'Web Server'
});

Available helper functions:

  • createHttpRoute() - Create an HTTP forwarding route
  • createHttpsTerminateRoute() - Create an HTTPS route with TLS termination
  • createHttpsPassthroughRoute() - Create an HTTPS passthrough route
  • createHttpToHttpsRedirect() - Create an HTTP to HTTPS redirect
  • createCompleteHttpsServer() - Create a complete HTTPS server setup with HTTP redirect
  • createLoadBalancerRoute() - Create a route for load balancing across multiple backends
  • createStaticFileRoute() - Create a route for serving static files
  • createApiRoute() - Create an API route with path matching and CORS support
  • createWebSocketRoute() - Create a route for WebSocket connections
  • createNfTablesRoute() - Create a high-performance NFTables route
  • createNfTablesTerminateRoute() - Create an NFTables route with TLS termination
  • createPortRange() - Helper to create port range configurations
  • createSecurityConfig() - Helper to create security configuration objects
  • createBlockRoute() - Create a route to block specific traffic
  • createTestRoute() - Create a test route for debugging and testing

What You Can Do with SmartProxy

  1. Route-Based Traffic Management

    // Route requests for different domains to different backend servers
    createHttpsTerminateRoute('api.example.com', { host: 'api-server', port: 3000 }, {
      certificate: 'auto'
    })
    
  2. Automatic SSL with Let's Encrypt

    // Get and automatically renew certificates
    createHttpsTerminateRoute('secure.example.com', { host: 'localhost', port: 8080 }, {
      certificate: 'auto'
    })
    
  3. Load Balancing

    // Distribute traffic across multiple backend servers
    createLoadBalancerRoute(
      'app.example.com',
      ['10.0.0.1', '10.0.0.2', '10.0.0.3'],
      8080,
      {
        tls: {
          mode: 'terminate',
          certificate: 'auto'
        }
      }
    )
    
  4. Security Controls

    // Restrict access based on IP addresses
    createHttpsTerminateRoute('admin.example.com', { host: 'localhost', port: 8080 }, {
      certificate: 'auto',
      security: {
        allowedIps: ['10.0.0.*', '192.168.1.*'],
        maxConnections: 100
      }
    })
    
  5. Wildcard Domains

    // Handle all subdomains with one config
    createHttpsPassthroughRoute(['example.com', '*.example.com'], { host: 'backend-server', port: 443 })
    
  6. Path-Based Routing

    // Route based on URL path
    createApiRoute('example.com', '/api', { host: 'api-server', port: 3000 }, {
      useTls: true,
      certificate: 'auto'
    })
    
  7. Block Malicious Traffic

    // Block traffic from specific IPs
    createBlockRoute([80, 443], {
      clientIp: ['1.2.3.*', '5.6.7.*'],
      priority: 1000  // High priority to ensure blocking
    })
    
  8. Dynamic Port Management

    // Start the proxy with initial configuration
    const proxy = new SmartProxy({
      routes: [
        createHttpRoute('example.com', { host: 'localhost', port: 8080 })
      ]
    });
    await proxy.start();
    
    // Dynamically add a new port listener
    await proxy.addListeningPort(8081);
    
    // Add a route for the new port
    const currentRoutes = proxy.settings.routes;
    const newRoute = createHttpRoute('api.example.com', { host: 'api-server', port: 3000 });
    newRoute.match.ports = 8081;  // Override the default port
    
    // Update routes - will automatically sync port listeners
    await proxy.updateRoutes([...currentRoutes, newRoute]);
    
    // Later, remove a port listener when needed
    await proxy.removeListeningPort(8081);
    
  9. High-Performance NFTables Routing

    // Use kernel-level packet forwarding for maximum performance
    createNfTablesRoute('high-traffic.example.com', { host: 'backend', port: 8080 }, {
      ports: 80,
      preserveSourceIP: true,
      maxRate: '1gbps'
    })
    

Other Components

While SmartProxy provides a unified API for most needs, you can also use individual components:

NetworkProxy

For HTTP/HTTPS reverse proxy with TLS termination and WebSocket support. Now with native route-based configuration support:

import { NetworkProxy } from '@push.rocks/smartproxy';
import * as fs from 'fs';

const proxy = new NetworkProxy({ port: 443 });
await proxy.start();

// Modern route-based configuration (recommended)
await proxy.updateRouteConfigs([
  {
    match: {
      ports: 443,
      domains: 'example.com'
    },
    action: {
      type: 'forward',
      target: {
        host: '127.0.0.1',
        port: 3000
      },
      tls: {
        mode: 'terminate',
        certificate: {
          cert: fs.readFileSync('cert.pem', 'utf8'),
          key: fs.readFileSync('key.pem', 'utf8')
        }
      },
      advanced: {
        headers: {
          'X-Forwarded-By': 'NetworkProxy'
        },
        urlRewrite: {
          pattern: '^/old/(.*)$',
          target: '/new/$1',
          flags: 'g'
        }
      },
      websocket: {
        enabled: true,
        pingInterval: 30000
      }
    }
  }
]);

// Legacy configuration (for backward compatibility)
await proxy.updateProxyConfigs([
  {
    hostName: 'legacy.example.com',
    destinationIps: ['127.0.0.1'],
    destinationPorts: [3000],
    publicKey: fs.readFileSync('cert.pem', 'utf8'),
    privateKey: fs.readFileSync('key.pem', 'utf8'),
  }
]);

Port80Handler

For standalone ACME certificate management:

import { Port80Handler } from '@push.rocks/smartproxy';

const acme = new Port80Handler({
  port: 80,
  contactEmail: 'admin@example.com',
  useProduction: true
});
acme.on('certificate-issued', evt => console.log(`Certificate ready: ${evt.domain}`));
await acme.start();

NfTablesProxy

For low-level port forwarding using nftables:

import { NfTablesProxy } from '@push.rocks/smartproxy';

const nft = new NfTablesProxy({
  fromPort: 80,
  toPort: 8080,
  toHost: 'localhost',
  preserveSourceIP: true
});
await nft.start();

Redirect / SslRedirect

For HTTP-to-HTTPS redirects:

import { SslRedirect } from '@push.rocks/smartproxy';

// Quick HTTP→HTTPS helper on port 80
const redirect = new SslRedirect(80);
await redirect.start();

NFTables Integration

SmartProxy v18.0.0 includes full integration with Linux NFTables for high-performance kernel-level packet forwarding. NFTables operates directly in the Linux kernel, providing much better performance than user-space proxying for high-traffic scenarios.

When to Use NFTables

NFTables routing is ideal for:

  • High-traffic TCP/UDP forwarding where performance is critical
  • Port forwarding scenarios where you need minimal latency
  • Load balancing across multiple backend servers
  • Security filtering with IP allowlists/blocklists at kernel level

Requirements

NFTables support requires:

  • Linux operating system with NFTables installed
  • Root or sudo permissions to configure NFTables rules
  • NFTables kernel modules loaded

NFTables Route Configuration

Use the NFTables helper functions to create high-performance routes:

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

const proxy = new SmartProxy({
  routes: [
    // Basic TCP forwarding with NFTables
    createNfTablesRoute('tcp-forward', {
      host: 'backend-server',
      port: 8080
    }, {
      ports: 80,
      protocol: 'tcp'
    }),

    // NFTables with IP filtering
    createNfTablesRoute('secure-tcp', {
      host: 'secure-backend',
      port: 8443
    }, {
      ports: 443,
      ipAllowList: ['10.0.0.*', '192.168.1.*'],
      preserveSourceIP: true
    }),

    // NFTables with QoS (rate limiting)
    createNfTablesRoute('limited-service', {
      host: 'api-server',
      port: 3000
    }, {
      ports: 8080,
      maxRate: '50mbps',
      priority: 1
    }),

    // NFTables TLS termination
    createNfTablesTerminateRoute('https-nftables', {
      host: 'backend',
      port: 8080
    }, {
      ports: 443,
      certificate: 'auto',
      useAdvancedNAT: true
    })
  ]
});

await proxy.start();

NFTables Route Options

The NFTables integration supports these options:

  • protocol: 'tcp' | 'udp' | 'all' - Protocol to forward
  • preserveSourceIP: boolean - Preserve client IP for backend
  • ipAllowList: string[] - Allow only these IPs (glob patterns)
  • ipBlockList: string[] - Block these IPs (glob patterns)
  • maxRate: string - Rate limit (e.g., '100mbps', '1gbps')
  • priority: number - QoS priority level
  • tableName: string - Custom NFTables table name
  • useIPSets: boolean - Use IP sets for better performance
  • useAdvancedNAT: boolean - Enable connection tracking

NFTables Status Monitoring

You can monitor the status of NFTables rules:

// Get status of all NFTables rules
const nftStatus = await proxy.getNfTablesStatus();

// Status includes:
// - active: boolean
// - ruleCount: { total, added, removed }
// - packetStats: { forwarded, dropped }
// - lastUpdate: Date

Performance Considerations

NFTables provides significantly better performance than application-level proxying:

  • Operates at kernel level with minimal overhead
  • Can handle millions of packets per second
  • Direct packet forwarding without copying to userspace
  • Hardware offload support on compatible network cards

Limitations

NFTables routing has some limitations:

  • Cannot modify HTTP headers or content
  • Limited to basic NAT and forwarding operations
  • Requires root permissions
  • Linux-only (not available on Windows/macOS)
  • No WebSocket message inspection

For scenarios requiring application-level features (header manipulation, WebSocket handling, etc.), use the standard SmartProxy routes without NFTables.

Migration to v18.0.0

Version 18.0.0 continues the evolution with NFTables integration while maintaining the unified route-based configuration system:

Key Changes

  1. NFTables Integration: High-performance kernel-level packet forwarding for Linux systems
  2. Pure Route-Based API: The configuration now exclusively uses the match/action pattern with no legacy interfaces
  3. Improved Helper Functions: Enhanced helper functions with cleaner parameter signatures
  4. Removed Legacy Support: Legacy domain-based APIs have been completely removed
  5. More Route Pattern Helpers: Additional helper functions for common routing patterns including NFTables routes

Migration Example

Legacy Configuration (pre-v14):

import { SmartProxy, createDomainConfig, httpOnly, tlsTerminateToHttp } from '@push.rocks/smartproxy';

const proxy = new SmartProxy({
  fromPort: 443,
  domainConfigs: [
    createDomainConfig('example.com', tlsTerminateToHttp({
      target: { host: 'localhost', port: 8080 },
      acme: { enabled: true, production: true }
    }))
  ],
  sniEnabled: true
});

Current Configuration (v18.0.0):

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

const proxy = new SmartProxy({
  routes: [
    createHttpsTerminateRoute('example.com', { host: 'localhost', port: 8080 }, {
      certificate: 'auto'
    })
  ],
  acme: {
    enabled: true,
    useProduction: true
  }
});

Migration from v14.x/v15.x to v16.0.0

If you're already using route-based configuration, update your helper function calls:

// Old v14.x/v15.x style:
createHttpsRoute({
  domains: 'example.com',
  target: { host: 'localhost', port: 8080 },
  certificate: 'auto'
})

// New v16.0.0 style:
createHttpsTerminateRoute('example.com', { host: 'localhost', port: 8080 }, {
  certificate: 'auto'
})

Complete Migration Steps

  1. Replace any remaining domainConfigs with route-based configuration using the routes array
  2. Update helper function calls to use the newer parameter format (domain first, target second, options third)
  3. Use the new specific helper functions (e.g., createHttpsTerminateRoute instead of createHttpsRoute)
  4. Update any code that uses updateDomainConfigs() to use addRoutes() or updateRoutes()
  5. For port-only configurations, create route configurations with port matching only

Architecture & Flow Diagrams

flowchart TB
    Client([Client])
    
    subgraph "SmartProxy Components"
        direction TB
        RouteConfig["Route Configuration<br>(Match/Action)"]
        RouteManager["Route Manager"]
        HTTPS443["HTTPS Port 443<br>NetworkProxy"]
        SmartProxy["SmartProxy<br>(TCP/SNI Proxy)"]
        ACME["Port80Handler<br>(ACME HTTP-01)"]
        Certs[(SSL Certificates)]
    end
    
    subgraph "Backend Services"
        Service1[Service 1]
        Service2[Service 2]
        Service3[Service 3]
    end
    
    Client -->|HTTP/HTTPS Request| SmartProxy
    
    SmartProxy -->|Route Matching| RouteManager
    RouteManager -->|Use| RouteConfig
    RouteManager -->|Execute Action| SmartProxy
    
    SmartProxy -->|Forward| Service1
    SmartProxy -->|Redirect| Client
    SmartProxy -->|Forward| Service2
    SmartProxy -->|Forward| Service3
    
    ACME -.->|Generate/Manage| Certs
    Certs -.->|Provide TLS Certs| SmartProxy
    
    classDef component fill:#f9f,stroke:#333,stroke-width:2px;
    classDef backend fill:#bbf,stroke:#333,stroke-width:1px;
    classDef client fill:#dfd,stroke:#333,stroke-width:2px;
    
    class Client client;
    class RouteConfig,RouteManager,HTTPS443,SmartProxy,ACME component;
    class Service1,Service2,Service3 backend;

Route-Based Connection Handling

This diagram illustrates how requests are matched and processed using the route-based configuration:

sequenceDiagram
    participant Client
    participant SmartProxy
    participant RouteManager
    participant Backend
    
    Client->>SmartProxy: Connection (TCP/HTTP/HTTPS)
    
    SmartProxy->>RouteManager: Match connection against routes
    
    RouteManager->>RouteManager: Check port match
    RouteManager->>RouteManager: Check domain match (if SNI)
    RouteManager->>RouteManager: Check path match (if HTTP)
    RouteManager->>RouteManager: Check client IP match
    RouteManager->>RouteManager: Check TLS version match
    
    RouteManager->>RouteManager: Determine highest priority matching route
    
    alt Forward Action
        RouteManager->>SmartProxy: Use forward action
        
        alt TLS Termination
            SmartProxy->>SmartProxy: Terminate TLS
            SmartProxy->>Backend: Forward as HTTP/HTTPS
        else TLS Passthrough
            SmartProxy->>Backend: Forward raw TCP
        end
        
    else Redirect Action
        RouteManager->>SmartProxy: Use redirect action
        SmartProxy->>Client: Send redirect response
        
    else Block Action
        RouteManager->>SmartProxy: Use block action
        SmartProxy->>Client: Close connection
    end
    
    loop Connection Active
        SmartProxy-->>SmartProxy: Monitor Activity
        SmartProxy-->>SmartProxy: Check Security Rules
        alt Security Violation or Timeout
            SmartProxy->>Client: Close Connection
            SmartProxy->>Backend: Close Connection
        end
    end

Features

  • Route-Based Traffic Management • Match/action pattern for flexible routing • Port, domain, path, client IP, and TLS version matching • Multiple action types (forward, redirect, block)

  • TLS Handling Options • TLS passthrough for end-to-end encryption • TLS termination for content inspection • TLS termination with re-encryption for gateway scenarios

  • Automatic ACME Certificates • HTTP-01 challenge handling • Certificate issuance/renewal • Pluggable storage

  • Security Controls • IP allow/block lists with glob pattern support • Connection limits and rate limiting • Timeout controls and connection monitoring

  • Load Balancing • Round-robin distribution across multiple backends • Health checks and failure handling

  • Advanced Features • Custom header manipulation • Template variables for dynamic values • Priority-based route matching

Certificate Hooks & Events

Listen for certificate events via EventEmitter:

  • Port80Handler:
    • certificate-issued, certificate-renewed, certificate-failed
    • manager-started, manager-stopped, request-forwarded
  • SmartProxy:
    • certificate (domain, publicKey, privateKey, expiryDate, source, isRenewal)

Provide a certProvisionFunction(domain) in SmartProxy settings to supply static certs or return 'http01'.

SmartProxy: Common Use Cases

The SmartProxy component with route-based configuration offers a clean, unified approach to handle virtually any proxy scenario.

1. API Gateway / Backend Routing

Create a flexible API gateway to route traffic to different microservices based on domain and path:

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

const apiGateway = new SmartProxy({
  routes: [
    // Users API
    createApiRoute('api.example.com', '/users', { host: 'users-service', port: 3000 }, {
      useTls: true,
      certificate: 'auto',
      addCorsHeaders: true
    }),

    // Products API
    createApiRoute('api.example.com', '/products', { host: 'products-service', port: 3001 }, {
      useTls: true,
      certificate: 'auto',
      addCorsHeaders: true
    }),

    // Admin dashboard with extra security
    createHttpsTerminateRoute('admin.example.com', { host: 'admin-dashboard', port: 8080 }, {
      certificate: 'auto',
      security: {
        allowedIps: ['10.0.0.*', '192.168.1.*'] // Only allow internal network
      }
    })
  ]
});

await apiGateway.start();

2. Complete HTTPS Server with HTTP Redirect

Easily set up a secure HTTPS server with automatic redirection from HTTP:

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

const webServer = new SmartProxy({
  routes: [
    // createHttpsServer creates both the HTTPS route and HTTP redirect
    ...createHttpsServer({
      domains: 'example.com',
      target: { host: 'localhost', port: 8080 },
      certificate: 'auto',
      addHttpRedirect: true
    })
  ]
});

await webServer.start();

3. Multi-Tenant Application with Wildcard Domains

Support dynamically created tenants with wildcard domain matching:

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

const multiTenantApp = new SmartProxy({
  routes: [
    // Handle all tenant subdomains with one route
    createHttpsRoute({
      ports: 443,
      domains: '*.example.com',
      target: { host: 'tenant-router', port: 8080 },
      certificate: 'auto',
      // Pass original hostname to backend for tenant identification
      advanced: {
        headers: {
          'X-Original-Host': '{sni}'
        }
      }
    }),
    
    // Redirect HTTP to HTTPS for all subdomains
    createHttpToHttpsRedirect({
      domains: ['*.example.com']
    })
  ]
});

await multiTenantApp.start();

4. Complex Multi-Service Infrastructure

Create a comprehensive proxy solution with multiple services and security controls:

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

const enterpriseProxy = new SmartProxy({
  routes: [
    // Web application with automatic HTTPS
    createHttpsRoute({
      ports: 443,
      domains: 'app.example.com',
      target: { host: 'web-app', port: 8080 },
      certificate: 'auto'
    }),

    // Legacy system that needs HTTPS passthrough
    createPassthroughRoute({
      ports: 443,
      domains: 'legacy.example.com',
      target: { host: 'legacy-server', port: 443 }
    }),

    // Internal APIs with IP restrictions
    createHttpsRoute({
      ports: 443,
      domains: 'api.internal.example.com',
      target: { host: 'api-gateway', port: 3000 },
      certificate: 'auto',
      security: {
        allowedIps: ['10.0.0.0/16', '192.168.0.0/16'],
        maxConnections: 500
      }
    }),

    // Block known malicious IPs
    createBlockRoute({
      ports: [80, 443],
      clientIp: ['1.2.3.*', '5.6.7.*'],
      priority: 1000
    }),

    // Redirect all HTTP to HTTPS
    createHttpToHttpsRedirect({
      domains: ['*.example.com', 'example.com']
    })
  ],

  // Global settings that apply to all routes
  defaults: {
    security: {
      maxConnections: 1000
    }
  },

  // Enable connection timeouts for security
  inactivityTimeout: 30000,
  
  // Using global certificate management
  acme: {
    enabled: true,
    contactEmail: 'admin@example.com',
    useProduction: true,
    renewThresholdDays: 30
  }
});

await enterpriseProxy.start();

Route-Based Configuration Details

Match Criteria Options

  • ports: number | number[] | Array<{ from: number; to: number }> (required) Listen on specific ports or port ranges

  • domains: string | string[] (optional) Match specific domain names, supports wildcards (e.g., *.example.com)

  • path: string (optional) Match specific URL paths, supports glob patterns

  • clientIp: string[] (optional) Match client IP addresses, supports glob patterns

  • tlsVersion: string[] (optional) Match specific TLS versions (e.g., TLSv1.2, TLSv1.3)

Action Types

  1. Forward:

    {
      type: 'forward',
      target: { host: 'localhost', port: 8080 },
      tls: { mode: 'terminate', certificate: 'auto' }
    }
    
  2. Redirect:

    {
      type: 'redirect',
      redirect: { to: 'https://{domain}{path}', status: 301 }
    }
    
  3. Block:

    {
      type: 'block'
    }
    

TLS Modes

  • passthrough: Forward raw TLS traffic without decryption
  • terminate: Terminate TLS and forward as HTTP
  • terminate-and-reencrypt: Terminate TLS and create a new TLS connection to the backend

Template Variables

Template variables can be used in string values:

  • {domain}: The requested domain name
  • {port}: The incoming port number
  • {path}: The requested URL path
  • {query}: The query string
  • {clientIp}: The client's IP address
  • {sni}: The SNI hostname

Example:

createRedirectRoute({
  domains: 'old.example.com',
  redirectTo: 'https://new.example.com{path}?source=redirect'
})

Configuration Options

SmartProxy (IRoutedSmartProxyOptions)

  • routes (IRouteConfig[], required) - Array of route configurations
  • defaults (object) - Default settings for all routes
  • acme (IAcmeOptions) - ACME certificate options
  • Connection timeouts: initialDataTimeout, socketTimeout, inactivityTimeout, etc.
  • Socket opts: noDelay, keepAlive, enableKeepAliveProbes
  • certProvisionFunction (callback) - Custom certificate provisioning

SmartProxy Dynamic Port Management Methods

  • async addListeningPort(port: number) - Add a new port listener without changing routes
  • async removeListeningPort(port: number) - Remove a port listener without changing routes
  • getListeningPorts() - Get all ports currently being listened on
  • async updateRoutes(routes: IRouteConfig[]) - Update routes and automatically adjust port listeners

NetworkProxy (INetworkProxyOptions)

  • port (number, required) - Main port to listen on
  • backendProtocol ('http1'|'http2', default 'http1') - Protocol to use with backend servers
  • maxConnections (number, default 10000) - Maximum concurrent connections
  • keepAliveTimeout (ms, default 120000) - Connection keep-alive timeout
  • headersTimeout (ms, default 60000) - Timeout for receiving complete headers
  • cors (object) - Cross-Origin Resource Sharing configuration
  • connectionPoolSize (number, default 50) - Size of the connection pool for backend servers
  • logLevel ('error'|'warn'|'info'|'debug') - Logging verbosity level
  • acme (IAcmeOptions) - ACME certificate configuration
  • useExternalPort80Handler (boolean) - Use external port 80 handler for ACME challenges
  • portProxyIntegration (boolean) - Integration with other proxies

NetworkProxy Enhanced Features

NetworkProxy now supports full route-based configuration including:

  • Advanced request and response header manipulation
  • URL rewriting with RegExp pattern matching
  • Template variable resolution for dynamic values (e.g. {domain}, {clientIp})
  • Function-based dynamic target resolution
  • Security features (IP filtering, rate limiting, authentication)
  • WebSocket configuration with path rewriting, custom headers, ping control, and size limits
  • Context-aware CORS configuration

Port80Handler (IAcmeOptions)

  • enabled (boolean, default true)
  • port (number, default 80)
  • contactEmail (string)
  • useProduction (boolean, default false)
  • renewThresholdDays (number, default 30)
  • autoRenew (boolean, default true)
  • certificateStore (string)
  • skipConfiguredCerts (boolean)
  • domainForwards (IDomainForwardConfig[])

NfTablesProxy (INfTableProxySettings)

  • fromPort / toPort (number|range|array)
  • toHost (string, default 'localhost')
  • preserveSourceIP, deleteOnExit, protocol, enableLogging, ipv6Support (booleans)
  • allowedSourceIPs, bannedSourceIPs (string[])
  • useIPSets (boolean, default true)
  • qos, netProxyIntegration (objects)

Documentation

Troubleshooting

SmartProxy

  • If routes aren't matching as expected, check their priorities
  • For domain matching issues, verify SNI extraction is working
  • Use higher priority for block routes to ensure they take precedence
  • Enable enableDetailedLogging or enableTlsDebugLogging for debugging

NFTables Integration

  • Ensure NFTables is installed: apt install nftables or yum install nftables
  • Verify root/sudo permissions for NFTables operations
  • Check NFTables service is running: systemctl status nftables
  • For debugging, check the NFTables rules: nft list ruleset
  • Monitor NFTables rule status: await proxy.getNfTablesStatus()

TLS/Certificates

  • For certificate issues, check the ACME settings and domain validation
  • Ensure domains are publicly accessible for Let's Encrypt validation
  • For TLS handshake issues, increase initialDataTimeout and maxPendingDataSize

NetworkProxy

  • Verify ports, certificates and rejectUnauthorized for TLS errors
  • Configure CORS for preflight issues
  • Increase maxConnections or connectionPoolSize under load

Port80Handler

  • Run as root or grant CAP_NET_BIND_SERVICE for port 80
  • Inspect certificate-failed events and switch staging/production

NfTablesProxy

  • Ensure nft is installed and run with sufficient privileges
  • Use forceCleanSlate:true to clear conflicting rules

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

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 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, and any usage must be approved in writing by Task Venture Capital GmbH.

Company Information

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

For any legal inquiries or if you require 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 11 MiB
Languages
TypeScript 100%