905 lines
30 KiB
Markdown
905 lines
30 KiB
Markdown
# @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 Configuration API**: One consistent way to configure various proxy types
|
|
- **SSL/TLS Support**: Automatic HTTPS with Let's Encrypt certificate provisioning
|
|
- **Simplified Domain Management**: Easy routing based on domain names with wildcard support
|
|
- **Advanced SNI Handling**: Smart TCP/SNI-based forwarding with IP filtering
|
|
- **Multiple Forwarding Types**: HTTP-only, HTTPS passthrough, TLS termination options
|
|
- **Security Features**: IP allowlists, connection limits, timeouts, and more
|
|
|
|
## Project Architecture Overview
|
|
|
|
SmartProxy has been restructured using a modern, modular architecture to improve maintainability and clarity:
|
|
|
|
```
|
|
/ts
|
|
├── /core # Core functionality
|
|
│ ├── /models # Data models and interfaces
|
|
│ ├── /utils # Shared utilities (IP validation, logging, etc.)
|
|
│ └── /events # Common event definitions
|
|
├── /certificate # Certificate management
|
|
│ ├── /acme # ACME-specific functionality
|
|
│ ├── /providers # Certificate providers (static, ACME)
|
|
│ └── /storage # Certificate storage mechanisms
|
|
├── /forwarding # Forwarding system
|
|
│ ├── /handlers # Various forwarding handlers
|
|
│ │ ├── base-handler.ts # Abstract base handler
|
|
│ │ ├── http-handler.ts # HTTP-only handler
|
|
│ │ └── ... # Other handlers
|
|
│ ├── /config # Configuration models
|
|
│ │ ├── forwarding-types.ts # Type definitions
|
|
│ │ ├── domain-config.ts # Domain config utilities
|
|
│ │ └── domain-manager.ts # Domain routing manager
|
|
│ └── /factory # Factory for creating handlers
|
|
├── /proxies # Different proxy implementations
|
|
│ ├── /smart-proxy # SmartProxy implementation
|
|
│ │ ├── /models # SmartProxy-specific interfaces
|
|
│ │ ├── smart-proxy.ts # Main SmartProxy class
|
|
│ │ └── ... # Supporting classes
|
|
│ ├── /network-proxy # NetworkProxy implementation
|
|
│ │ ├── /models # NetworkProxy-specific interfaces
|
|
│ │ ├── network-proxy.ts # Main NetworkProxy class
|
|
│ │ └── ... # Supporting classes
|
|
│ └── /nftables-proxy # NfTablesProxy implementation
|
|
├── /tls # TLS-specific functionality
|
|
│ ├── /sni # SNI handling components
|
|
│ └── /alerts # TLS alerts system
|
|
└── /http # HTTP-specific functionality
|
|
├── /port80 # Port80Handler components
|
|
├── /router # HTTP routing system
|
|
└── /redirects # Redirect handlers
|
|
```
|
|
|
|
## Main Components
|
|
|
|
### Primary API (Recommended)
|
|
|
|
- **SmartProxy** (`ts/proxies/smart-proxy/smart-proxy.ts`)
|
|
The central unified API for all proxy needs, featuring:
|
|
- Domain-based routing with SNI inspection
|
|
- Automatic certificate management
|
|
- Multiple forwarding types in one configuration
|
|
- Advanced security controls
|
|
- Flexible backend targeting options
|
|
|
|
### Helper Functions
|
|
|
|
- **createDomainConfig**
|
|
Create domain configuration with clean syntax
|
|
- **httpOnly**, **httpsPassthrough**, **tlsTerminateToHttp**, **tlsTerminateToHttps**
|
|
Helper functions to create different forwarding configurations
|
|
|
|
### 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
|
|
|
|
- `ISmartProxyOptions`, `IDomainConfig` (`ts/proxies/smart-proxy/models/interfaces.ts`)
|
|
- `IForwardConfig`, `TForwardingType` (`ts/forwarding/config/forwarding-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:
|
|
```bash
|
|
npm install @push.rocks/smartproxy
|
|
```
|
|
|
|
## Quick Start with SmartProxy
|
|
|
|
SmartProxy is the recommended way to use this library, providing a unified API for all proxy scenarios.
|
|
|
|
```typescript
|
|
import { SmartProxy, createDomainConfig, httpOnly, tlsTerminateToHttp, httpsPassthrough } from '@push.rocks/smartproxy';
|
|
|
|
// Create a new SmartProxy instance with all your domain configurations in one place
|
|
const proxy = new SmartProxy({
|
|
// Listen on port 443 for incoming connections
|
|
fromPort: 443,
|
|
|
|
// Configure domains and their forwarding rules
|
|
domainConfigs: [
|
|
// Basic HTTP forwarding for api.example.com
|
|
createDomainConfig('api.example.com', httpOnly({
|
|
target: { host: 'localhost', port: 3000 }
|
|
})),
|
|
|
|
// HTTPS termination with automatic Let's Encrypt certificates
|
|
createDomainConfig('secure.example.com', tlsTerminateToHttp({
|
|
target: { host: 'localhost', port: 8080 },
|
|
acme: {
|
|
enabled: true,
|
|
production: true
|
|
}
|
|
})),
|
|
|
|
// Multiple domains with wildcard support
|
|
createDomainConfig(['example.com', '*.example.com'], httpsPassthrough({
|
|
target: {
|
|
// Load balancing across multiple backend servers
|
|
host: ['192.168.1.10', '192.168.1.11'],
|
|
port: 443
|
|
},
|
|
security: {
|
|
// IP filtering for enhanced security
|
|
allowedIps: ['10.0.0.*', '192.168.1.*'],
|
|
blockedIps: ['1.2.3.4']
|
|
}
|
|
}))
|
|
],
|
|
|
|
// Enable SNI-based routing
|
|
sniEnabled: true,
|
|
|
|
// 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 or update domain configurations later
|
|
await proxy.updateDomainConfigs([
|
|
createDomainConfig('new-domain.com', tlsTerminateToHttp({
|
|
target: { host: 'localhost', port: 9000 }
|
|
}))
|
|
]);
|
|
|
|
// Later, gracefully shut down
|
|
await proxy.stop();
|
|
```
|
|
|
|
### What You Can Do with SmartProxy
|
|
|
|
1. **Domain-Based Routing**
|
|
```typescript
|
|
// Route requests for different domains to different backend servers
|
|
createDomainConfig('api.example.com', httpOnly({
|
|
target: { host: 'api-server', port: 3000 }
|
|
}))
|
|
```
|
|
|
|
2. **Automatic SSL with Let's Encrypt**
|
|
```typescript
|
|
// Get and automatically renew certificates
|
|
createDomainConfig('secure.example.com', tlsTerminateToHttp({
|
|
target: { host: 'localhost', port: 8080 },
|
|
acme: { enabled: true, production: true }
|
|
}))
|
|
```
|
|
|
|
3. **Load Balancing**
|
|
```typescript
|
|
// Distribute traffic across multiple backend servers
|
|
createDomainConfig('app.example.com', httpOnly({
|
|
target: {
|
|
host: ['10.0.0.1', '10.0.0.2', '10.0.0.3'],
|
|
port: 8080
|
|
}
|
|
}))
|
|
```
|
|
|
|
4. **Security Controls**
|
|
```typescript
|
|
// Restrict access based on IP addresses
|
|
createDomainConfig('admin.example.com', httpOnly({
|
|
target: { host: 'localhost', port: 8080 },
|
|
security: {
|
|
allowedIps: ['10.0.0.*', '192.168.1.*'],
|
|
maxConnections: 100
|
|
}
|
|
}))
|
|
```
|
|
|
|
5. **Wildcard Domains**
|
|
```typescript
|
|
// Handle all subdomains with one config
|
|
createDomainConfig(['example.com', '*.example.com'], httpsPassthrough({
|
|
target: { host: 'backend-server', port: 443 }
|
|
}))
|
|
```
|
|
|
|
## 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:
|
|
|
|
```typescript
|
|
import { NetworkProxy } from '@push.rocks/smartproxy';
|
|
import * as fs from 'fs';
|
|
|
|
const proxy = new NetworkProxy({ port: 443 });
|
|
await proxy.start();
|
|
await proxy.updateProxyConfigs([
|
|
{
|
|
hostName: '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:
|
|
|
|
```typescript
|
|
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:
|
|
|
|
```typescript
|
|
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:
|
|
|
|
```typescript
|
|
import { SslRedirect } from '@push.rocks/smartproxy';
|
|
|
|
// Quick HTTP→HTTPS helper on port 80
|
|
const redirect = new SslRedirect(80);
|
|
await redirect.start();
|
|
```
|
|
|
|
## API Reference
|
|
For full configuration options and type definitions, see the TypeScript interfaces:
|
|
- `INetworkProxyOptions` (`ts/proxies/network-proxy/models/types.ts`)
|
|
- `IAcmeOptions`, `IDomainOptions` (`ts/certificate/models/certificate-types.ts`)
|
|
- `IForwardConfig` (`ts/forwarding/config/forwarding-types.ts`)
|
|
- `INfTableProxySettings` (`ts/proxies/nftables-proxy/models/interfaces.ts`)
|
|
- `ISmartProxyOptions`, `IDomainConfig` (`ts/proxies/smart-proxy/models/interfaces.ts`)
|
|
|
|
## Architecture & Flow Diagrams
|
|
|
|
```mermaid
|
|
flowchart TB
|
|
Client([Client])
|
|
|
|
subgraph "SmartProxy Components"
|
|
direction TB
|
|
HTTP80["HTTP Port 80<br>Redirect / SslRedirect"]
|
|
HTTPS443["HTTPS Port 443<br>NetworkProxy"]
|
|
SmartProxy["SmartProxy<br>(TCP/SNI Proxy)"]
|
|
NfTables[NfTablesProxy]
|
|
Router[ProxyRouter]
|
|
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 Request| HTTP80
|
|
HTTP80 -->|Redirect| Client
|
|
Client -->|HTTPS Request| HTTPS443
|
|
Client -->|TLS/TCP| SmartProxy
|
|
|
|
HTTPS443 -->|Route Request| Router
|
|
Router -->|Proxy Request| Service1
|
|
Router -->|Proxy Request| Service2
|
|
|
|
SmartProxy -->|Direct TCP| Service2
|
|
SmartProxy -->|Direct TCP| Service3
|
|
|
|
NfTables -.->|Low-level forwarding| SmartProxy
|
|
|
|
HTTP80 -.->|Challenge Response| ACME
|
|
ACME -.->|Generate/Manage| Certs
|
|
Certs -.->|Provide TLS Certs| HTTPS443
|
|
|
|
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 HTTP80,HTTPS443,SmartProxy,NfTables,Router,ACME component;
|
|
class Service1,Service2,Service3 backend;
|
|
```
|
|
|
|
### HTTPS Reverse Proxy Flow
|
|
This diagram shows how HTTPS requests are handled and proxied to backend services:
|
|
|
|
```mermaid
|
|
sequenceDiagram
|
|
participant Client
|
|
participant NetworkProxy
|
|
participant ProxyRouter
|
|
participant Backend
|
|
|
|
Client->>NetworkProxy: HTTPS Request
|
|
|
|
Note over NetworkProxy: TLS Termination
|
|
|
|
NetworkProxy->>ProxyRouter: Route Request
|
|
ProxyRouter->>ProxyRouter: Match hostname to config
|
|
|
|
alt Authentication Required
|
|
NetworkProxy->>Client: Request Authentication
|
|
Client->>NetworkProxy: Send Credentials
|
|
NetworkProxy->>NetworkProxy: Validate Credentials
|
|
end
|
|
|
|
NetworkProxy->>Backend: Forward Request
|
|
Backend->>NetworkProxy: Response
|
|
|
|
Note over NetworkProxy: Add Default Headers
|
|
|
|
NetworkProxy->>Client: Forward Response
|
|
|
|
alt WebSocket Request
|
|
Client->>NetworkProxy: Upgrade to WebSocket
|
|
NetworkProxy->>Backend: Upgrade to WebSocket
|
|
loop WebSocket Active
|
|
Client->>NetworkProxy: WebSocket Message
|
|
NetworkProxy->>Backend: Forward Message
|
|
Backend->>NetworkProxy: WebSocket Message
|
|
NetworkProxy->>Client: Forward Message
|
|
NetworkProxy-->>NetworkProxy: Heartbeat Check
|
|
end
|
|
end
|
|
```
|
|
|
|
### SNI-based Connection Handling
|
|
This diagram illustrates how TCP connections with SNI (Server Name Indication) are processed and forwarded:
|
|
|
|
```mermaid
|
|
sequenceDiagram
|
|
participant Client
|
|
participant SmartProxy
|
|
participant Backend
|
|
|
|
Client->>SmartProxy: TLS Connection
|
|
|
|
alt SNI Enabled
|
|
SmartProxy->>Client: Accept Connection
|
|
Client->>SmartProxy: TLS ClientHello with SNI
|
|
SmartProxy->>SmartProxy: Extract SNI Hostname
|
|
SmartProxy->>SmartProxy: Match Domain Config
|
|
SmartProxy->>SmartProxy: Validate Client IP
|
|
|
|
alt IP Allowed
|
|
SmartProxy->>Backend: Forward Connection
|
|
Note over SmartProxy,Backend: Bidirectional Data Flow
|
|
else IP Rejected
|
|
SmartProxy->>Client: Close Connection
|
|
end
|
|
else Port-based Routing
|
|
SmartProxy->>SmartProxy: Match Port Range
|
|
SmartProxy->>SmartProxy: Find Domain Config
|
|
SmartProxy->>SmartProxy: Validate Client IP
|
|
|
|
alt IP Allowed
|
|
SmartProxy->>Backend: Forward Connection
|
|
Note over SmartProxy,Backend: Bidirectional Data Flow
|
|
else IP Rejected
|
|
SmartProxy->>Client: Close Connection
|
|
end
|
|
end
|
|
|
|
loop Connection Active
|
|
SmartProxy-->>SmartProxy: Monitor Activity
|
|
SmartProxy-->>SmartProxy: Check Max Lifetime
|
|
alt Inactivity or Max Lifetime Exceeded
|
|
SmartProxy->>Client: Close Connection
|
|
SmartProxy->>Backend: Close Connection
|
|
end
|
|
end
|
|
```
|
|
|
|
### Let's Encrypt Certificate Acquisition
|
|
This diagram shows how certificates are automatically acquired through the ACME protocol:
|
|
|
|
```mermaid
|
|
sequenceDiagram
|
|
participant Client
|
|
participant Port80Handler
|
|
participant ACME as Let's Encrypt ACME
|
|
participant NetworkProxy
|
|
|
|
Client->>Port80Handler: HTTP Request for domain
|
|
|
|
alt Certificate Exists
|
|
Port80Handler->>Client: Redirect to HTTPS
|
|
else No Certificate
|
|
Port80Handler->>Port80Handler: Mark domain as obtaining cert
|
|
Port80Handler->>ACME: Create account & new order
|
|
ACME->>Port80Handler: Challenge information
|
|
|
|
Port80Handler->>Port80Handler: Store challenge token & key authorization
|
|
|
|
ACME->>Port80Handler: HTTP-01 Challenge Request
|
|
Port80Handler->>ACME: Challenge Response
|
|
|
|
ACME->>ACME: Validate domain ownership
|
|
ACME->>Port80Handler: Challenge validated
|
|
|
|
Port80Handler->>Port80Handler: Generate CSR
|
|
Port80Handler->>ACME: Submit CSR
|
|
ACME->>Port80Handler: Issue Certificate
|
|
|
|
Port80Handler->>Port80Handler: Store certificate & private key
|
|
Port80Handler->>Port80Handler: Mark certificate as obtained
|
|
|
|
Note over Port80Handler,NetworkProxy: Certificate available for use
|
|
|
|
Client->>Port80Handler: Another HTTP Request
|
|
Port80Handler->>Client: Redirect to HTTPS
|
|
Client->>NetworkProxy: HTTPS Request
|
|
Note over NetworkProxy: Uses new certificate
|
|
end
|
|
```
|
|
|
|
## Features
|
|
|
|
- HTTP/HTTPS Reverse Proxy (NetworkProxy)
|
|
• TLS termination, virtual-host routing, HTTP/2 & WebSocket support, pooling & metrics
|
|
|
|
- Automatic ACME Certificates (Port80Handler)
|
|
• HTTP-01 challenge handling, certificate issuance/renewal, pluggable storage
|
|
|
|
- Low-Level Port Forwarding (NfTablesProxy)
|
|
• nftables NAT rules for ports/ranges, IPv4/IPv6, IP filtering, QoS & ipset support
|
|
|
|
- Custom Redirects (Redirect / SslRedirect)
|
|
• URL redirects with wildcard host/path, template variables & status codes
|
|
|
|
- TCP/SNI Proxy (SmartProxy)
|
|
• SNI-based routing, IP allow/block lists, port ranges, timeouts & graceful shutdown
|
|
|
|
- SNI Utilities (SniHandler)
|
|
• Robust ClientHello parsing, fragmentation & session resumption support
|
|
|
|
- Core Utilities
|
|
• ValidationUtils and IpUtils for configuration validation and IP management
|
|
|
|
## 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 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:
|
|
|
|
```typescript
|
|
import { SmartProxy, createDomainConfig, httpOnly, tlsTerminateToHttp } from '@push.rocks/smartproxy';
|
|
|
|
const apiGateway = new SmartProxy({
|
|
fromPort: 443,
|
|
domainConfigs: [
|
|
// Users API
|
|
createDomainConfig('users.api.example.com', tlsTerminateToHttp({
|
|
target: { host: 'users-service', port: 3000 },
|
|
acme: { enabled: true, production: true }
|
|
})),
|
|
|
|
// Products API
|
|
createDomainConfig('products.api.example.com', tlsTerminateToHttp({
|
|
target: { host: 'products-service', port: 3001 },
|
|
acme: { enabled: true, production: true }
|
|
})),
|
|
|
|
// Admin dashboard gets extra security
|
|
createDomainConfig('admin.example.com', tlsTerminateToHttp({
|
|
target: { host: 'admin-dashboard', port: 8080 },
|
|
security: {
|
|
allowedIps: ['10.0.0.*', '192.168.1.*'] // Only allow internal network
|
|
}
|
|
}))
|
|
],
|
|
sniEnabled: true
|
|
});
|
|
|
|
await apiGateway.start();
|
|
```
|
|
|
|
### 2. Automatic HTTPS for Development
|
|
|
|
Easily add HTTPS to your local development environment with automatic certificates:
|
|
|
|
```typescript
|
|
import { SmartProxy, createDomainConfig, tlsTerminateToHttp } from '@push.rocks/smartproxy';
|
|
|
|
const devProxy = new SmartProxy({
|
|
fromPort: 443,
|
|
domainConfigs: [
|
|
createDomainConfig('dev.local', tlsTerminateToHttp({
|
|
target: { host: 'localhost', port: 3000 },
|
|
// For development, use self-signed or existing certificates
|
|
https: {
|
|
customCert: {
|
|
key: fs.readFileSync('dev-cert.key', 'utf8'),
|
|
cert: fs.readFileSync('dev-cert.pem', 'utf8')
|
|
}
|
|
},
|
|
// Auto-redirect HTTP to HTTPS
|
|
http: {
|
|
enabled: true,
|
|
redirectToHttps: true
|
|
}
|
|
}))
|
|
]
|
|
});
|
|
|
|
await devProxy.start();
|
|
```
|
|
|
|
### 3. Load Balancing Multiple Servers
|
|
|
|
Distribute traffic across multiple backend servers with round-robin load balancing:
|
|
|
|
```typescript
|
|
import { SmartProxy, createDomainConfig, tlsTerminateToHttp } from '@push.rocks/smartproxy';
|
|
|
|
const loadBalancer = new SmartProxy({
|
|
fromPort: 443,
|
|
domainConfigs: [
|
|
createDomainConfig('app.example.com', tlsTerminateToHttp({
|
|
target: {
|
|
// Round-robin across multiple servers
|
|
host: [
|
|
'10.0.0.10',
|
|
'10.0.0.11',
|
|
'10.0.0.12'
|
|
],
|
|
port: 8080
|
|
},
|
|
acme: { enabled: true, production: true }
|
|
}))
|
|
]
|
|
});
|
|
|
|
await loadBalancer.start();
|
|
```
|
|
|
|
### 4. Wildcard Subdomain Handling
|
|
|
|
Support multiple or dynamically created subdomains with one configuration:
|
|
|
|
```typescript
|
|
import { SmartProxy, createDomainConfig, tlsTerminateToHttp } from '@push.rocks/smartproxy';
|
|
|
|
const multiTenantProxy = new SmartProxy({
|
|
fromPort: 443,
|
|
domainConfigs: [
|
|
// Handle all customer subdomains with one config
|
|
createDomainConfig('*.example.com', tlsTerminateToHttp({
|
|
target: { host: 'tenant-router', port: 8080 },
|
|
acme: { enabled: true, production: true },
|
|
// Pass original hostname to backend for tenant identification
|
|
advanced: {
|
|
headers: {
|
|
'X-Original-Host': '{sni}'
|
|
}
|
|
}
|
|
}))
|
|
],
|
|
sniEnabled: true
|
|
});
|
|
|
|
await multiTenantProxy.start();
|
|
```
|
|
|
|
### 5. Comprehensive Proxy Server
|
|
|
|
Create a complete proxy solution with multiple services on a single server:
|
|
|
|
```typescript
|
|
import { SmartProxy, createDomainConfig, httpOnly, tlsTerminateToHttp, tlsTerminateToHttps, httpsPassthrough } from '@push.rocks/smartproxy';
|
|
|
|
const enterpriseProxy = new SmartProxy({
|
|
fromPort: 443,
|
|
domainConfigs: [
|
|
// Web application with automatic HTTPS
|
|
createDomainConfig('app.example.com', tlsTerminateToHttp({
|
|
target: { host: 'web-app', port: 8080 },
|
|
acme: { enabled: true, production: true },
|
|
http: { enabled: true, redirectToHttps: true }
|
|
})),
|
|
|
|
// Legacy system that needs HTTPS passthrough
|
|
createDomainConfig('legacy.example.com', httpsPassthrough({
|
|
target: { host: 'legacy-server', port: 443 }
|
|
})),
|
|
|
|
// Internal APIs with IP restrictions
|
|
createDomainConfig('api.internal.example.com', tlsTerminateToHttp({
|
|
target: { host: 'api-gateway', port: 3000 },
|
|
security: {
|
|
allowedIps: ['10.0.0.0/16', '192.168.0.0/16'],
|
|
maxConnections: 500
|
|
}
|
|
})),
|
|
|
|
// External services with customer certificate
|
|
createDomainConfig('external.example.com', tlsTerminateToHttps({
|
|
target: { host: 'external-service', port: 8443 },
|
|
https: {
|
|
customCert: {
|
|
key: fs.readFileSync('external-key.pem', 'utf8'),
|
|
cert: fs.readFileSync('external-cert.pem', 'utf8')
|
|
}
|
|
}
|
|
}))
|
|
],
|
|
sniEnabled: true,
|
|
// 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();
|
|
```
|
|
|
|
## Unified Forwarding System Details
|
|
|
|
SmartProxy's unified forwarding system supports four primary forwarding types:
|
|
|
|
1. **HTTP-only (`http-only`)**: Forwards HTTP traffic to a backend server.
|
|
2. **HTTPS Passthrough (`https-passthrough`)**: Passes through raw TLS traffic without termination (SNI forwarding).
|
|
3. **HTTPS Termination to HTTP (`https-terminate-to-http`)**: Terminates TLS and forwards the decrypted traffic to an HTTP backend.
|
|
4. **HTTPS Termination to HTTPS (`https-terminate-to-https`)**: Terminates TLS and creates a new TLS connection to an HTTPS backend.
|
|
|
|
### Configuration Format
|
|
|
|
Each domain is configured with a forwarding type and target:
|
|
|
|
```typescript
|
|
{
|
|
domains: ['example.com'], // Single domain or array of domains (with wildcard support)
|
|
forwarding: {
|
|
type: 'http-only', // One of the four forwarding types
|
|
target: {
|
|
host: 'localhost', // Backend server (string or array for load balancing)
|
|
port: 3000 // Backend port
|
|
}
|
|
// Additional options as needed
|
|
}
|
|
}
|
|
```
|
|
|
|
### Helper Functions
|
|
|
|
Helper functions provide a cleaner syntax for creating configurations:
|
|
|
|
```typescript
|
|
// Instead of manually specifying the type and format
|
|
const config = createDomainConfig('example.com', httpOnly({
|
|
target: { host: 'localhost', port: 3000 }
|
|
}));
|
|
|
|
// Available helper functions:
|
|
// - httpOnly() - For HTTP-only traffic
|
|
// - httpsPassthrough() - For SNI-based passthrough
|
|
// - tlsTerminateToHttp() - For HTTPS termination to HTTP
|
|
// - tlsTerminateToHttps() - For HTTPS termination to HTTPS
|
|
```
|
|
|
|
### Advanced Configuration Options
|
|
|
|
For more complex scenarios, additional options can be specified:
|
|
|
|
```typescript
|
|
createDomainConfig('api.example.com', tlsTerminateToHttps({
|
|
// Target configuration with load balancing
|
|
target: {
|
|
host: ['10.0.0.10', '10.0.0.11'], // Round-robin load balancing
|
|
port: 8443
|
|
},
|
|
|
|
// HTTP options
|
|
http: {
|
|
enabled: true, // Listen on HTTP port
|
|
redirectToHttps: true // Automatically redirect to HTTPS
|
|
},
|
|
|
|
// HTTPS/TLS options
|
|
https: {
|
|
customCert: { // Provide your own certificate
|
|
key: '-----BEGIN PRIVATE KEY-----\n...',
|
|
cert: '-----BEGIN CERTIFICATE-----\n...'
|
|
},
|
|
forwardSni: true // Forward original SNI to backend
|
|
},
|
|
|
|
// Let's Encrypt ACME integration
|
|
acme: {
|
|
enabled: true, // Enable automatic certificates
|
|
production: true, // Use production Let's Encrypt
|
|
maintenance: true // Auto-renew certificates
|
|
},
|
|
|
|
// Security settings
|
|
security: {
|
|
allowedIps: ['10.0.0.*'], // IP allowlist (glob patterns)
|
|
blockedIps: ['1.2.3.4'], // IP blocklist
|
|
maxConnections: 100 // Connection limits
|
|
},
|
|
|
|
// Advanced settings
|
|
advanced: {
|
|
timeout: 30000, // Connection timeout in ms
|
|
headers: { // Custom headers to backend
|
|
'X-Forwarded-For': '{clientIp}',
|
|
'X-Original-Host': '{sni}' // Template variables available
|
|
},
|
|
keepAlive: true // Keep connections alive
|
|
}
|
|
}))
|
|
```
|
|
|
|
### Extended Configuration Options
|
|
|
|
#### IForwardConfig
|
|
- `type`: 'http-only' | 'https-passthrough' | 'https-terminate-to-http' | 'https-terminate-to-https'
|
|
- `target`: { host: string | string[], port: number }
|
|
- `http?`: { enabled?: boolean, redirectToHttps?: boolean, headers?: Record<string, string> }
|
|
- `https?`: { customCert?: { key: string, cert: string }, forwardSni?: boolean }
|
|
- `acme?`: { enabled?: boolean, maintenance?: boolean, production?: boolean, forwardChallenges?: { host: string, port: number, useTls?: boolean } }
|
|
- `security?`: { allowedIps?: string[], blockedIps?: string[], maxConnections?: number }
|
|
- `advanced?`: { portRanges?: Array<{ from: number, to: number }>, networkProxyPort?: number, keepAlive?: boolean, timeout?: number, headers?: Record<string, string> }
|
|
|
|
## Configuration Options
|
|
|
|
### NetworkProxy (INetworkProxyOptions)
|
|
- `port` (number, required)
|
|
- `backendProtocol` ('http1'|'http2', default 'http1')
|
|
- `maxConnections` (number, default 10000)
|
|
- `keepAliveTimeout` (ms, default 120000)
|
|
- `headersTimeout` (ms, default 60000)
|
|
- `cors` (object)
|
|
- `connectionPoolSize` (number, default 50)
|
|
- `logLevel` ('error'|'warn'|'info'|'debug')
|
|
- `acme` (IAcmeOptions)
|
|
- `useExternalPort80Handler` (boolean)
|
|
- `portProxyIntegration` (boolean)
|
|
|
|
### 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)
|
|
|
|
### Redirect / SslRedirect
|
|
- Constructor options: `httpPort`, `httpsPort`, `sslOptions`, `rules` (IRedirectRule[])
|
|
|
|
### SmartProxy (ISmartProxyOptions)
|
|
- `fromPort`, `toPort` (number)
|
|
- `domainConfigs` (IDomainConfig[]) - Using unified forwarding configuration
|
|
- `sniEnabled`, `preserveSourceIP` (booleans)
|
|
- `defaultAllowedIPs`, `defaultBlockedIPs` (string[]) - Default IP allowlists/blocklists
|
|
- Timeouts: `initialDataTimeout`, `socketTimeout`, `inactivityTimeout`, etc.
|
|
- Socket opts: `noDelay`, `keepAlive`, `enableKeepAliveProbes`
|
|
- `acme` (IAcmeOptions), `certProvisionFunction` (callback)
|
|
- `useNetworkProxy` (number[]), `networkProxyPort` (number)
|
|
- `globalPortRanges` (Array<{ from: number; to: number }>)
|
|
|
|
## Troubleshooting
|
|
|
|
### NetworkProxy
|
|
- Verify ports, certificates and `rejectUnauthorized` for TLS errors
|
|
- Configure CORS or use `addDefaultHeaders` 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
|
|
|
|
### Redirect / SslRedirect
|
|
- Check `fromHost`/`fromPath` patterns and Host headers
|
|
- Validate `sslOptions` key/cert correctness
|
|
|
|
### SmartProxy & SniHandler
|
|
- Increase `initialDataTimeout`/`maxPendingDataSize` for large ClientHello
|
|
- Enable `enableTlsDebugLogging` to trace handshake
|
|
- Ensure `allowSessionTicket` and fragmentation support for resumption
|
|
- Double-check forwarding configuration to ensure correct `type` for your use case
|
|
- Use helper functions like `httpOnly()`, `httpsPassthrough()`, etc. to create correct configurations
|
|
- For IP filtering issues, check the `security.allowedIps` and `security.blockedIps` settings
|
|
|
|
## License and Legal Information
|
|
|
|
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](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. |