fbi-proxy 1.4.0 → 1.5.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/README.md +37 -154
- package/package.json +9 -4
- package/release/fbi-proxy-linux-arm64 +0 -0
- package/release/fbi-proxy-linux-x64 +0 -0
- package/release/fbi-proxy-macos-arm64 +0 -0
- package/release/fbi-proxy-macos-x64 +0 -0
- package/release/fbi-proxy-windows-arm64.exe +0 -0
- package/release/fbi-proxy-windows-x64.exe +0 -0
- package/ts/buildFbiProxy.ts +1 -1
- package/ts/cli.ts +51 -47
- package/ts/{dRun.ts → dSpawn.ts} +9 -8
- package/ts/downloadCaddy.ts +15 -22
package/README.md
CHANGED
|
@@ -1,184 +1,67 @@
|
|
|
1
1
|
# fbi-proxy
|
|
2
2
|
|
|
3
|
-
FBI
|
|
3
|
+
FBI-Proxy provides easy HTTPS access to your local services with intelligent domain routing.
|
|
4
4
|
|
|
5
|
-
##
|
|
5
|
+
## Usage
|
|
6
6
|
|
|
7
|
-
```
|
|
8
|
-
#
|
|
9
|
-
|
|
7
|
+
```sh
|
|
8
|
+
# launch
|
|
9
|
+
bunx fbi-proxy
|
|
10
10
|
|
|
11
|
-
#
|
|
12
|
-
|
|
11
|
+
# expose to LAN
|
|
12
|
+
bunx fbi-proxy --host 0.0.0.0 --port=2432
|
|
13
13
|
|
|
14
|
-
#
|
|
15
|
-
|
|
16
|
-
```
|
|
14
|
+
# with caddy, forwarding *.fbi.com
|
|
15
|
+
bunx fbi-proxy --caddy=fbi.com
|
|
17
16
|
|
|
18
|
-
|
|
17
|
+
# or
|
|
18
|
+
docker start
|
|
19
|
+
```
|
|
19
20
|
|
|
20
|
-
###
|
|
21
|
+
### Routing Examples
|
|
21
22
|
|
|
22
23
|
```bash
|
|
23
|
-
#
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
# Build Rust proxy binary
|
|
27
|
-
bun run build:rs
|
|
24
|
+
# Port forwarding
|
|
25
|
+
https://3000.fbi.com → localhost:3000
|
|
26
|
+
https://8080.fbi.com → localhost:8080
|
|
28
27
|
|
|
29
|
-
#
|
|
30
|
-
|
|
28
|
+
# Host--Port forwarding
|
|
29
|
+
https://api--3001.fbi.com → api:3001
|
|
30
|
+
https://db--5432.fbi.com → db:5432
|
|
31
31
|
|
|
32
|
-
#
|
|
33
|
-
|
|
32
|
+
# Subdomain routing (with Host header)
|
|
33
|
+
https://admin.app.fbi.com → app:80 (Host: admin)
|
|
34
|
+
https://v2.api.fbi.com → api:80 (Host: v2)
|
|
34
35
|
|
|
35
|
-
#
|
|
36
|
-
|
|
36
|
+
# Direct host forwarding
|
|
37
|
+
https://myserver.fbi.com → myserver:80
|
|
37
38
|
```
|
|
38
39
|
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
The FBI Proxy consists of three main components:
|
|
42
|
-
|
|
43
|
-
- **TypeScript CLI** (`ts/cli.ts`): Orchestrates the entire system, manages Caddy and Rust proxy processes
|
|
44
|
-
- **Rust Proxy Server** (`proxy.rs`): High-performance HTTP/WebSocket proxy using Hyper framework
|
|
45
|
-
- **Caddy Server**: Handles TLS termination, SSL certificates, and domain routing
|
|
46
|
-
|
|
47
|
-
### How It Works
|
|
40
|
+
WebSocket connections are supported for all patterns.
|
|
48
41
|
|
|
49
|
-
|
|
50
|
-
2. **Caddy** receives incoming HTTPS requests and forwards them to the Rust proxy
|
|
51
|
-
3. **Rust Proxy** intelligently routes requests based on hostname patterns
|
|
52
|
-
|
|
53
|
-
## Development Workflow
|
|
54
|
-
|
|
55
|
-
### First Time Setup:
|
|
42
|
+
## Development
|
|
56
43
|
|
|
57
44
|
```bash
|
|
58
|
-
#
|
|
45
|
+
# Install dependencies
|
|
59
46
|
bun install
|
|
60
47
|
|
|
61
|
-
#
|
|
48
|
+
# Start development
|
|
62
49
|
bun run dev
|
|
63
|
-
```
|
|
64
|
-
|
|
65
|
-
### Daily Development:
|
|
66
|
-
|
|
67
|
-
```bash
|
|
68
|
-
# Development with hot reload for both Caddy and Rust
|
|
69
|
-
bun run dev
|
|
70
|
-
|
|
71
|
-
# Or run individual components:
|
|
72
|
-
bun run dev:caddy # Start Caddy with file watching
|
|
73
|
-
bun run dev:rs # Start Rust proxy with bacon (auto-rebuild)
|
|
74
|
-
```
|
|
75
|
-
|
|
76
|
-
### Production Deployment:
|
|
77
|
-
|
|
78
|
-
```bash
|
|
79
|
-
bun run build # Build optimized binaries
|
|
80
|
-
bun run start # Start production services
|
|
81
|
-
```
|
|
82
|
-
|
|
83
|
-
## Prerequisites
|
|
84
|
-
|
|
85
|
-
- **Bun**: JavaScript runtime and package manager (install from https://bun.sh/)
|
|
86
|
-
- **Rust**: For building the proxy binary (install from https://rustup.rs/)
|
|
87
|
-
- **Caddy**: Automatically downloaded by the CLI if not found
|
|
88
|
-
|
|
89
|
-
## Routing Features
|
|
90
50
|
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
### 1. Port Forwarding
|
|
94
|
-
|
|
95
|
-
- `https://3000.fbi.com` → `http://localhost:3000`
|
|
96
|
-
- `https://8080.fbi.com` → `http://localhost:8080`
|
|
97
|
-
|
|
98
|
-
### 2. Host--Port Forwarding
|
|
99
|
-
|
|
100
|
-
- `https://localhost--3000.fbi.com` → `http://localhost:3000`
|
|
101
|
-
- `https://myserver--8080.fbi.com` → `http://myserver:8080`
|
|
102
|
-
|
|
103
|
-
### 3. Subdomain Hoisting
|
|
104
|
-
|
|
105
|
-
- `https://api.myserver.fbi.com` → `http://myserver:80` (with Host: `api`)
|
|
106
|
-
- `https://admin.localhost.fbi.com` → `http://localhost:80` (with Host: `admin`)
|
|
107
|
-
|
|
108
|
-
### 4. Direct Host Forwarding
|
|
109
|
-
|
|
110
|
-
- `https://myserver.fbi.com` → `http://myserver:80`
|
|
111
|
-
- `https://localhost.fbi.com` → `http://localhost:80`
|
|
112
|
-
|
|
113
|
-
### WebSocket Support
|
|
114
|
-
|
|
115
|
-
All routing patterns support WebSocket connections with automatic upgrade handling.
|
|
116
|
-
|
|
117
|
-
## Configuration
|
|
118
|
-
|
|
119
|
-
### Environment Variables
|
|
120
|
-
|
|
121
|
-
```env
|
|
122
|
-
FBIHOST="fbi.com" # Default domain (configurable via --fbihost)
|
|
123
|
-
FBIPROXY_PORT="24306" # Internal proxy port (auto-assigned)
|
|
124
|
-
```
|
|
125
|
-
|
|
126
|
-
### CLI Options
|
|
127
|
-
|
|
128
|
-
```bash
|
|
129
|
-
bun run ts/cli.ts --help
|
|
130
|
-
|
|
131
|
-
Options:
|
|
132
|
-
--help Show help message
|
|
133
|
-
--fbihost Set the FBI host (default: fbi.com)
|
|
134
|
-
```
|
|
135
|
-
|
|
136
|
-
## Service Configuration Examples
|
|
137
|
-
|
|
138
|
-
Create custom service mappings by modifying the routing logic or using the built-in patterns:
|
|
139
|
-
|
|
140
|
-
```bash
|
|
141
|
-
# Direct port access
|
|
142
|
-
https://3000.fbi.com # → localhost:3000
|
|
143
|
-
https://5173.fbi.com # → localhost:5173 (Vite dev server)
|
|
144
|
-
https://8000.fbi.com # → localhost:8000 (VS Code server)
|
|
145
|
-
|
|
146
|
-
# Named services with custom ports
|
|
147
|
-
https://api--3001.fbi.com # → api:3001
|
|
148
|
-
https://db--5432.fbi.com # → db:5432
|
|
149
|
-
|
|
150
|
-
# Subdomain routing
|
|
151
|
-
# Subdomain routing
|
|
152
|
-
https://admin.app.fbi.com # → app:80 with Host: admin
|
|
153
|
-
https://v2.api.fbi.com # → api:80 with Host: v2
|
|
51
|
+
# Or production
|
|
52
|
+
bun run build && bun run start
|
|
154
53
|
```
|
|
155
54
|
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
### Rust Proxy Implementation (`proxy.rs`)
|
|
159
|
-
|
|
160
|
-
The Rust proxy server implements the following routing logic:
|
|
161
|
-
|
|
162
|
-
1. **Number Host Detection**: Pure numeric hosts (e.g., `3000`) route to `localhost:3000`
|
|
163
|
-
2. **Double-Dash Parsing**: `host--port` format routes to `host:port`
|
|
164
|
-
3. **Subdomain Hoisting**: Multi-level domains route to the root domain with subdomain as Host header
|
|
165
|
-
4. **Default Port 80**: Simple hostnames default to port 80
|
|
166
|
-
|
|
167
|
-
### TypeScript CLI (`ts/cli.ts`)
|
|
168
|
-
|
|
169
|
-
The CLI manages:
|
|
55
|
+
### Prerequisites
|
|
170
56
|
|
|
171
|
-
-
|
|
172
|
-
-
|
|
173
|
-
-
|
|
174
|
-
- Hot reloading during development
|
|
57
|
+
- **Bun**: https://bun.sh/
|
|
58
|
+
- **Rust**: https://rustup.rs/
|
|
59
|
+
- **Caddy**: Auto-downloaded if not found
|
|
175
60
|
|
|
176
|
-
###
|
|
61
|
+
### Configuration
|
|
177
62
|
|
|
178
|
-
-
|
|
179
|
-
-
|
|
180
|
-
- Reverse proxy configuration with header manipulation
|
|
181
|
-
- Support for wildcard subdomain routing
|
|
63
|
+
- Default domain: `fbi.com` (change with `--fbihost`)
|
|
64
|
+
- Internal proxy port: Auto-assigned to `FBIPROXY_PORT`
|
|
182
65
|
|
|
183
66
|
## License
|
|
184
67
|
|
package/package.json
CHANGED
|
@@ -15,6 +15,7 @@
|
|
|
15
15
|
"semantic-release": "^22.0.0"
|
|
16
16
|
},
|
|
17
17
|
"peerDependencies": {
|
|
18
|
+
"@snomiao/caddy-baron": "^3.0.4",
|
|
18
19
|
"typescript": "^5"
|
|
19
20
|
},
|
|
20
21
|
"files": [
|
|
@@ -24,10 +25,13 @@
|
|
|
24
25
|
"dist",
|
|
25
26
|
"Caddyfile"
|
|
26
27
|
],
|
|
28
|
+
"trustedDependencies": [
|
|
29
|
+
"@radically-straightforward/caddy"
|
|
30
|
+
],
|
|
27
31
|
"dependencies": {
|
|
28
|
-
"@
|
|
32
|
+
"@radically-straightforward/caddy": "^2.0.6",
|
|
29
33
|
"bun": "^1.2.19",
|
|
30
|
-
"
|
|
34
|
+
"execa": "^9.6.0",
|
|
31
35
|
"from-node-stream": "^0.1.0",
|
|
32
36
|
"get-port": "^7.1.0",
|
|
33
37
|
"hot-memo": "^1.1.1",
|
|
@@ -38,6 +42,7 @@
|
|
|
38
42
|
"sflow": "^1.23.0",
|
|
39
43
|
"ts-toolbelt": "^9.6.0",
|
|
40
44
|
"tsa-composer": "^1.0.0",
|
|
45
|
+
"yargs": "^17.7.2",
|
|
41
46
|
"zx": "^8.7.2"
|
|
42
47
|
},
|
|
43
48
|
"scripts": {
|
|
@@ -55,7 +60,7 @@
|
|
|
55
60
|
"start:js": "node dist/cli.js",
|
|
56
61
|
"start:caddy": "./caddy run",
|
|
57
62
|
"start:rs": "./target/release/fbi-proxy",
|
|
58
|
-
"prepare": "husky
|
|
63
|
+
"prepare": "husky"
|
|
59
64
|
},
|
|
60
65
|
"lint-staged": {
|
|
61
66
|
"*.{ts,js}": [
|
|
@@ -68,5 +73,5 @@
|
|
|
68
73
|
"bin": {
|
|
69
74
|
"fbi-proxy": "dist/cli.js"
|
|
70
75
|
},
|
|
71
|
-
"version": "1.
|
|
76
|
+
"version": "1.5.0"
|
|
72
77
|
}
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
package/ts/buildFbiProxy.ts
CHANGED
|
@@ -2,7 +2,7 @@ import fsp from "fs/promises";
|
|
|
2
2
|
import { existsSync } from "fs";
|
|
3
3
|
import { getProxyFilename } from "./getProxyFilename";
|
|
4
4
|
import { copyFile } from "fs/promises";
|
|
5
|
-
import { $ } from "./
|
|
5
|
+
import { $ } from "./dSpawn";
|
|
6
6
|
import { mkdir } from "fs/promises";
|
|
7
7
|
|
|
8
8
|
if (import.meta.main) {
|
package/ts/cli.ts
CHANGED
|
@@ -1,49 +1,43 @@
|
|
|
1
1
|
#!/usr/bin/env bun
|
|
2
2
|
import getPort from "get-port";
|
|
3
3
|
import hotMemo from "hot-memo";
|
|
4
|
-
import minimist from "minimist";
|
|
5
4
|
import path from "path";
|
|
6
|
-
import
|
|
5
|
+
import yargs from "yargs";
|
|
6
|
+
import { hideBin } from "yargs/helpers";
|
|
7
7
|
import { buildFbiProxy } from "./buildFbiProxy";
|
|
8
|
-
import { $ } from "./
|
|
8
|
+
import { $ } from "./dSpawn";
|
|
9
9
|
import { downloadCaddy } from "./downloadCaddy";
|
|
10
|
+
import { execa } from "execa";
|
|
10
11
|
|
|
11
12
|
process.chdir(path.resolve(__dirname, "..")); // Change to project root directory
|
|
12
13
|
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
14
|
+
// Parse command line arguments with yargs
|
|
15
|
+
const argv = await yargs(hideBin(process.argv))
|
|
16
|
+
.option("fbihost", {
|
|
17
|
+
type: "string",
|
|
18
|
+
default: "fbi.com",
|
|
19
|
+
description: "Set the FBI host",
|
|
20
|
+
})
|
|
21
|
+
.option("caddy", {
|
|
22
|
+
type: "boolean",
|
|
23
|
+
default: false,
|
|
24
|
+
description: "Start Caddy server",
|
|
25
|
+
})
|
|
26
|
+
.option("dev", {
|
|
27
|
+
alias: "d",
|
|
28
|
+
type: "boolean",
|
|
29
|
+
default: false,
|
|
30
|
+
description: "Run in development mode",
|
|
31
|
+
})
|
|
32
|
+
.help().argv;
|
|
19
33
|
|
|
20
|
-
console.log("
|
|
34
|
+
console.log("Preparing Binaries");
|
|
21
35
|
|
|
22
|
-
|
|
23
|
-
const
|
|
24
|
-
default: {
|
|
25
|
-
dev: false,
|
|
26
|
-
d: false,
|
|
27
|
-
fbihost: "fbi.com", // Default FBI host
|
|
28
|
-
},
|
|
29
|
-
alias: {
|
|
30
|
-
dev: "d",
|
|
31
|
-
},
|
|
32
|
-
boolean: ["dev", "d", "help"],
|
|
33
|
-
});
|
|
34
|
-
// console.log(argv);
|
|
35
|
-
if (argv.help) {
|
|
36
|
-
console.log(`Usage: fbi-proxy [options]
|
|
37
|
-
Options:
|
|
38
|
-
--help Show this help message
|
|
39
|
-
--fbihost Set the FBI host (default: fbi.com)
|
|
40
|
-
`);
|
|
41
|
-
process.exit(0);
|
|
42
|
-
}
|
|
36
|
+
const FBIHOST = argv.fbihost;
|
|
37
|
+
const FBIPROXY_PORT = String(await getPort({ port: 2432 }));
|
|
43
38
|
|
|
44
|
-
const FBIHOST = argv.fbihost || "fbi.com"; // Default FBI host
|
|
45
|
-
const FBIPROXY_PORT = String(await getPort({ port: 24306 }));
|
|
46
39
|
const proxyProcess = await hotMemo(async () => {
|
|
40
|
+
const proxy = await buildFbiProxy();
|
|
47
41
|
console.log("Starting Rust proxy server");
|
|
48
42
|
const p = $.opt({
|
|
49
43
|
env: {
|
|
@@ -59,25 +53,35 @@ const proxyProcess = await hotMemo(async () => {
|
|
|
59
53
|
return p;
|
|
60
54
|
});
|
|
61
55
|
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
56
|
+
let caddyProcess: any = null;
|
|
57
|
+
|
|
58
|
+
// Only start Caddy if --caddy flag is passed
|
|
59
|
+
if (argv.caddy) {
|
|
60
|
+
const caddy = await downloadCaddy();
|
|
61
|
+
caddyProcess = await hotMemo(async () => {
|
|
62
|
+
const p = $.opt({
|
|
63
|
+
env: {
|
|
64
|
+
...process.env,
|
|
65
|
+
FBIPROXY_PORT, // Rust proxy server port
|
|
66
|
+
FBIHOST,
|
|
67
|
+
},
|
|
68
|
+
})`${caddy} run`.process;
|
|
69
|
+
p.on("exit", (code) => {
|
|
70
|
+
console.log(`Caddy exited with code ${code}`);
|
|
71
|
+
process.exit(code || 0);
|
|
72
|
+
});
|
|
73
|
+
return p;
|
|
73
74
|
});
|
|
74
|
-
|
|
75
|
-
});
|
|
75
|
+
}
|
|
76
76
|
|
|
77
77
|
console.log("all done");
|
|
78
78
|
// show process pids
|
|
79
79
|
console.log(`Proxy server PID: ${proxyProcess.pid}`);
|
|
80
|
-
|
|
80
|
+
if (caddyProcess) {
|
|
81
|
+
console.log(`Caddy server PID: ${caddyProcess.pid}`);
|
|
82
|
+
} else {
|
|
83
|
+
console.log("Caddy server not started (use --caddy to start it)");
|
|
84
|
+
}
|
|
81
85
|
|
|
82
86
|
const exit = () => {
|
|
83
87
|
console.log("Shutting down...");
|
package/ts/{dRun.ts → dSpawn.ts}
RENAMED
|
@@ -15,17 +15,18 @@ type DRunProc = Promise<{
|
|
|
15
15
|
process: ChildProcess;
|
|
16
16
|
};
|
|
17
17
|
|
|
18
|
-
const
|
|
18
|
+
const dSpawn = ({
|
|
19
19
|
cwd = process.cwd(),
|
|
20
20
|
env = process.env as Record<string, string>,
|
|
21
21
|
} = {}) =>
|
|
22
22
|
tsaComposer(
|
|
23
|
-
|
|
24
|
-
|
|
23
|
+
// slot is un dividable
|
|
24
|
+
(slot: string | { raw: string }) =>
|
|
25
|
+
typeof slot === "string"
|
|
25
26
|
? {
|
|
26
|
-
raw: String(
|
|
27
|
+
raw: String(slot), // todo: escape quotes
|
|
27
28
|
}
|
|
28
|
-
:
|
|
29
|
+
: slot,
|
|
29
30
|
(...slots): DRunProc => {
|
|
30
31
|
try {
|
|
31
32
|
// TODO: parse slots for quotes
|
|
@@ -106,7 +107,7 @@ const dRun = ({
|
|
|
106
107
|
},
|
|
107
108
|
);
|
|
108
109
|
|
|
109
|
-
export const $ = Object.assign(
|
|
110
|
-
opt:
|
|
111
|
-
cwd: (path: string) =>
|
|
110
|
+
export const $ = Object.assign(dSpawn(), {
|
|
111
|
+
opt: dSpawn,
|
|
112
|
+
cwd: (path: string) => dSpawn({ cwd: path }),
|
|
112
113
|
});
|
package/ts/downloadCaddy.ts
CHANGED
|
@@ -1,31 +1,24 @@
|
|
|
1
1
|
import { existsSync } from "fs";
|
|
2
|
-
import
|
|
3
|
-
import { $ } from "./dRun";
|
|
2
|
+
import { $ } from "./dSpawn";
|
|
4
3
|
|
|
5
|
-
|
|
6
|
-
//
|
|
7
|
-
const
|
|
4
|
+
if (import.meta.main) {
|
|
5
|
+
// if this file is run directly, download caddy
|
|
6
|
+
const caddy = await downloadCaddy();
|
|
7
|
+
console.log(`Caddy downloaded to: ${caddy}`);
|
|
8
|
+
process.exit(0);
|
|
9
|
+
}
|
|
8
10
|
|
|
9
|
-
|
|
11
|
+
export async function downloadCaddy() {
|
|
12
|
+
// use pwdCaddy if already downloaded
|
|
13
|
+
const pwdCaddy = "./node_modules/.bin/caddy";
|
|
10
14
|
if (existsSync(pwdCaddy)) return pwdCaddy;
|
|
11
15
|
|
|
12
|
-
// or use system caddy if installed, run `caddy --version` to check
|
|
16
|
+
// // or use system caddy if installed, run `caddy --version` to check
|
|
13
17
|
if (await $`caddy --version`.catch(() => false)) {
|
|
14
18
|
return "caddy";
|
|
15
19
|
}
|
|
16
20
|
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
// @ts-ignore
|
|
22
|
-
await import("../node_modules/caddy-baron/index.mjs");
|
|
23
|
-
|
|
24
|
-
if (!existsSync(pwdCaddy))
|
|
25
|
-
throw new Error(
|
|
26
|
-
"Failed to download Caddy. Please install Caddy manually or check your network connection.",
|
|
27
|
-
);
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
return pwdCaddy;
|
|
31
|
-
};
|
|
21
|
+
throw new Error(
|
|
22
|
+
"Failed to download Caddy. Please install Caddy manually or check your network connection.",
|
|
23
|
+
);
|
|
24
|
+
}
|