@push.rocks/smartproxy 21.1.7 → 22.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/changelog.md +109 -0
- package/dist_rust/rustproxy +0 -0
- package/dist_ts/00_commitinfo_data.js +1 -1
- package/dist_ts/core/utils/shared-security-manager.d.ts +17 -0
- package/dist_ts/core/utils/shared-security-manager.js +66 -1
- package/dist_ts/index.d.ts +1 -5
- package/dist_ts/index.js +3 -9
- package/dist_ts/protocols/common/fragment-handler.js +5 -1
- package/dist_ts/proxies/http-proxy/default-certificates.d.ts +54 -0
- package/dist_ts/proxies/http-proxy/default-certificates.js +127 -0
- package/dist_ts/proxies/http-proxy/http-proxy.d.ts +1 -1
- package/dist_ts/proxies/http-proxy/http-proxy.js +9 -14
- package/dist_ts/proxies/http-proxy/index.d.ts +5 -1
- package/dist_ts/proxies/http-proxy/index.js +6 -2
- package/dist_ts/proxies/http-proxy/security-manager.d.ts +4 -12
- package/dist_ts/proxies/http-proxy/security-manager.js +66 -99
- package/dist_ts/proxies/index.d.ts +1 -5
- package/dist_ts/proxies/index.js +2 -6
- package/dist_ts/proxies/nftables-proxy/index.d.ts +1 -0
- package/dist_ts/proxies/nftables-proxy/index.js +2 -1
- package/dist_ts/proxies/nftables-proxy/nftables-proxy.d.ts +4 -26
- package/dist_ts/proxies/nftables-proxy/nftables-proxy.js +84 -236
- package/dist_ts/proxies/nftables-proxy/utils/index.d.ts +9 -0
- package/dist_ts/proxies/nftables-proxy/utils/index.js +12 -0
- package/dist_ts/proxies/nftables-proxy/utils/nft-command-executor.d.ts +66 -0
- package/dist_ts/proxies/nftables-proxy/utils/nft-command-executor.js +131 -0
- package/dist_ts/proxies/nftables-proxy/utils/nft-port-spec-normalizer.d.ts +39 -0
- package/dist_ts/proxies/nftables-proxy/utils/nft-port-spec-normalizer.js +112 -0
- package/dist_ts/proxies/nftables-proxy/utils/nft-rule-validator.d.ts +59 -0
- package/dist_ts/proxies/nftables-proxy/utils/nft-rule-validator.js +130 -0
- package/dist_ts/proxies/smart-proxy/certificate-manager.js +4 -3
- package/dist_ts/proxies/smart-proxy/connection-manager.d.ts +13 -2
- package/dist_ts/proxies/smart-proxy/connection-manager.js +16 -6
- package/dist_ts/proxies/smart-proxy/http-proxy-bridge.js +35 -10
- package/dist_ts/proxies/smart-proxy/index.d.ts +5 -10
- package/dist_ts/proxies/smart-proxy/index.js +7 -13
- package/dist_ts/proxies/smart-proxy/models/interfaces.d.ts +5 -3
- package/dist_ts/proxies/smart-proxy/route-connection-handler.d.ts +17 -0
- package/dist_ts/proxies/smart-proxy/route-connection-handler.js +72 -9
- package/dist_ts/proxies/smart-proxy/route-preprocessor.d.ts +37 -0
- package/dist_ts/proxies/smart-proxy/route-preprocessor.js +103 -0
- package/dist_ts/proxies/smart-proxy/rust-binary-locator.d.ts +23 -0
- package/dist_ts/proxies/smart-proxy/rust-binary-locator.js +104 -0
- package/dist_ts/proxies/smart-proxy/rust-metrics-adapter.d.ts +74 -0
- package/dist_ts/proxies/smart-proxy/rust-metrics-adapter.js +146 -0
- package/dist_ts/proxies/smart-proxy/rust-proxy-bridge.d.ts +49 -0
- package/dist_ts/proxies/smart-proxy/rust-proxy-bridge.js +259 -0
- package/dist_ts/proxies/smart-proxy/security-manager.d.ts +14 -12
- package/dist_ts/proxies/smart-proxy/security-manager.js +80 -74
- package/dist_ts/proxies/smart-proxy/smart-proxy.d.ts +39 -157
- package/dist_ts/proxies/smart-proxy/smart-proxy.js +224 -622
- package/dist_ts/proxies/smart-proxy/socket-handler-server.d.ts +45 -0
- package/dist_ts/proxies/smart-proxy/socket-handler-server.js +253 -0
- package/dist_ts/proxies/smart-proxy/tls-manager.d.ts +2 -9
- package/dist_ts/proxies/smart-proxy/tls-manager.js +3 -26
- package/dist_ts/proxies/smart-proxy/utils/index.d.ts +1 -1
- package/dist_ts/proxies/smart-proxy/utils/index.js +3 -4
- package/dist_ts/proxies/smart-proxy/utils/route-helpers/api-helpers.d.ts +49 -0
- package/dist_ts/proxies/smart-proxy/utils/route-helpers/api-helpers.js +108 -0
- package/dist_ts/proxies/smart-proxy/utils/route-helpers/dynamic-helpers.d.ts +57 -0
- package/dist_ts/proxies/smart-proxy/utils/route-helpers/dynamic-helpers.js +89 -0
- package/dist_ts/proxies/smart-proxy/utils/route-helpers/http-helpers.d.ts +17 -0
- package/dist_ts/proxies/smart-proxy/utils/route-helpers/http-helpers.js +32 -0
- package/dist_ts/proxies/smart-proxy/utils/route-helpers/https-helpers.d.ts +68 -0
- package/dist_ts/proxies/smart-proxy/utils/route-helpers/https-helpers.js +117 -0
- package/dist_ts/proxies/smart-proxy/utils/route-helpers/index.d.ts +17 -0
- package/dist_ts/proxies/smart-proxy/utils/route-helpers/index.js +27 -0
- package/dist_ts/proxies/smart-proxy/utils/route-helpers/load-balancer-helpers.d.ts +63 -0
- package/dist_ts/proxies/smart-proxy/utils/route-helpers/load-balancer-helpers.js +105 -0
- package/dist_ts/proxies/smart-proxy/utils/route-helpers/nftables-helpers.d.ts +83 -0
- package/dist_ts/proxies/smart-proxy/utils/route-helpers/nftables-helpers.js +126 -0
- package/dist_ts/proxies/smart-proxy/utils/route-helpers/security-helpers.d.ts +47 -0
- package/dist_ts/proxies/smart-proxy/utils/route-helpers/security-helpers.js +66 -0
- package/dist_ts/proxies/smart-proxy/utils/route-helpers/socket-handlers.d.ts +70 -0
- package/dist_ts/proxies/smart-proxy/utils/route-helpers/socket-handlers.js +287 -0
- package/dist_ts/proxies/smart-proxy/utils/route-helpers/websocket-helpers.d.ts +46 -0
- package/dist_ts/proxies/smart-proxy/utils/route-helpers/websocket-helpers.js +67 -0
- package/dist_ts/proxies/smart-proxy/utils/route-helpers.d.ts +4 -457
- package/dist_ts/proxies/smart-proxy/utils/route-helpers.js +6 -950
- package/dist_ts/proxies/smart-proxy/utils/route-utils.js +2 -2
- package/dist_ts/proxies/smart-proxy/utils/route-validator.d.ts +67 -1
- package/dist_ts/proxies/smart-proxy/utils/route-validator.js +251 -3
- package/dist_ts/routing/index.d.ts +1 -1
- package/dist_ts/routing/index.js +3 -3
- package/dist_ts/routing/models/http-types.d.ts +119 -4
- package/dist_ts/routing/models/http-types.js +93 -5
- package/npmextra.json +12 -6
- package/package.json +34 -24
- package/readme.hints.md +184 -1
- package/readme.md +580 -266
- package/ts/00_commitinfo_data.ts +1 -1
- package/ts/core/utils/shared-security-manager.ts +98 -13
- package/ts/index.ts +4 -12
- package/ts/protocols/common/fragment-handler.ts +4 -0
- package/ts/proxies/index.ts +1 -9
- package/ts/proxies/nftables-proxy/index.ts +1 -0
- package/ts/proxies/nftables-proxy/nftables-proxy.ts +116 -290
- package/ts/proxies/nftables-proxy/utils/index.ts +38 -0
- package/ts/proxies/nftables-proxy/utils/nft-command-executor.ts +162 -0
- package/ts/proxies/nftables-proxy/utils/nft-port-spec-normalizer.ts +125 -0
- package/ts/proxies/nftables-proxy/utils/nft-rule-validator.ts +156 -0
- package/ts/proxies/smart-proxy/index.ts +6 -13
- package/ts/proxies/smart-proxy/models/interfaces.ts +6 -5
- package/ts/proxies/smart-proxy/route-preprocessor.ts +122 -0
- package/ts/proxies/smart-proxy/rust-binary-locator.ts +112 -0
- package/ts/proxies/smart-proxy/rust-metrics-adapter.ts +161 -0
- package/ts/proxies/smart-proxy/rust-proxy-bridge.ts +310 -0
- package/ts/proxies/smart-proxy/smart-proxy.ts +282 -800
- package/ts/proxies/smart-proxy/socket-handler-server.ts +279 -0
- package/ts/proxies/smart-proxy/utils/index.ts +3 -5
- package/ts/proxies/smart-proxy/utils/route-helpers/api-helpers.ts +144 -0
- package/ts/proxies/smart-proxy/utils/route-helpers/dynamic-helpers.ts +124 -0
- package/ts/proxies/smart-proxy/utils/route-helpers/http-helpers.ts +40 -0
- package/ts/proxies/smart-proxy/utils/route-helpers/https-helpers.ts +163 -0
- package/ts/proxies/smart-proxy/utils/route-helpers/index.ts +62 -0
- package/ts/proxies/smart-proxy/utils/route-helpers/load-balancer-helpers.ts +154 -0
- package/ts/proxies/smart-proxy/utils/route-helpers/nftables-helpers.ts +202 -0
- package/ts/proxies/smart-proxy/utils/route-helpers/security-helpers.ts +96 -0
- package/ts/proxies/smart-proxy/utils/route-helpers/socket-handlers.ts +337 -0
- package/ts/proxies/smart-proxy/utils/route-helpers/websocket-helpers.ts +98 -0
- package/ts/proxies/smart-proxy/utils/route-helpers.ts +5 -1302
- package/ts/proxies/smart-proxy/utils/route-utils.ts +1 -1
- package/ts/proxies/smart-proxy/utils/route-validator.ts +274 -4
- package/ts/routing/index.ts +2 -2
- package/ts/routing/models/http-types.ts +147 -4
- package/ts/proxies/http-proxy/certificate-manager.ts +0 -244
- package/ts/proxies/http-proxy/connection-pool.ts +0 -228
- package/ts/proxies/http-proxy/context-creator.ts +0 -145
- package/ts/proxies/http-proxy/function-cache.ts +0 -279
- package/ts/proxies/http-proxy/handlers/index.ts +0 -5
- package/ts/proxies/http-proxy/http-proxy.ts +0 -675
- package/ts/proxies/http-proxy/http-request-handler.ts +0 -331
- package/ts/proxies/http-proxy/http2-request-handler.ts +0 -255
- package/ts/proxies/http-proxy/index.ts +0 -13
- package/ts/proxies/http-proxy/models/http-types.ts +0 -148
- package/ts/proxies/http-proxy/models/index.ts +0 -5
- package/ts/proxies/http-proxy/models/types.ts +0 -125
- package/ts/proxies/http-proxy/request-handler.ts +0 -878
- package/ts/proxies/http-proxy/security-manager.ts +0 -433
- package/ts/proxies/http-proxy/websocket-handler.ts +0 -581
- package/ts/proxies/smart-proxy/acme-state-manager.ts +0 -112
- package/ts/proxies/smart-proxy/cert-store.ts +0 -92
- package/ts/proxies/smart-proxy/certificate-manager.ts +0 -894
- package/ts/proxies/smart-proxy/connection-manager.ts +0 -796
- package/ts/proxies/smart-proxy/http-proxy-bridge.ts +0 -187
- package/ts/proxies/smart-proxy/metrics-collector.ts +0 -453
- package/ts/proxies/smart-proxy/nftables-manager.ts +0 -271
- package/ts/proxies/smart-proxy/port-manager.ts +0 -358
- package/ts/proxies/smart-proxy/route-connection-handler.ts +0 -1640
- package/ts/proxies/smart-proxy/route-orchestrator.ts +0 -297
- package/ts/proxies/smart-proxy/security-manager.ts +0 -257
- package/ts/proxies/smart-proxy/throughput-tracker.ts +0 -138
- package/ts/proxies/smart-proxy/timeout-manager.ts +0 -196
- package/ts/proxies/smart-proxy/tls-manager.ts +0 -207
- package/ts/proxies/smart-proxy/utils/route-validators.ts +0 -283
package/readme.md
CHANGED
|
@@ -1,33 +1,45 @@
|
|
|
1
1
|
# @push.rocks/smartproxy 🚀
|
|
2
2
|
|
|
3
|
-
**
|
|
4
|
-
|
|
5
|
-
## 🎯 What is SmartProxy?
|
|
6
|
-
|
|
7
|
-
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.
|
|
8
|
-
|
|
9
|
-
### ⚡ Key Features
|
|
10
|
-
|
|
11
|
-
- **🔀 Unified Route-Based Configuration** - Clean match/action patterns for intuitive traffic routing
|
|
12
|
-
- **🔒 Automatic SSL/TLS with Let's Encrypt** - Zero-config HTTPS with automatic certificate provisioning
|
|
13
|
-
- **🎯 Flexible Matching Patterns** - Route by port, domain, path, client IP, TLS version, or custom logic
|
|
14
|
-
- **🚄 High-Performance Forwarding** - Choose between user-space or kernel-level (NFTables) forwarding
|
|
15
|
-
- **⚖️ Built-in Load Balancing** - Distribute traffic across multiple backends with health checks
|
|
16
|
-
- **🛡️ Enterprise Security** - IP filtering, rate limiting, authentication, and connection limits
|
|
17
|
-
- **🔌 WebSocket Support** - First-class WebSocket proxying with ping/pong management
|
|
18
|
-
- **🎮 Custom Socket Handlers** - Implement any protocol with full socket control
|
|
19
|
-
- **📊 Dynamic Port Management** - Add/remove ports at runtime without restarts
|
|
20
|
-
- **🔧 Protocol Detection** - Smart protocol detection for mixed-mode operation
|
|
3
|
+
**A high-performance, Rust-powered proxy toolkit for Node.js** — unified route-based configuration for SSL/TLS termination, HTTP/HTTPS reverse proxying, WebSocket support, load balancing, custom protocol handlers, and kernel-level NFTables forwarding.
|
|
21
4
|
|
|
22
5
|
## 📦 Installation
|
|
23
6
|
|
|
24
7
|
```bash
|
|
25
8
|
npm install @push.rocks/smartproxy
|
|
9
|
+
# or
|
|
10
|
+
pnpm add @push.rocks/smartproxy
|
|
26
11
|
```
|
|
27
12
|
|
|
13
|
+
## Issue Reporting and Security
|
|
14
|
+
|
|
15
|
+
For reporting bugs, issues, or security vulnerabilities, please visit [community.foss.global/](https://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/](https://code.foss.global/) account to submit Pull Requests directly.
|
|
16
|
+
|
|
17
|
+
## 🎯 What is SmartProxy?
|
|
18
|
+
|
|
19
|
+
SmartProxy is a production-ready proxy solution that takes the complexity out of traffic management. Under the hood, all networking — TCP, TLS, HTTP reverse proxy, connection tracking, security enforcement, and NFTables — is handled by a **Rust engine** for maximum performance, while you configure everything through a clean TypeScript API with full type safety.
|
|
20
|
+
|
|
21
|
+
Whether you're building microservices, deploying edge infrastructure, or need a battle-tested reverse proxy with automatic Let's Encrypt certificates, SmartProxy has you covered.
|
|
22
|
+
|
|
23
|
+
### ⚡ Key Features
|
|
24
|
+
|
|
25
|
+
| Feature | Description |
|
|
26
|
+
|---------|-------------|
|
|
27
|
+
| 🦀 **Rust-Powered Engine** | All networking handled by a high-performance Rust binary via IPC |
|
|
28
|
+
| 🔀 **Unified Route-Based Config** | Clean match/action patterns for intuitive traffic routing |
|
|
29
|
+
| 🔒 **Automatic SSL/TLS** | Zero-config HTTPS with Let's Encrypt ACME integration |
|
|
30
|
+
| 🎯 **Flexible Matching** | Route by port, domain, path, client IP, TLS version, headers, or custom logic |
|
|
31
|
+
| 🚄 **High-Performance** | Choose between user-space or kernel-level (NFTables) forwarding |
|
|
32
|
+
| ⚖️ **Load Balancing** | Round-robin, least-connections, IP-hash with health checks |
|
|
33
|
+
| 🛡️ **Enterprise Security** | IP filtering, rate limiting, basic auth, JWT auth, connection limits |
|
|
34
|
+
| 🔌 **WebSocket Support** | First-class WebSocket proxying with ping/pong keep-alive |
|
|
35
|
+
| 🎮 **Custom Protocols** | Socket handlers for implementing any protocol in TypeScript |
|
|
36
|
+
| 📊 **Live Metrics** | Real-time throughput, connection counts, and performance data |
|
|
37
|
+
| 🔧 **Dynamic Management** | Add/remove ports and routes at runtime without restarts |
|
|
38
|
+
| 🔄 **PROXY Protocol** | Full PROXY protocol v1/v2 support for preserving client information |
|
|
39
|
+
|
|
28
40
|
## 🚀 Quick Start
|
|
29
41
|
|
|
30
|
-
|
|
42
|
+
Get up and running in 30 seconds:
|
|
31
43
|
|
|
32
44
|
```typescript
|
|
33
45
|
import { SmartProxy, createCompleteHttpsServer } from '@push.rocks/smartproxy';
|
|
@@ -35,16 +47,16 @@ import { SmartProxy, createCompleteHttpsServer } from '@push.rocks/smartproxy';
|
|
|
35
47
|
// Create a proxy with automatic HTTPS
|
|
36
48
|
const proxy = new SmartProxy({
|
|
37
49
|
acme: {
|
|
38
|
-
email: 'ssl@
|
|
39
|
-
useProduction: true
|
|
50
|
+
email: 'ssl@yourdomain.com',
|
|
51
|
+
useProduction: true
|
|
40
52
|
},
|
|
41
53
|
routes: [
|
|
42
|
-
// Complete HTTPS setup
|
|
43
|
-
...createCompleteHttpsServer('app.example.com', {
|
|
44
|
-
host: 'localhost',
|
|
45
|
-
port: 3000
|
|
54
|
+
// Complete HTTPS setup in one call! ✨
|
|
55
|
+
...createCompleteHttpsServer('app.example.com', {
|
|
56
|
+
host: 'localhost',
|
|
57
|
+
port: 3000
|
|
46
58
|
}, {
|
|
47
|
-
certificate: 'auto' //
|
|
59
|
+
certificate: 'auto' // Automatic Let's Encrypt cert 🎩
|
|
48
60
|
})
|
|
49
61
|
]
|
|
50
62
|
});
|
|
@@ -57,10 +69,11 @@ console.log('🚀 Proxy running with automatic HTTPS!');
|
|
|
57
69
|
|
|
58
70
|
### 🏗️ Route-Based Architecture
|
|
59
71
|
|
|
60
|
-
SmartProxy uses a powerful match/action pattern that makes routing predictable and maintainable:
|
|
72
|
+
SmartProxy uses a powerful **match/action** pattern that makes routing predictable and maintainable:
|
|
61
73
|
|
|
62
74
|
```typescript
|
|
63
75
|
{
|
|
76
|
+
name: 'api-route',
|
|
64
77
|
match: {
|
|
65
78
|
ports: 443,
|
|
66
79
|
domains: 'api.example.com',
|
|
@@ -74,22 +87,32 @@ SmartProxy uses a powerful match/action pattern that makes routing predictable a
|
|
|
74
87
|
}
|
|
75
88
|
```
|
|
76
89
|
|
|
77
|
-
Every route
|
|
78
|
-
- **Match
|
|
79
|
-
- **Action**
|
|
80
|
-
- **Security** (optional)
|
|
81
|
-
- **
|
|
90
|
+
Every route consists of:
|
|
91
|
+
- **Match** — What traffic to capture (ports, domains, paths, IPs, headers)
|
|
92
|
+
- **Action** — What to do with it (`forward` or `socket-handler`)
|
|
93
|
+
- **Security** (optional) — IP allow/block lists, rate limits, authentication
|
|
94
|
+
- **Headers** (optional) — Request/response header manipulation with template variables
|
|
95
|
+
- **Name/Priority** (optional) — For identification and ordering
|
|
96
|
+
|
|
97
|
+
### 🔄 TLS Modes
|
|
98
|
+
|
|
99
|
+
SmartProxy supports three TLS handling modes:
|
|
100
|
+
|
|
101
|
+
| Mode | Description | Use Case |
|
|
102
|
+
|------|-------------|----------|
|
|
103
|
+
| `passthrough` | Forward encrypted traffic as-is (SNI-based routing) | Backend handles TLS |
|
|
104
|
+
| `terminate` | Decrypt at proxy, forward plain HTTP to backend | Standard reverse proxy |
|
|
105
|
+
| `terminate-and-reencrypt` | Decrypt, then re-encrypt to backend | Zero-trust environments |
|
|
82
106
|
|
|
83
107
|
## 💡 Common Use Cases
|
|
84
108
|
|
|
85
|
-
### 🌐
|
|
109
|
+
### 🌐 HTTP to HTTPS Redirect
|
|
86
110
|
|
|
87
111
|
```typescript
|
|
88
112
|
import { SmartProxy, createHttpToHttpsRedirect } from '@push.rocks/smartproxy';
|
|
89
113
|
|
|
90
114
|
const proxy = new SmartProxy({
|
|
91
115
|
routes: [
|
|
92
|
-
// Redirect all HTTP traffic to HTTPS
|
|
93
116
|
createHttpToHttpsRedirect(['example.com', '*.example.com'])
|
|
94
117
|
]
|
|
95
118
|
});
|
|
@@ -98,52 +121,61 @@ const proxy = new SmartProxy({
|
|
|
98
121
|
### ⚖️ Load Balancer with Health Checks
|
|
99
122
|
|
|
100
123
|
```typescript
|
|
101
|
-
import { createLoadBalancerRoute } from '@push.rocks/smartproxy';
|
|
102
|
-
|
|
103
|
-
const
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
124
|
+
import { SmartProxy, createLoadBalancerRoute } from '@push.rocks/smartproxy';
|
|
125
|
+
|
|
126
|
+
const proxy = new SmartProxy({
|
|
127
|
+
routes: [
|
|
128
|
+
createLoadBalancerRoute(
|
|
129
|
+
'app.example.com',
|
|
130
|
+
[
|
|
131
|
+
{ host: 'server1.internal', port: 8080 },
|
|
132
|
+
{ host: 'server2.internal', port: 8080 },
|
|
133
|
+
{ host: 'server3.internal', port: 8080 }
|
|
134
|
+
],
|
|
135
|
+
{
|
|
136
|
+
tls: { mode: 'terminate', certificate: 'auto' },
|
|
137
|
+
loadBalancing: {
|
|
138
|
+
algorithm: 'round-robin',
|
|
139
|
+
healthCheck: {
|
|
140
|
+
path: '/health',
|
|
141
|
+
interval: 30000,
|
|
142
|
+
timeout: 5000
|
|
143
|
+
}
|
|
144
|
+
}
|
|
118
145
|
}
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
);
|
|
146
|
+
)
|
|
147
|
+
]
|
|
148
|
+
});
|
|
122
149
|
```
|
|
123
150
|
|
|
124
151
|
### 🔌 WebSocket Proxy
|
|
125
152
|
|
|
126
153
|
```typescript
|
|
127
|
-
import { createWebSocketRoute } from '@push.rocks/smartproxy';
|
|
154
|
+
import { SmartProxy, createWebSocketRoute } from '@push.rocks/smartproxy';
|
|
128
155
|
|
|
129
|
-
const
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
156
|
+
const proxy = new SmartProxy({
|
|
157
|
+
routes: [
|
|
158
|
+
createWebSocketRoute(
|
|
159
|
+
'ws.example.com',
|
|
160
|
+
{ host: 'websocket-server', port: 8080 },
|
|
161
|
+
{
|
|
162
|
+
path: '/socket',
|
|
163
|
+
useTls: true,
|
|
164
|
+
certificate: 'auto',
|
|
165
|
+
pingInterval: 30000,
|
|
166
|
+
pingTimeout: 10000
|
|
167
|
+
}
|
|
168
|
+
)
|
|
169
|
+
]
|
|
170
|
+
});
|
|
139
171
|
```
|
|
140
172
|
|
|
141
173
|
### 🚦 API Gateway with Rate Limiting
|
|
142
174
|
|
|
143
175
|
```typescript
|
|
144
|
-
import { createApiGatewayRoute, addRateLimiting } from '@push.rocks/smartproxy';
|
|
176
|
+
import { SmartProxy, createApiGatewayRoute, addRateLimiting } from '@push.rocks/smartproxy';
|
|
145
177
|
|
|
146
|
-
let
|
|
178
|
+
let apiRoute = createApiGatewayRoute(
|
|
147
179
|
'api.example.com',
|
|
148
180
|
'/api',
|
|
149
181
|
{ host: 'api-backend', port: 8080 },
|
|
@@ -154,354 +186,636 @@ let route = createApiGatewayRoute(
|
|
|
154
186
|
}
|
|
155
187
|
);
|
|
156
188
|
|
|
157
|
-
// Add rate limiting
|
|
158
|
-
|
|
189
|
+
// Add rate limiting — 100 requests per minute per IP
|
|
190
|
+
apiRoute = addRateLimiting(apiRoute, {
|
|
159
191
|
maxRequests: 100,
|
|
160
|
-
window: 60,
|
|
192
|
+
window: 60,
|
|
161
193
|
keyBy: 'ip'
|
|
162
194
|
});
|
|
195
|
+
|
|
196
|
+
const proxy = new SmartProxy({ routes: [apiRoute] });
|
|
163
197
|
```
|
|
164
198
|
|
|
165
199
|
### 🎮 Custom Protocol Handler
|
|
166
200
|
|
|
201
|
+
SmartProxy lets you implement any protocol with full socket control. Routes with JavaScript socket handlers are automatically relayed from the Rust engine back to your TypeScript code:
|
|
202
|
+
|
|
167
203
|
```typescript
|
|
168
|
-
import { createSocketHandlerRoute, SocketHandlers } from '@push.rocks/smartproxy';
|
|
204
|
+
import { SmartProxy, createSocketHandlerRoute, SocketHandlers } from '@push.rocks/smartproxy';
|
|
169
205
|
|
|
170
|
-
//
|
|
206
|
+
// Use pre-built handlers
|
|
171
207
|
const echoRoute = createSocketHandlerRoute(
|
|
172
|
-
'echo.example.com',
|
|
173
|
-
7777,
|
|
208
|
+
'echo.example.com',
|
|
209
|
+
7777,
|
|
174
210
|
SocketHandlers.echo
|
|
175
211
|
);
|
|
176
212
|
|
|
177
|
-
//
|
|
213
|
+
// Or create your own custom protocol
|
|
178
214
|
const customRoute = createSocketHandlerRoute(
|
|
179
215
|
'custom.example.com',
|
|
180
216
|
9999,
|
|
181
|
-
async (socket
|
|
182
|
-
console.log(`
|
|
183
|
-
|
|
217
|
+
async (socket) => {
|
|
218
|
+
console.log(`New connection on custom protocol`);
|
|
184
219
|
socket.write('Welcome to my custom protocol!\n');
|
|
185
|
-
|
|
220
|
+
|
|
186
221
|
socket.on('data', (data) => {
|
|
187
222
|
const command = data.toString().trim();
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
socket.write(
|
|
191
|
-
|
|
192
|
-
socket.
|
|
223
|
+
switch (command) {
|
|
224
|
+
case 'PING': socket.write('PONG\n'); break;
|
|
225
|
+
case 'TIME': socket.write(`${new Date().toISOString()}\n`); break;
|
|
226
|
+
case 'QUIT': socket.end('Goodbye!\n'); break;
|
|
227
|
+
default: socket.write(`Unknown: ${command}\n`);
|
|
193
228
|
}
|
|
194
229
|
});
|
|
195
230
|
}
|
|
196
231
|
);
|
|
232
|
+
|
|
233
|
+
const proxy = new SmartProxy({ routes: [echoRoute, customRoute] });
|
|
197
234
|
```
|
|
198
235
|
|
|
236
|
+
**Pre-built Socket Handlers:**
|
|
237
|
+
|
|
238
|
+
| Handler | Description |
|
|
239
|
+
|---------|-------------|
|
|
240
|
+
| `SocketHandlers.echo` | Echo server — returns everything sent |
|
|
241
|
+
| `SocketHandlers.proxy(host, port)` | TCP proxy to another server |
|
|
242
|
+
| `SocketHandlers.lineProtocol(handler)` | Line-based text protocol |
|
|
243
|
+
| `SocketHandlers.httpResponse(code, body)` | Simple HTTP response |
|
|
244
|
+
| `SocketHandlers.httpRedirect(url, code)` | HTTP redirect with template variables (`{domain}`, `{path}`, `{port}`, `{clientIp}`) |
|
|
245
|
+
| `SocketHandlers.httpServer(handler)` | Full HTTP request/response handling |
|
|
246
|
+
| `SocketHandlers.httpBlock(status, message)` | HTTP block response |
|
|
247
|
+
| `SocketHandlers.block(message)` | Block with optional message |
|
|
248
|
+
|
|
199
249
|
### ⚡ High-Performance NFTables Forwarding
|
|
200
250
|
|
|
201
|
-
For ultra-low latency, use kernel-level forwarding (
|
|
251
|
+
For ultra-low latency on Linux, use kernel-level forwarding (requires root):
|
|
202
252
|
|
|
203
253
|
```typescript
|
|
204
|
-
import { createNfTablesTerminateRoute } from '@push.rocks/smartproxy';
|
|
254
|
+
import { SmartProxy, createNfTablesTerminateRoute } from '@push.rocks/smartproxy';
|
|
205
255
|
|
|
206
|
-
const
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
256
|
+
const proxy = new SmartProxy({
|
|
257
|
+
routes: [
|
|
258
|
+
createNfTablesTerminateRoute(
|
|
259
|
+
'fast.example.com',
|
|
260
|
+
{ host: 'backend', port: 8080 },
|
|
261
|
+
{
|
|
262
|
+
ports: 443,
|
|
263
|
+
certificate: 'auto',
|
|
264
|
+
preserveSourceIP: true // Backend sees real client IP
|
|
265
|
+
}
|
|
266
|
+
)
|
|
267
|
+
]
|
|
268
|
+
});
|
|
269
|
+
```
|
|
270
|
+
|
|
271
|
+
### 🔒 SNI Passthrough (TLS Passthrough)
|
|
272
|
+
|
|
273
|
+
Forward encrypted traffic to backends without terminating TLS — the proxy routes based on the SNI hostname alone:
|
|
274
|
+
|
|
275
|
+
```typescript
|
|
276
|
+
import { SmartProxy, createHttpsPassthroughRoute } from '@push.rocks/smartproxy';
|
|
277
|
+
|
|
278
|
+
const proxy = new SmartProxy({
|
|
279
|
+
routes: [
|
|
280
|
+
createHttpsPassthroughRoute('secure.example.com', {
|
|
281
|
+
host: 'backend-that-handles-tls',
|
|
282
|
+
port: 8443
|
|
283
|
+
})
|
|
284
|
+
]
|
|
285
|
+
});
|
|
216
286
|
```
|
|
217
287
|
|
|
218
288
|
## 🔧 Advanced Features
|
|
219
289
|
|
|
220
290
|
### 🎯 Dynamic Routing
|
|
221
291
|
|
|
222
|
-
Route traffic based on runtime conditions:
|
|
292
|
+
Route traffic based on runtime conditions using function-based host/port resolution:
|
|
223
293
|
|
|
224
294
|
```typescript
|
|
225
|
-
{
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
295
|
+
const proxy = new SmartProxy({
|
|
296
|
+
routes: [{
|
|
297
|
+
name: 'dynamic-backend',
|
|
298
|
+
match: {
|
|
299
|
+
ports: 443,
|
|
300
|
+
domains: 'app.example.com'
|
|
301
|
+
},
|
|
302
|
+
action: {
|
|
303
|
+
type: 'forward',
|
|
304
|
+
targets: [{
|
|
305
|
+
host: (context) => {
|
|
306
|
+
return context.path?.startsWith('/premium')
|
|
307
|
+
? 'premium-backend'
|
|
308
|
+
: 'standard-backend';
|
|
309
|
+
},
|
|
310
|
+
port: 8080
|
|
311
|
+
}],
|
|
312
|
+
tls: { mode: 'terminate', certificate: 'auto' }
|
|
232
313
|
}
|
|
233
|
-
}
|
|
234
|
-
|
|
235
|
-
type: 'forward',
|
|
236
|
-
targets: [{
|
|
237
|
-
host: (context) => {
|
|
238
|
-
// Dynamic host selection
|
|
239
|
-
return context.path.startsWith('/premium')
|
|
240
|
-
? 'premium-backend'
|
|
241
|
-
: 'standard-backend';
|
|
242
|
-
},
|
|
243
|
-
port: 8080
|
|
244
|
-
}]
|
|
245
|
-
}
|
|
246
|
-
}
|
|
314
|
+
}]
|
|
315
|
+
});
|
|
247
316
|
```
|
|
248
317
|
|
|
318
|
+
> **Note:** Routes with dynamic functions (host/port callbacks) are automatically relayed through the TypeScript socket handler server, since JavaScript functions can't be serialized to Rust.
|
|
319
|
+
|
|
249
320
|
### 🔒 Security Controls
|
|
250
321
|
|
|
251
|
-
Comprehensive security options
|
|
322
|
+
Comprehensive per-route security options:
|
|
252
323
|
|
|
253
324
|
```typescript
|
|
254
325
|
{
|
|
326
|
+
name: 'secure-api',
|
|
327
|
+
match: { ports: 443, domains: 'api.example.com' },
|
|
328
|
+
action: {
|
|
329
|
+
type: 'forward',
|
|
330
|
+
targets: [{ host: 'api-backend', port: 8080 }],
|
|
331
|
+
tls: { mode: 'terminate', certificate: 'auto' }
|
|
332
|
+
},
|
|
255
333
|
security: {
|
|
256
334
|
// IP-based access control
|
|
257
335
|
ipAllowList: ['10.0.0.0/8', '192.168.*'],
|
|
258
336
|
ipBlockList: ['192.168.1.100'],
|
|
259
|
-
|
|
337
|
+
|
|
260
338
|
// Connection limits
|
|
261
339
|
maxConnections: 1000,
|
|
262
|
-
|
|
263
|
-
|
|
340
|
+
|
|
264
341
|
// Rate limiting
|
|
265
342
|
rateLimit: {
|
|
343
|
+
enabled: true,
|
|
266
344
|
maxRequests: 100,
|
|
267
|
-
|
|
345
|
+
window: 60
|
|
268
346
|
},
|
|
269
|
-
|
|
347
|
+
|
|
270
348
|
// Authentication
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
secret: process.env.JWT_SECRET,
|
|
274
|
-
algorithms: ['HS256']
|
|
275
|
-
}
|
|
349
|
+
basicAuth: { users: [{ username: 'admin', password: 'secret' }] },
|
|
350
|
+
jwtAuth: { secret: 'your-jwt-secret', algorithm: 'HS256' }
|
|
276
351
|
}
|
|
277
352
|
}
|
|
278
353
|
```
|
|
279
354
|
|
|
355
|
+
**Security modifier helpers** let you add security to any existing route:
|
|
356
|
+
|
|
357
|
+
```typescript
|
|
358
|
+
import { addRateLimiting, addBasicAuth, addJwtAuth } from '@push.rocks/smartproxy';
|
|
359
|
+
|
|
360
|
+
let route = createHttpsTerminateRoute('api.example.com', { host: 'backend', port: 8080 });
|
|
361
|
+
route = addRateLimiting(route, { maxRequests: 100, window: 60, keyBy: 'ip' });
|
|
362
|
+
route = addBasicAuth(route, { users: [{ username: 'admin', password: 'secret' }] });
|
|
363
|
+
```
|
|
364
|
+
|
|
280
365
|
### 📊 Runtime Management
|
|
281
366
|
|
|
282
367
|
Control your proxy without restarts:
|
|
283
368
|
|
|
284
369
|
```typescript
|
|
285
|
-
//
|
|
370
|
+
// Dynamic port management
|
|
286
371
|
await proxy.addListeningPort(8443);
|
|
287
372
|
await proxy.removeListeningPort(8080);
|
|
373
|
+
const ports = await proxy.getListeningPorts();
|
|
288
374
|
|
|
289
|
-
// Update routes on the fly
|
|
375
|
+
// Update routes on the fly (atomic, mutex-locked)
|
|
290
376
|
await proxy.updateRoutes([...newRoutes]);
|
|
291
377
|
|
|
292
|
-
//
|
|
293
|
-
const status = proxy.getStatus();
|
|
378
|
+
// Get real-time metrics
|
|
294
379
|
const metrics = proxy.getMetrics();
|
|
380
|
+
console.log(`Active connections: ${metrics.connections.active()}`);
|
|
381
|
+
console.log(`Requests/sec: ${metrics.throughput.requestsPerSecond()}`);
|
|
382
|
+
|
|
383
|
+
// Get detailed statistics from the Rust engine
|
|
384
|
+
const stats = await proxy.getStatistics();
|
|
295
385
|
|
|
296
386
|
// Certificate management
|
|
297
|
-
await proxy.
|
|
298
|
-
|
|
387
|
+
await proxy.provisionCertificate('my-route-name');
|
|
388
|
+
await proxy.renewCertificate('my-route-name');
|
|
389
|
+
const certStatus = await proxy.getCertificateStatus('my-route-name');
|
|
390
|
+
|
|
391
|
+
// NFTables status
|
|
392
|
+
const nftStatus = await proxy.getNfTablesStatus();
|
|
299
393
|
```
|
|
300
394
|
|
|
301
395
|
### 🔄 Header Manipulation
|
|
302
396
|
|
|
303
|
-
Transform requests and responses:
|
|
397
|
+
Transform requests and responses with template variables:
|
|
304
398
|
|
|
305
399
|
```typescript
|
|
306
400
|
{
|
|
307
401
|
action: {
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
},
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
402
|
+
type: 'forward',
|
|
403
|
+
targets: [{ host: 'backend', port: 8080 }]
|
|
404
|
+
},
|
|
405
|
+
headers: {
|
|
406
|
+
request: {
|
|
407
|
+
'X-Real-IP': '{clientIp}',
|
|
408
|
+
'X-Request-ID': '{uuid}',
|
|
409
|
+
'X-Forwarded-Proto': 'https'
|
|
410
|
+
},
|
|
411
|
+
response: {
|
|
412
|
+
'Strict-Transport-Security': 'max-age=31536000',
|
|
413
|
+
'X-Frame-Options': 'DENY'
|
|
319
414
|
}
|
|
320
415
|
}
|
|
321
416
|
}
|
|
322
417
|
```
|
|
323
418
|
|
|
419
|
+
### 🔀 PROXY Protocol Support
|
|
420
|
+
|
|
421
|
+
Preserve original client information through proxy chains:
|
|
422
|
+
|
|
423
|
+
```typescript
|
|
424
|
+
const proxy = new SmartProxy({
|
|
425
|
+
// Accept PROXY protocol from trusted load balancers
|
|
426
|
+
acceptProxyProtocol: true,
|
|
427
|
+
proxyIPs: ['10.0.0.1', '10.0.0.2'],
|
|
428
|
+
|
|
429
|
+
// Forward PROXY protocol to backends
|
|
430
|
+
sendProxyProtocol: true,
|
|
431
|
+
|
|
432
|
+
routes: [...]
|
|
433
|
+
});
|
|
434
|
+
```
|
|
435
|
+
|
|
436
|
+
### 🏗️ Custom Certificate Provisioning
|
|
437
|
+
|
|
438
|
+
Supply your own certificates or integrate with external certificate providers:
|
|
439
|
+
|
|
440
|
+
```typescript
|
|
441
|
+
const proxy = new SmartProxy({
|
|
442
|
+
certProvisionFunction: async (domain: string) => {
|
|
443
|
+
// Return 'http01' to let the built-in ACME handle it
|
|
444
|
+
if (domain.endsWith('.example.com')) return 'http01';
|
|
445
|
+
|
|
446
|
+
// Or return a static certificate object
|
|
447
|
+
return {
|
|
448
|
+
publicKey: myPemCert,
|
|
449
|
+
privateKey: myPemKey,
|
|
450
|
+
};
|
|
451
|
+
},
|
|
452
|
+
certProvisionFallbackToAcme: true, // Fall back to ACME if callback fails
|
|
453
|
+
routes: [...]
|
|
454
|
+
});
|
|
455
|
+
```
|
|
456
|
+
|
|
324
457
|
## 🏛️ Architecture
|
|
325
458
|
|
|
326
|
-
SmartProxy
|
|
459
|
+
SmartProxy uses a hybrid **Rust + TypeScript** architecture:
|
|
327
460
|
|
|
328
461
|
```
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
462
|
+
┌─────────────────────────────────────────────────────┐
|
|
463
|
+
│ Your Application │
|
|
464
|
+
│ (TypeScript — routes, config, socket handlers) │
|
|
465
|
+
└──────────────────┬──────────────────────────────────┘
|
|
466
|
+
│ IPC (JSON over stdin/stdout)
|
|
467
|
+
┌──────────────────▼──────────────────────────────────┐
|
|
468
|
+
│ Rust Proxy Engine │
|
|
469
|
+
│ ┌─────────┐ ┌─────────┐ ┌─────────┐ ┌──────────┐ │
|
|
470
|
+
│ │ TCP/TLS │ │ HTTP │ │ Route │ │ ACME │ │
|
|
471
|
+
│ │ Listener│ │ Reverse │ │ Matcher │ │ Cert Mgr │ │
|
|
472
|
+
│ │ │ │ Proxy │ │ │ │ │ │
|
|
473
|
+
│ └─────────┘ └─────────┘ └─────────┘ └──────────┘ │
|
|
474
|
+
│ ┌─────────┐ ┌─────────┐ ┌─────────┐ ┌──────────┐ │
|
|
475
|
+
│ │ Security│ │ Metrics │ │ Connec- │ │ NFTables │ │
|
|
476
|
+
│ │ Enforce │ │ Collect │ │ tion │ │ Mgr │ │
|
|
477
|
+
│ │ │ │ │ │ Tracker │ │ │ │
|
|
478
|
+
│ └─────────┘ └─────────┘ └─────────┘ └──────────┘ │
|
|
479
|
+
└──────────────────┬──────────────────────────────────┘
|
|
480
|
+
│ Unix Socket Relay
|
|
481
|
+
┌──────────────────▼──────────────────────────────────┐
|
|
482
|
+
│ TypeScript Socket Handler Server │
|
|
483
|
+
│ (for JS-defined socket handlers & dynamic routes) │
|
|
484
|
+
└─────────────────────────────────────────────────────┘
|
|
337
485
|
```
|
|
338
486
|
|
|
487
|
+
- **Rust Engine** handles all networking, TLS, HTTP proxying, connection management, security, and metrics
|
|
488
|
+
- **TypeScript** provides the npm API, configuration types, route helpers, validation, and socket handler callbacks
|
|
489
|
+
- **IPC** — JSON commands/events over stdin/stdout for seamless cross-language communication
|
|
490
|
+
- **Socket Relay** — a Unix domain socket server for routes requiring TypeScript-side handling (socket handlers, dynamic host/port functions)
|
|
491
|
+
|
|
339
492
|
## 🎯 Route Configuration Reference
|
|
340
493
|
|
|
341
494
|
### Match Criteria
|
|
342
495
|
|
|
343
496
|
```typescript
|
|
344
497
|
interface IRouteMatch {
|
|
345
|
-
ports: number | number[] |
|
|
346
|
-
domains?: string | string[];
|
|
347
|
-
path?: string;
|
|
348
|
-
clientIp?: string
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
customMatcher?: (context) => boolean; // Custom logic
|
|
498
|
+
ports: number | number[] | Array<{ from: number; to: number }>; // Port(s) to listen on
|
|
499
|
+
domains?: string | string[]; // 'example.com', '*.example.com'
|
|
500
|
+
path?: string; // '/api/*', '/users/:id'
|
|
501
|
+
clientIp?: string[]; // ['10.0.0.0/8', '192.168.*']
|
|
502
|
+
tlsVersion?: string[]; // ['TLSv1.2', 'TLSv1.3']
|
|
503
|
+
headers?: Record<string, string | RegExp>; // Match by HTTP headers
|
|
352
504
|
}
|
|
353
505
|
```
|
|
354
506
|
|
|
355
507
|
### Action Types
|
|
356
508
|
|
|
509
|
+
| Type | Description |
|
|
510
|
+
|------|-------------|
|
|
511
|
+
| `forward` | Proxy to one or more backend targets (with optional TLS, WebSocket, load balancing) |
|
|
512
|
+
| `socket-handler` | Custom socket handling function in TypeScript |
|
|
513
|
+
|
|
514
|
+
### Target Options
|
|
515
|
+
|
|
516
|
+
```typescript
|
|
517
|
+
interface IRouteTarget {
|
|
518
|
+
host: string | string[] | ((context: IRouteContext) => string);
|
|
519
|
+
port: number | 'preserve' | ((context: IRouteContext) => number);
|
|
520
|
+
tls?: { ... }; // Per-target TLS override
|
|
521
|
+
priority?: number; // Target priority
|
|
522
|
+
match?: ITargetMatch; // Sub-match within a route (by port, path, headers, method)
|
|
523
|
+
}
|
|
524
|
+
```
|
|
525
|
+
|
|
526
|
+
### TLS Options
|
|
527
|
+
|
|
357
528
|
```typescript
|
|
358
|
-
interface
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
// For 'redirect'
|
|
368
|
-
redirectUrl?: string; // With {domain}, {path}, {clientIp} templates
|
|
369
|
-
redirectCode?: number; // 301, 302, etc.
|
|
370
|
-
|
|
371
|
-
// For 'socket-handler'
|
|
372
|
-
socketHandler?: (socket, context) => void | Promise<void>;
|
|
373
|
-
|
|
374
|
-
// TLS options
|
|
375
|
-
tls?: {
|
|
376
|
-
mode: 'terminate' | 'passthrough' | 'terminate-and-reencrypt';
|
|
377
|
-
certificate: 'auto' | { key: string; cert: string };
|
|
529
|
+
interface IRouteTls {
|
|
530
|
+
mode: 'passthrough' | 'terminate' | 'terminate-and-reencrypt';
|
|
531
|
+
certificate?: 'auto' | {
|
|
532
|
+
key: string;
|
|
533
|
+
cert: string;
|
|
534
|
+
ca?: string;
|
|
535
|
+
keyFile?: string;
|
|
536
|
+
certFile?: string;
|
|
378
537
|
};
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
pingTimeout?: number;
|
|
538
|
+
acme?: {
|
|
539
|
+
email: string;
|
|
540
|
+
useProduction?: boolean;
|
|
541
|
+
challengePort?: number;
|
|
542
|
+
renewBeforeDays?: number;
|
|
385
543
|
};
|
|
544
|
+
versions?: string[];
|
|
545
|
+
ciphers?: string;
|
|
546
|
+
honorCipherOrder?: boolean;
|
|
547
|
+
sessionTimeout?: number;
|
|
386
548
|
}
|
|
387
549
|
```
|
|
388
550
|
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
### Certificate Issues
|
|
392
|
-
- ✅ Ensure domain points to your server
|
|
393
|
-
- ✅ Port 80 must be accessible for ACME challenges
|
|
394
|
-
- ✅ Check DNS propagation with `nslookup`
|
|
395
|
-
- ✅ Verify email in ACME configuration
|
|
551
|
+
### WebSocket Options
|
|
396
552
|
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
553
|
+
```typescript
|
|
554
|
+
interface IRouteWebSocket {
|
|
555
|
+
enabled: boolean;
|
|
556
|
+
pingInterval?: number; // ms between pings
|
|
557
|
+
pingTimeout?: number; // ms to wait for pong
|
|
558
|
+
maxPayloadSize?: number; // Maximum frame payload
|
|
559
|
+
subprotocols?: string[]; // Allowed subprotocols
|
|
560
|
+
allowedOrigins?: string[]; // CORS origins
|
|
561
|
+
}
|
|
562
|
+
```
|
|
402
563
|
|
|
403
|
-
###
|
|
404
|
-
- ✅ Use NFTables for high-traffic routes
|
|
405
|
-
- ✅ Enable connection pooling
|
|
406
|
-
- ✅ Adjust keep-alive settings
|
|
407
|
-
- ✅ Monitor with built-in metrics
|
|
564
|
+
### Load Balancing Options
|
|
408
565
|
|
|
409
|
-
### Debug Mode
|
|
410
566
|
```typescript
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
567
|
+
interface IRouteLoadBalancing {
|
|
568
|
+
algorithm: 'round-robin' | 'least-connections' | 'ip-hash';
|
|
569
|
+
healthCheck?: {
|
|
570
|
+
path: string;
|
|
571
|
+
interval: number; // ms
|
|
572
|
+
timeout: number; // ms
|
|
573
|
+
unhealthyThreshold: number;
|
|
574
|
+
healthyThreshold: number;
|
|
575
|
+
};
|
|
576
|
+
}
|
|
415
577
|
```
|
|
416
578
|
|
|
417
|
-
##
|
|
579
|
+
## 🛠️ Helper Functions Reference
|
|
418
580
|
|
|
419
|
-
|
|
581
|
+
All helpers are fully typed and return `IRouteConfig` or `IRouteConfig[]`:
|
|
420
582
|
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
583
|
+
```typescript
|
|
584
|
+
import {
|
|
585
|
+
// HTTP/HTTPS
|
|
586
|
+
createHttpRoute, // Plain HTTP route
|
|
587
|
+
createHttpsTerminateRoute, // HTTPS with TLS termination
|
|
588
|
+
createHttpsPassthroughRoute, // SNI passthrough (no termination)
|
|
589
|
+
createHttpToHttpsRedirect, // HTTP → HTTPS redirect
|
|
590
|
+
createCompleteHttpsServer, // HTTPS + redirect combo (returns IRouteConfig[])
|
|
591
|
+
|
|
592
|
+
// Load Balancing
|
|
593
|
+
createLoadBalancerRoute, // Multi-backend with health checks
|
|
594
|
+
createSmartLoadBalancer, // Dynamic domain-based backend selection
|
|
595
|
+
|
|
596
|
+
// API & WebSocket
|
|
597
|
+
createApiRoute, // API route with path matching
|
|
598
|
+
createApiGatewayRoute, // API gateway with CORS
|
|
599
|
+
createWebSocketRoute, // WebSocket-enabled route
|
|
600
|
+
|
|
601
|
+
// Custom Protocols
|
|
602
|
+
createSocketHandlerRoute, // Custom socket handler
|
|
603
|
+
SocketHandlers, // Pre-built handlers (echo, proxy, block, etc.)
|
|
604
|
+
|
|
605
|
+
// NFTables (Linux, requires root)
|
|
606
|
+
createNfTablesRoute, // Kernel-level packet forwarding
|
|
607
|
+
createNfTablesTerminateRoute, // NFTables + TLS termination
|
|
608
|
+
createCompleteNfTablesHttpsServer, // NFTables HTTPS + redirect combo
|
|
609
|
+
|
|
610
|
+
// Dynamic Routing
|
|
611
|
+
createPortMappingRoute, // Port mapping with context
|
|
612
|
+
createOffsetPortMappingRoute, // Simple port offset
|
|
613
|
+
createDynamicRoute, // Dynamic host/port via functions
|
|
614
|
+
|
|
615
|
+
// Security Modifiers
|
|
616
|
+
addRateLimiting, // Add rate limiting to any route
|
|
617
|
+
addBasicAuth, // Add basic auth to any route
|
|
618
|
+
addJwtAuth, // Add JWT auth to any route
|
|
619
|
+
|
|
620
|
+
// Route Utilities
|
|
621
|
+
mergeRouteConfigs, // Deep-merge two route configs
|
|
622
|
+
findMatchingRoutes, // Find routes matching criteria
|
|
623
|
+
findBestMatchingRoute, // Find best matching route
|
|
624
|
+
cloneRoute, // Deep-clone a route
|
|
625
|
+
generateRouteId, // Generate deterministic route ID
|
|
626
|
+
RouteValidator, // Validate route configurations
|
|
627
|
+
} from '@push.rocks/smartproxy';
|
|
628
|
+
```
|
|
430
629
|
|
|
431
630
|
## 📖 API Documentation
|
|
432
631
|
|
|
433
632
|
### SmartProxy Class
|
|
434
633
|
|
|
435
634
|
```typescript
|
|
436
|
-
class SmartProxy {
|
|
437
|
-
constructor(options:
|
|
438
|
-
|
|
635
|
+
class SmartProxy extends EventEmitter {
|
|
636
|
+
constructor(options: ISmartProxyOptions);
|
|
637
|
+
|
|
439
638
|
// Lifecycle
|
|
440
639
|
start(): Promise<void>;
|
|
441
640
|
stop(): Promise<void>;
|
|
442
|
-
|
|
443
|
-
// Route Management
|
|
641
|
+
|
|
642
|
+
// Route Management (atomic, mutex-locked)
|
|
444
643
|
updateRoutes(routes: IRouteConfig[]): Promise<void>;
|
|
445
|
-
|
|
446
|
-
removeRoute(routeName: string): Promise<void>;
|
|
447
|
-
findMatchingRoute(context: Partial<IRouteContext>): IRouteConfig | null;
|
|
448
|
-
|
|
644
|
+
|
|
449
645
|
// Port Management
|
|
450
646
|
addListeningPort(port: number): Promise<void>;
|
|
451
647
|
removeListeningPort(port: number): Promise<void>;
|
|
452
|
-
getListeningPorts(): number[]
|
|
453
|
-
|
|
648
|
+
getListeningPorts(): Promise<number[]>;
|
|
649
|
+
|
|
650
|
+
// Monitoring & Metrics
|
|
651
|
+
getMetrics(): IMetrics; // Sync — returns cached metrics adapter
|
|
652
|
+
getStatistics(): Promise<any>; // Async — queries Rust engine
|
|
653
|
+
|
|
454
654
|
// Certificate Management
|
|
455
|
-
|
|
456
|
-
renewCertificate(
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
655
|
+
provisionCertificate(routeName: string): Promise<void>;
|
|
656
|
+
renewCertificate(routeName: string): Promise<void>;
|
|
657
|
+
getCertificateStatus(routeName: string): Promise<any>;
|
|
658
|
+
getEligibleDomainsForCertificates(): string[];
|
|
659
|
+
|
|
660
|
+
// NFTables
|
|
661
|
+
getNfTablesStatus(): Promise<Record<string, any>>;
|
|
662
|
+
|
|
663
|
+
// Events
|
|
664
|
+
on(event: 'error', handler: (err: Error) => void): this;
|
|
461
665
|
}
|
|
462
666
|
```
|
|
463
667
|
|
|
464
|
-
###
|
|
668
|
+
### Configuration Options
|
|
465
669
|
|
|
466
|
-
|
|
670
|
+
```typescript
|
|
671
|
+
interface ISmartProxyOptions {
|
|
672
|
+
routes: IRouteConfig[]; // Required: array of route configs
|
|
673
|
+
|
|
674
|
+
// ACME/Let's Encrypt
|
|
675
|
+
acme?: {
|
|
676
|
+
email: string; // Contact email for Let's Encrypt
|
|
677
|
+
useProduction?: boolean; // Use production servers (default: false)
|
|
678
|
+
port?: number; // HTTP-01 challenge port (default: 80)
|
|
679
|
+
renewThresholdDays?: number; // Days before expiry to renew (default: 30)
|
|
680
|
+
autoRenew?: boolean; // Enable auto-renewal (default: true)
|
|
681
|
+
certificateStore?: string; // Directory to store certs (default: './certs')
|
|
682
|
+
renewCheckIntervalHours?: number; // Renewal check interval (default: 24)
|
|
683
|
+
};
|
|
684
|
+
|
|
685
|
+
// Custom certificate provisioning
|
|
686
|
+
certProvisionFunction?: (domain: string) => Promise<ICert | 'http01'>;
|
|
687
|
+
certProvisionFallbackToAcme?: boolean; // Fall back to ACME on failure (default: true)
|
|
688
|
+
|
|
689
|
+
// Global defaults
|
|
690
|
+
defaults?: {
|
|
691
|
+
target?: { host: string; port: number };
|
|
692
|
+
security?: { ipAllowList?: string[]; ipBlockList?: string[]; maxConnections?: number };
|
|
693
|
+
};
|
|
694
|
+
|
|
695
|
+
// PROXY protocol
|
|
696
|
+
proxyIPs?: string[]; // Trusted proxy IPs
|
|
697
|
+
acceptProxyProtocol?: boolean; // Accept PROXY protocol headers
|
|
698
|
+
sendProxyProtocol?: boolean; // Send PROXY protocol to targets
|
|
699
|
+
|
|
700
|
+
// Timeouts
|
|
701
|
+
connectionTimeout?: number; // Backend connection timeout (default: 30s)
|
|
702
|
+
initialDataTimeout?: number; // Initial data/SNI timeout (default: 60s)
|
|
703
|
+
socketTimeout?: number; // Socket inactivity timeout (default: 1h)
|
|
704
|
+
maxConnectionLifetime?: number; // Max connection lifetime (default: 24h)
|
|
705
|
+
inactivityTimeout?: number; // Inactivity timeout (default: 4h)
|
|
706
|
+
gracefulShutdownTimeout?: number; // Shutdown grace period (default: 30s)
|
|
707
|
+
|
|
708
|
+
// Connection limits
|
|
709
|
+
maxConnectionsPerIP?: number; // Per-IP connection limit (default: 100)
|
|
710
|
+
connectionRateLimitPerMinute?: number; // Per-IP rate limit (default: 300/min)
|
|
711
|
+
|
|
712
|
+
// Keep-alive
|
|
713
|
+
keepAliveTreatment?: 'standard' | 'extended' | 'immortal';
|
|
714
|
+
keepAliveInactivityMultiplier?: number; // (default: 6)
|
|
715
|
+
extendedKeepAliveLifetime?: number; // (default: 7 days)
|
|
716
|
+
|
|
717
|
+
// Metrics
|
|
718
|
+
metrics?: {
|
|
719
|
+
enabled?: boolean;
|
|
720
|
+
sampleIntervalMs?: number;
|
|
721
|
+
retentionSeconds?: number;
|
|
722
|
+
};
|
|
723
|
+
|
|
724
|
+
// Behavior
|
|
725
|
+
enableDetailedLogging?: boolean; // Verbose connection logging
|
|
726
|
+
enableTlsDebugLogging?: boolean; // TLS handshake debug logging
|
|
727
|
+
|
|
728
|
+
// Rust binary
|
|
729
|
+
rustBinaryPath?: string; // Custom path to the Rust binary
|
|
730
|
+
}
|
|
731
|
+
```
|
|
732
|
+
|
|
733
|
+
### NfTablesProxy Class
|
|
734
|
+
|
|
735
|
+
A standalone class for managing nftables NAT rules directly (Linux only, requires root):
|
|
467
736
|
|
|
468
737
|
```typescript
|
|
469
|
-
import {
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
738
|
+
import { NfTablesProxy } from '@push.rocks/smartproxy';
|
|
739
|
+
|
|
740
|
+
const nftProxy = new NfTablesProxy({
|
|
741
|
+
fromPort: [80, 443],
|
|
742
|
+
toPort: [8080, 8443],
|
|
743
|
+
toHost: 'backend-server',
|
|
744
|
+
protocol: 'tcp',
|
|
745
|
+
preserveSourceIP: true,
|
|
746
|
+
ipv6Support: true,
|
|
747
|
+
useIPSets: true,
|
|
748
|
+
qos: {
|
|
749
|
+
enabled: true,
|
|
750
|
+
maxRate: '1gbps'
|
|
751
|
+
}
|
|
752
|
+
});
|
|
753
|
+
|
|
754
|
+
await nftProxy.start(); // Apply nftables rules
|
|
755
|
+
const status = await nftProxy.getStatus();
|
|
756
|
+
await nftProxy.stop(); // Remove rules
|
|
488
757
|
```
|
|
489
758
|
|
|
759
|
+
## 🐛 Troubleshooting
|
|
760
|
+
|
|
761
|
+
### Certificate Issues
|
|
762
|
+
- ✅ Ensure domain DNS points to your server
|
|
763
|
+
- ✅ Port 80 must be accessible for ACME HTTP-01 challenges
|
|
764
|
+
- ✅ Check DNS propagation with `dig` or `nslookup`
|
|
765
|
+
- ✅ Verify the email in ACME configuration is valid
|
|
766
|
+
- ✅ Use `getCertificateStatus('route-name')` to check cert state
|
|
767
|
+
|
|
768
|
+
### Connection Problems
|
|
769
|
+
- ✅ Check route priorities (higher number = matched first)
|
|
770
|
+
- ✅ Verify security rules aren't blocking legitimate traffic
|
|
771
|
+
- ✅ Test with `curl -v` for detailed connection output
|
|
772
|
+
- ✅ Enable debug logging with `enableDetailedLogging: true`
|
|
773
|
+
|
|
774
|
+
### Rust Binary Not Found
|
|
775
|
+
SmartProxy searches for the Rust binary in this order:
|
|
776
|
+
1. `SMARTPROXY_RUST_BINARY` environment variable
|
|
777
|
+
2. Platform-specific npm package (`@push.rocks/smartproxy-linux-x64`, etc.)
|
|
778
|
+
3. Local dev build (`./rust/target/release/rustproxy`)
|
|
779
|
+
4. System PATH (`rustproxy`)
|
|
780
|
+
|
|
781
|
+
Set `rustBinaryPath` in options to override.
|
|
782
|
+
|
|
783
|
+
### Performance Tuning
|
|
784
|
+
- ✅ Use NFTables forwarding for high-traffic routes (Linux only)
|
|
785
|
+
- ✅ Enable connection keep-alive where appropriate
|
|
786
|
+
- ✅ Use `getMetrics()` and `getStatistics()` to identify bottlenecks
|
|
787
|
+
- ✅ Adjust `maxConnectionsPerIP` and `connectionRateLimitPerMinute` based on your workload
|
|
788
|
+
- ✅ Use `passthrough` TLS mode when backend can handle TLS directly
|
|
789
|
+
|
|
790
|
+
## 🏆 Best Practices
|
|
791
|
+
|
|
792
|
+
1. **📝 Use Helper Functions** — They provide sensible defaults and prevent common mistakes
|
|
793
|
+
2. **🎯 Set Route Priorities** — More specific routes should have higher priority values
|
|
794
|
+
3. **🔒 Enable Security** — Always use IP filtering and rate limiting for public-facing services
|
|
795
|
+
4. **📊 Monitor Metrics** — Use the built-in metrics to catch issues early
|
|
796
|
+
5. **🔄 Certificate Monitoring** — Set up alerts before certificates expire
|
|
797
|
+
6. **🛑 Graceful Shutdown** — Always call `proxy.stop()` for clean connection termination
|
|
798
|
+
7. **✅ Validate Routes** — Use `RouteValidator.validateRoutes()` to catch config errors before deployment
|
|
799
|
+
8. **🔀 Atomic Updates** — Use `updateRoutes()` for hot-reloading routes (mutex-locked, no downtime)
|
|
800
|
+
9. **🎮 Use Socket Handlers** — For protocols beyond HTTP, implement custom socket handlers instead of fighting the proxy model
|
|
801
|
+
|
|
490
802
|
## License and Legal Information
|
|
491
803
|
|
|
492
|
-
This repository contains open-source code
|
|
804
|
+
This repository contains open-source code licensed under the MIT License. A copy of the license can be found in the [LICENSE](./LICENSE) file.
|
|
493
805
|
|
|
494
806
|
**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.
|
|
495
807
|
|
|
496
808
|
### Trademarks
|
|
497
809
|
|
|
498
|
-
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.
|
|
810
|
+
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.
|
|
811
|
+
|
|
812
|
+
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.
|
|
499
813
|
|
|
500
814
|
### Company Information
|
|
501
815
|
|
|
502
|
-
Task Venture Capital GmbH
|
|
503
|
-
Registered at District
|
|
816
|
+
Task Venture Capital GmbH
|
|
817
|
+
Registered at District Court Bremen HRB 35230 HB, Germany
|
|
504
818
|
|
|
505
|
-
For any legal inquiries or
|
|
819
|
+
For any legal inquiries or further information, please contact us via email at hello@task.vc.
|
|
506
820
|
|
|
507
|
-
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.
|
|
821
|
+
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.
|